ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

YOLOv5环境配置到训练自己的数据集:版本匹配与报错排查全流程

YOLOv5环境配置到训练自己的数据集:版本匹配与报错排查全流程 “装了两天最后发现是 PyTorch 和 CUDA 版本对不上”——这句话我在实验室、在群里、在评论区至少见过几十次。YOLOv5 这个东西本身的代码结构非常干净train.py一行命令就能把训练跑起来真正劝退新手的从来都不是模型原理而是前面那段看起来无聊透顶的 YOLOv5 环境配置。显卡驱动、CUDA、cuDNN、Anaconda、PyTorch、Python 版本六个东西互相咬着错一个就报一串看不懂的英文。这篇东西就是写给完全没碰过深度学习环境的人的从一台干净的电脑开始到把自己的数据集训练出best.pt中间每一步为什么这么做、哪一步最容易出事、出事了怎么自己排查我按顺序全写清楚。不管你最后是想做水果识别、车牌号识别还是单纯想跑通一次训练流程交作业跟着走一遍就行。有显卡的用显卡没显卡的租一台云 GPU 也能跑。1. YOLOv5 环境配置为什么总在第一步就卡死人1.1 六个版本号互相咬合这才是真正的难点先把这个事情的复杂度讲清楚你才知道为什么别人给的命令你复制粘贴就是不行。YOLOv5 跑起来需要一条完整的链路显卡硬件 → 显卡驱动 → CUDA → PyTorch → Python → YOLOv5 代码依赖。这条链上的每个环节都有版本要求而且不是随便搭配都行。显卡驱动版本决定了你能用的最高 CUDA 版本CUDA 版本决定了你能装哪个版本的 PyTorchPyTorch 版本又要求 Python 在某个区间内YOLOv5 的requirements.txt里还有一堆包numpy、opencv-python、pillow、matplotlib、tqdm、pyyaml、requests、scipy、thop 等对 numpy 和 Python 版本有隐性要求。新手最常见的错误是“看到哪个教程就照抄”结果 A 教程写的是torch1.7.1cu110B 教程写的是torch2.0.1cu118你电脑上的驱动是两年前的老版本装完torch.cuda.is_available()返回False然后你就懵了。这里有个必须纠正的认知误区pip 安装的 PyTorch 是自带 CUDA runtime 的你不需要单独去 NVIDIA 官网下载安装 CUDA Toolkit也不需要手动配 cuDNN。很多教程让你去装 CUDA Toolkit 11.3、再把 cuDNN 的文件拷到 CUDA 目录里那套流程是给编译源码或者用 TensorFlow 老版本的人准备的。YOLOv5 pip 版 PyTorch 这条路线里多装 CUDA Toolkit 反而容易造成版本冲突因为系统里出现了两套 CUDA 库动态链接的时候加载错了就报DLL load failed或者undefined symbol。所以你真正需要准备的只有两样东西一张 NVIDIA 显卡 一个足够新的显卡驱动。其余的交给 conda 和 pip。1.2 一张表把版本搭配说清楚先确认你的显卡驱动支持到哪个 CUDA 版本。打开命令行敲nvidia-smi输出右上角有一行CUDA Version: 12.1之类的字样。注意这个数字表示你的驱动“最高能支持”CUDA 12.1不是说你已经装了 CUDA 12.1很多人在这里理解错然后满世界找“我什么时候装的 CUDA”。拿到这个数字后对照下面的表格选 PyTorch驱动显示的 CUDA Version推荐 PyTorch 版本pip 安装后缀备注11.0 及以上torch 1.8 ~ 1.10cu111老驱动能用的最稳组合11.4 及以上torch 1.11 / 1.12cu113YOLOv5 v6.0 时代的主流11.7 及以上torch 1.13 / 2.0cu117兼容性最广的一档11.8 及以上torch 2.0 / 2.1cu118目前装得最多的组合12.1 及以上torch 2.1cu121新卡新驱动直接上“及以上”这三个字很关键驱动是向下兼容的。你的驱动支持 CUDA 12.1那装 cu118 的 PyTorch 完全没问题反过来驱动只支持 11.4你硬装 cu118 的版本torch.cuda.is_available()就会给你一个冷冷的False。如果你实在懒得算用最土但最有效的办法打开 PyTorch 官网的 Get Started 页面在选项里选你的系统、pip、Python 版本、CUDA 版本它会把完整命令生成给你。这个页面上的组合都是官方验证过的出错概率最低。1.3 为什么一定要用 conda 建虚拟环境我见过太多人所有东西都往 base 环境里塞半年后 numpy 版本打架PyTorch 莫名其妙导入失败只能重装 Anaconda。这种事完全没必要经历一次。虚拟环境的价值在于隔离。你可以在同一台电脑上建三个环境一个跑 YOLOv5一个跑 YOLOv8一个跑别的框架各自锁死自己的依赖版本互不干扰。哪天某个环境搞崩了conda remove -n 环境名 --all删掉重建五分钟的事不会连累其他项目。建环境的时候有个小细节环境名别用中文别带空格。我用yolov5这个名字简单直接。另外创建环境时把 Python 版本一起定死不要事后在环境里升级 Python那是给自己找麻烦。2. 从一台干净电脑到 detect.py 跑通的完整路径2.1 创建 conda 虚拟环境并激活假设你已经装好了 Anaconda 或者更轻量的 Miniconda打开 Anaconda PromptWindows或者终端Linux/macOS执行conda create -n yolov5 python3.9 -y conda activate yolov5Python 版本我建议3.9或者3.10。选 3.9 的理由是它对 PyTorch 1.8 到 2.1 全系列都友好覆盖面最广选 3.10 也没问题但再往上3.11、3.12就有些依赖包会装不上或者编译失败新手别去踩。至于 3.7、3.8YOLOv5 官方现在要求Python3.8.03.8 还能用但很多新包已经不支持了也不推荐。激活成功后命令行前面会出现(yolov5)的前缀。这个前缀很重要它告诉你接下来所有操作都在这个环境里装包不会污染全局。如果你后面发现命令行没有这个前缀说明环境掉了重新conda activate yolov5一下。提醒Windows 上关闭终端再打开环境是需要重新激活的。这不是 bug是 conda 的默认行为。2.2 装 PyTorch这条命令决定后面顺不顺以上面表格里的 cu118 torch 2.0 为例在激活的yolov5环境里执行pip install torch2.0.1 torchvision0.15.2 --index-url https://download.pytorch.org/whl/cu118装完之后必须验证别急着往下走python -c import torch; print(torch.__version__); print(torch.cuda.is_available()); print(torch.cuda.get_device_name(0))期望看到三行输出版本号、True、你的显卡型号。如果第二行是False先别慌按这个顺序排查你的电脑是不是根本没有 NVIDIA 显卡或者只有集显。没有 N 卡的话只能跑 CPU训练会慢到让你怀疑人生这时候建议租云 GPU。装的包是不是 CPU 版本。用pip list | grep torchLinux/macOS或pip list | findstr torchWindows看看版本号后缀2.0.1cpu就是 CPU 版得卸了重装。显卡驱动太老。回nvidia-smi看看版本和 PyTorch 要求的 CUDA 版本对不上的话先升级驱动。这三步走完基本能解决 95% 的False问题。2.3 下载 YOLOv5 源码与安装依赖有了 Git 直接克隆没有 Git 就去 GitHub 上下载 zip 包解压git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt关于版本选择有个实用建议YOLOv5 的 v6.0、v6.2、v7.0 这三个 tag 是社区里资料最多、教程最多的。如果你后面要查问题用最新的 main 分支有时会遇到“别人的教程里根本没有这个文件”的尴尬。想切换版本git checkout v7.0requirements.txt里的包装完之后我强烈建议再手动确认一下 numpy 和 opencvpip install numpy1.23.5 pip install opencv-python4.6.0.66这两个包是版本冲突的高发区。numpy 2.x 出来之后不少老版本的 YOLOv5 代码会出现np.int之类的兼容性问题锁一个 1.23.x 能避开一大片坑。opencv 选 4.6 左右的版本兼容性最好。2.4 下载预训练权重跑通第一次推理YOLOv5 提供了 n/s/m/l/x 五个尺寸的模型参数量从 1.9M 到 86M 不等。第一次一定用 s不要用 l 或 x。s 版本在 640 分辨率下单张推理速度很快显存占用小拿来做流程验证最合适。权重文件可以直接从官方 release 页面下载也可以在跑detect.py的时候让代码自动下载。国内网络环境下自动下载经常卡住所以我习惯手动下载yolov5s.pt放到项目根目录。然后python detect.py --weights yolov5s.pt --source data/images --conf 0.25K.这是整个流程里最爽的一步。跑完之后终端会打印每张图的检测结果和耗时结果图片默认保存在runs/detect/exp/下面打开看一眼人、车、狗被框出来了说明环境彻底通了。如果这一步跑通了后面 90% 的环境问题都不会再出现了。因为推理和训练用的是同一套 CUDA、同一套 PyTorch推理能跑说明底层链路是好的。所以我一直建议新手把“跑通 detect.py”作为环境配置的验收标准而不是“装完包就算完事”。3. 自己的数据集怎么组织才不会被 train.py 嫌弃3.1 LabelImg 标注以及标注里那些细节坑YOLOv5 用的是 YOLO 格式的 txt 标签每个 txt 对应一张图每行一个目标格式是类别编号 中心点x 中心点y 宽 高后面四个数字都是归一化到 0~1 的。比如0 0.523 0.441 0.212 0.334就表示第 0 类的目标中心点在图片宽度的 52.3%、高度的 44.1% 处框宽占整图 21.2%框高占 33.4%。用 LabelImg 标注的话有几个坑我必须提前说启动 LabelImg 时左侧工具栏要手动切换到 YOLO 模式默认的 PascalVOC 生成的是 xml格式不对。标注之前先在设置里勾上“自动保存”并且把默认保存目录设成和图片同一个文件夹。不然后面你会得到一堆只有图片没有标签的“半成品”。类别名的拼写必须完全一致。apple和Apple在 YOLO 里是两个不同的类混着标就会出现“我明明只标了 3 类训练日志说找到 4 类”的诡异情况。一个目标框要贴紧物体边缘不要框得太松也不要太小。框得太松模型学到的是背景框得太小模型学不到完整的目标。这是个手工活练习几十张之后就熟练了。如果一张图里有多个目标必须全部标完不能只标一个剩下的不管。YOLO 训练时把没标的部分当背景处理漏标会造成严重的误检。标注完成后正常你会得到一个classes.txt里面是类别列表。这个文件的顺序就是类别编号的顺序第 0 行是 0 类第 1 行是 1 类。后面写data.yaml的时候要跟它保持一致否则会出现“标签编号和类别名对不上”的问题。3.2 目录结构必须严格镜像对应YOLOv5 对目录结构有硬性要求最简洁的版本是这样的mydata/ ├── images/ │ ├── train/ │ │ ├── 001.jpg │ │ └── 002.jpg │ └── val/ │ ├── 003.jpg │ └── 004.jpg └── labels/ ├── train/ │ ├── 001.txt │ └── 002.txt └── val/ ├── 003.txt └── 004.txt核心规则images 和 labels 的目录结构必须完全平行图片和 txt 必须同名除了扩展名。images/train/001.jpg对应的就是labels/train/001.txt。YOLOv5 在训练时会自动把images路径里的/images/替换成/labels/再把扩展名换成.txt去找标签。如果你的目录不是这个结构它就会找不到标签然后给你一句No labels found。还有一个隐藏在后台的机制训练前 YOLOv5 会把所有图片路径和标签信息缓存成train.cache和val.cache两个文件放在 labels 目录旁边。这个缓存在大数据集上能大幅提速但它同时也是最容易坑人的东西——你改了标签缓存没更新训练用的还是老数据。所以记住一句话动过标签或者重新划分过数据集先去把.cache文件删掉。3.3 data.yaml 每个字段到底在说什么新建一个data/mydata.yamltrain: ../mydata/images/train val: ../mydata/images/val nc: 3 names: [apple, banana, orange]四个字段逐个解释train和val训练集和验证集的图片目录不是标签目录。YOLOv5 会自己推导出标签路径。ncnumber of classes类别数量。注意是不含背景类的纯目标类别数。很多人从别的框架转过来会把背景算作一类结果设成 4训练时直接报索引越界。names类别名列表顺序必须和标注时的编号严格对应。路径写法上有个高频错误YOLOv5 里相对路径是相对train.py所在目录计算的不是相对 yaml 文件。所以我一般直接写绝对路径省得纠结train: /home/user/mydata/images/train val: /home/user/mydata/images/valWindows 上用绝对路径记得把反斜杠转义或者改成正斜杠D:/mydata/images/train这样写就行。数据集大小的经验值每个类别至少 100~200 张带标注的图类别之间数量尽量均衡。如果某一类只有 10 张模型基本学不会训练日志里那个类的 mAP 会一直是 0 或者接近 0。数据量实在少的话多用数据增强YOLOv5 默认就开了 mosaic、HSV 抖动、随机缩放等同时把 epochs 调大一点、把模型换成 s 或 n 这种小模型减少过拟合。4. train.py 参数逐个拆开讲别抄命令抄得不明不白4.1 五个必改参数其余保持默认一条典型的训练命令python train.py --img 640 --batch 16 --epochs 100 --data data/mydata.yaml --weights yolov5s.pt --project runs/train --name exp1逐个说--img 640训练时的输入分辨率。640 是 YOLOv5 的标准尺寸也是预训练权重的默认尺寸。改小比如 416能省显存但掉精度改大比如 1280提精度但显存翻着涨。新手就用 640。--batch 16一个批次塞多少张图。这个参数直接决定显存占用是后面 OOM 报错的第一嫌疑人。一般来说 8G 显存用 8 或 1612G 用 16 或 3224G 可以上 64。显存不够就降这个数没有别的办法。--epochs 100整个数据集过 100 遍。小数据集几百张建议 200~300中等数据集 100~200 够用。看 loss 曲线不再下降就可以提前停。--data指向你写好的 yaml。--weights yolov5s.pt从预训练权重开始训练迁移学习。这一步极其重要不要写成--weights 从头训。从头训需要的数据量和算力是个人玩家扛不住的用预训练权重能让模型在几百张图上就有不错的效果。4.2 Windows 下 --workers 和 batch size 的显存账--workers控制数据加载的进程数默认 8。这个参数在 Linux 上一般不用管但在 Windows 上经常出事。Windows 下如果--workers设得太大或者你的数据集放在机械硬盘上很容易报RuntimeError: DataLoader worker (pid(s) ...) exited unexpectedly。遇到这个错第一反应就是把--workers改成 0 或者 2。改成 0 意味着数据加载在主进程里做慢一点但绝对稳。等训练能跑起来了再慢慢往上加找一个不报错的临界值。关于 batch size 和显存的关系给个粗略的估算参照模型imgszbatch显存占用近似建议显卡yolov5n640322~3 GB6G 及以上yolov5s640164~6 GB8G 及以上yolov5m640168~10 GB12G 及以上yolov5l6401612~16 GB16G 及以上yolov5x640816~20 GB24G这只是个大概。实际占用还跟数据集图片尺寸、增强策略有关。训练启动后马上敲一次nvidia-smi看显存实际用了多少这比任何估算都准。还有一个常被忽略的参数是--device。多卡机器上可以用--device 0,1指定用哪几张卡。单卡就--device 0。4.3 训练日志里哪些数字值得盯训练开始后终端会刷新一行一行的进度格式大概是Epoch gpu_mem box_loss obj_loss cls_loss Instances Size 1/100 5.2G 0.0721 0.0312 0.0145 32 640gpu_mem显存占用看看有没有贴着上限跑贴着跑就要小心后面崩。box_loss边界框回归损失反映框得准不准。应该随着训练下降。obj_loss目标置信度损失反映“这里有没有东西”判断得对不对。cls_loss分类损失反映“这是什么东西”判断得对不对。判断训练是否正常最简单的标准就是这三条 loss 是不是在稳定下降。如果训练几十个 epoch 后 box_loss 还在 0.05 以上不下来可能是标注质量有问题如果 obj_loss 一直很高可能有大量漏标如果 cls_loss 不降反升大概率是类别不平衡或者学习率太大。验证阶段会打印mAP0.5和mAP0.5:0.95。前者表示 IoU 阈值取 0.5 时的平均精度后者是 0.5 到 0.95 每隔 0.05 取一次再平均后者更严格。所有训练结果都存在runs/train/exp1/下面其中weights/best.pt验证集上表现最好的权重。weights/last.pt最后一个 epoch 的权重。results.csv每个 epoch 的所有指标可以用 Excel 打开画图。results.png自动生成的损失和指标曲线图最直观。confusion_matrix.png混淆矩阵能看出哪些类别容易混。labels.jpg标注框的分布统计能看出目标大小、位置分布是否合理。labels.jpg这张图新手经常忽略但它特别有用。如果图上显示大量框挤在图片正中间说明你的数据集里目标位置太单一模型泛化能力会差如果框的宽高分布差异很大说明目标尺度跨度大可能需要考虑多尺度训练。4.4 断点续训怎么操作训练被中断断电、手滑关窗口、显存崩了之后不用从头再来YOLOv5 支持续训python train.py --resume runs/train/exp1/weights/last.pt注意--resume后面跟的必须是含有优化器状态的last.ptbest.pt是保存模型权重的格式续训时用它不会恢复学习率调度和优化器动量效果会打折扣。5. 训练过程中真正会遇到的报错与排查链路5.1 CUDA out of memory从降 batch 到降 imgsz这是出现频率最高的报错全称RuntimeError: CUDA out of memory. Tried to allocate ...。排查顺序应该是这样的先降 batch size。这是最直接有效的--batch 16改成--batch 8还不行改 4。改到能跑为止。再考虑降 imgsz。640 改 512 或者 416显存占用会明显下降但小目标的检测精度会掉。换小一号的模型。yolov5m 换成 yolov5s参数量少一半以上显存压力小很多。检查是不是别的东西占了显存。跑一次nvidia-smi看看除了你的训练进程还有没有别的 Python 进程赖着不走。这种情况在 Jupyter 里特别常见——改了代码重新运行旧的进程没释放。用kill -9 PIDLinux或者在任务管理器里结束进程Windows。确认没有同时跑两个训练。有人为了“加快速度”开两个终端跑两次训练结果互相抢显存两个都崩。还有一个隐蔽的坑验证阶段的显存占用通常比训练阶段更高因为验证时 batch size 会被自动放大默认是训练 batch 的两倍左右。所以有时候训练跑了几个 epoch 都好好的一到验证就 OOM。修改方法是在train.py里找到验证的 batch 设置或者直接降低整体 batch size。5.2 DLL load failed 与版本错位的识别方法Windows 上最常见的另一个报错是ImportError: DLL load failed while importing _C: 找不到指定的模块这个错误 99% 是 PyTorch 和 CUDA 版本不匹配造成的。排查步骤打印版本信息python -c import torch; print(torch.__version__)看后缀是不是cuXXX。如果后缀是cpu而你想用 GPU或者后缀是cu118但你的驱动只支持 11.4那就是这里的问题。检查驱动nvidia-smi看 CUDA Version。卸载重装pip uninstall torch torchvision然后装匹配版本。另一个可能的原因是系统 PATH 里有多个 CUDA 相关的 dll 在打架尤其是你之前手动装过 CUDA Toolkit 的情况。如果对当初装过什么没把握最干净的办法是新建一个 conda 环境重装别在旧环境里折腾。还有一个长得有点像但原因完全不同的错误OMP: Error #15: Initializing libiomp5md.dll, but found libiomp5md.dll already initialized.这个跟 CUDA 无关是 Intel OpenMP 库的重复初始化问题。临时解决方案是设置环境变量# Windows set KMP_DUPLICATE_LIB_OKTRUE # Linux / macOS export KMP_DUPLICATE_LIB_OKTRUE或者在代码最前面加import os os.environ[KMP_DUPLICATE_LIB_OK] TRUE不过要说明的是这个只是让程序不崩根本原因是环境里装了多份 OpenMP 库。如果是长期使用的环境建议还是查一下是哪个包装进来的。5.3 No labels found 与缓存文件的坑报错长这样AssertionError: No labels found in /path/to/labels/train.cache或者更温和的一个警告WARNING: No labels found in /path/to/labels/train, can not train without labels.排查链路确认 images 和 labels 目录结构是否镜像对应。这是最容易出问题的地方尤其是在 Windows 上从别处拷数据集路径大小写、斜杠方向都可能出问题。确认图片和标签是否同名。001.jpg必须对应001.txt。如果图片是001.JPG大写标签是001.txt大多数情况下没问题但保险起见统一成小写。删除.cache文件重试。这一步能解决一半以上的诡异情况。缓存文件里存的是旧的文件列表你新加了图片它不知道。检查标签文件是不是空的。有时候 LabelImg 保存出问题txt 是 0 字节。用脚本扫一遍把空文件列出来。我写过一个特别简单的检查脚本几行代码就能定位大部分问题import os from pathlib import Path img_dir Path(mydata/images/train) lbl_dir Path(mydata/labels/train) img_stems {p.stem for p in img_dir.glob(*.jpg)} lbl_stems {p.stem for p in lbl_dir.glob(*.txt)} print(图片没有对应标签:, sorted(img_stems - lbl_stems)[:20]) print(标签没有对应图片:, sorted(lbl_stems - img_stems)[:20]) print(空标签文件:, [p.name for p in lbl_dir.glob(*.txt) if p.stat().st_size 0][:20])跑一次三类问题一目了然。5.4 GPU 占用为 0、训练慢得像蜗牛数据加载瓶颈怎么查现象是nvidia-smi显示 GPU 利用率只有 10%~30%显存占用也不高但一个 epoch 跑得特别久。这是典型的数据加载成了瓶颈。GPU 在等 CPU 把图片读出来、解码、做增强。排查方向调--workers。设得太小比如 0数据加载全在主进程GPU 大把时间在等。在 Linux 上可以设到 8 甚至 16Windows 上保守一点从 4 开始试。数据集别放机械硬盘。放 SSD 上速度差异非常明显。图片别太大。如果你原始的图片是 4000x3000 的高清图即使训练用 640读取和解码的开销仍然很大。建议预处理阶段就把图片统一缩放到长边 1280 左右既保留细节又不浪费 IO。检查是不是在做特别重的增强。mosaic、mixup 这些增强如果开得太猛会明显增加 CPU 负担。另外一个容易误导人的点GPU 利用率是瞬时采样值波动很大偶尔看到 0% 不一定是问题。真正该看的是一个 epoch 的总耗时以及nvidia-smi连续看几秒的平均值。5.5 页面文件太小与 Windows 共享内存问题Windows 上还有一类报错OSError: [WinError 1455] 页面文件太小无法完成操作。这个和显卡显存没关系是系统虚拟内存不够。PyTorch 的 DataLoader 在多进程模式下会通过共享内存在进程间传递数据这个共享内存走的是系统虚拟内存。解决方法是手动调大虚拟内存右键“此电脑” → 属性 → 高级系统设置 → 性能设置 → 高级 → 虚拟内存 → 更改取消自动管理把初始大小和最大值都设成物理内存的 1.5~2 倍比如 16G 内存就设 24576 MB 到 32768 MB。改完需要重启。或者简单粗暴地把--workers改成 0绕开多进程共享内存机制。代价是数据加载慢一点但对于中小数据集完全能接受。6. 训练跑完之后验证、推理和导出部署6.1 用 val.py 独立评估看清每个类的表现训练结束时的那次验证是快速的如果想认真评估单独跑一次python val.py --weights runs/train/exp1/weights/best.pt --data data/mydata.yaml --img 640 --task val输出会给出每个类别的 P精确率、R召回率、mAP0.5、mAP0.5:0.95。看这几个数字有个经验判断如果某个类别的 P 很高比如 0.95但 R 很低比如 0.3说明模型很保守只敢在特别有把握的时候才报漏检多。这时候可以降低推理时的置信度阈值或者给这个类补充更多训练数据。如果 P 低 R 高说明模型太激进什么都敢报误检多。可以提高置信度阈值或者检查这一类是不是有大量标注错误的样本。如果 mAP0.5 有 0.8 以上但 mAP0.5:0.95 只有 0.4说明框的位置还不够精准可以试试加大 imgsz 或者在标注时把框贴得更紧。runs/val/目录下会生成PR_curve.png、F1_curve.png、confusion_matrix.png这几张图比数字更能说明问题值得花时间看。6.2 best.pt 和 last.pt 到底选哪个这是个高频问题。简单结论默认用 best.pt除非你怀疑 best.pt 过拟合了。best.pt是在验证集上 mAP 最高的那一版。但因为验证集和训练集来自同一个分布再加上小数据集上波动大有时候 best.pt 是“运气好”的产物。有个简单的判断方法训练结束后把 best.pt 和 last.pt 分别在验证集上跑一次val.py如果两者 mAP 差距在 1~2 个点以内用 best.pt如果 best.pt 明显高出一大截说明验证集可能太小导致波动这时候考虑重新划分数据集。还有一个更靠谱的做法留一份真正独立的测试集不参与训练也不参与验证只用它来最终评估。这能给你一个相对客观的泛化能力估计。6.3 detect.py 批量推理与阈值调优推理自己的图片python detect.py --weights runs/train/exp1/weights/best.pt --source my_test_images --conf-thres 0.25 --iou-thres 0.45 --save-txt --save-conf--source可以是单张图、整个文件夹、视频文件也可以填0调用摄像头。--conf-thres置信度阈值。默认 0.25调高减少误检调低减少漏检。--iou-thresNMS 的 IoU 阈值。当两个框重叠度超过这个值保留分数高的那个。默认 0.45目标密集的场景可以调低一点比如 0.3避免把相邻目标合并掉。--save-txt把检测结果保存成 YOLO 格式的 txt方便后续二次处理。--save-conf在 txt 里带上置信度分数。这两个阈值没有放之四海皆准的答案必须针对你的场景调。拿 100 张测试图从 0.1 试到 0.6每次都统计一下漏检和误检的数量找到平衡点。这个过程看着笨但比任何理论推导都管用。6.4 导出 ONNX 与其他格式的注意事项想在 C、移动端或者其他框架里用需要把 pt 转成通用格式python export.py --weights runs/train/exp1/weights/best.pt --include onnx --img 640 --batch 1有个坑一定要说清楚训练时用的--img和导出时的--img必须一致。如果训练用 640导出用 1280导出过程可能不报错但在别的框架里推理结果会明显不对。同样--batch 1导出的模型只能处理单张图要批量推理就得用对应的 batch 导出或者用动态 batch。还有一个更隐蔽的问题预处理必须对齐。YOLOv5 推理时的预处理包含 letterbox保持宽高比缩放并填充灰边、BGR 转 RGB、归一化除以 255、HWC 转 CHW 这几个步骤。你在别的框架里部署时只要漏掉或者顺序搞错任意一步检测结果就会离谱。如果部署后效果不对第一件事就是拿同一张图把 Python 端和部署端的预处理中间结果逐层打印出来对比。7. 几个能省下大半天时间的实操经验聊完了整个流程说几个我踩过之后才明白的点。关于环境最省时间的做法不是修是重建。环境问题排查到半小时还没头绪直接conda remove -n yolov5 --all重建一个往往比继续 debug 快。前提是你把安装命令记下来了——所以我建议把整个流程写成一个setup.sh或者一个 markdown 笔记重建的时候复制粘贴就行。关于数据集花在标注上的时间永远不亏。我见过太多人为了赶进度几百张图两小时标完框都是随手拉的最后训练出来 mAP 死活上不去回头重标一遍花的时间更多。标注这一关慢就是快。先跑通小流程再上大数据集。拿到一个新数据集先挑 50 张图做一个迷你版数据集把data.yaml配好用--epochs 10跑一遍确认整条链路没问题。确认之后再换成完整数据集跑正式训练。这样做的好处是如果配置有问题你 5 分钟就能发现而不是等到正式训练跑了 3 小时之后才报错。训练日志的第一屏一定要认真看。YOLOv5 启动时会打印一堆信息用的什么设备、检测到多少个类别、每个类多少张图、预训练权重加载了多少层。这里面藏着很多线索比如“每个类多少张图”能立刻暴露类别不平衡的问题“加载了多少层”如果不是 100% 就说明预训练权重和模型结构对不上。很多人直接跳过这一屏然后在训练崩了之后一脸茫然。最后一个小技巧把runs/目录按项目分开放。train.py的--project参数可以指定输出根目录我习惯写成--project runs/fruit或者--project runs/license_plate这样--name写日期。跑十几次实验之后你会庆幸自己当初这么做了——不然全堆在runs/train/exp1到runs/train/exp37里想找三周前那个效果最好的权重只能一个个点进去看。至于训练本身其实没什么玄学数据够、标注准、参数合理剩下的交给时间和显卡。真正难的是把前面那一整套环境理顺而这件事跑通一次之后就不会再难了。
返回列表