干了几年图像相关的东西,经常有朋友拿着YOLOv5的代码问我:“这玩意儿到底怎么跑起来?为什么我照着网上的教程走了一遍,不是报错就是结果全绿框框?”我特别理解这种状态。YOLOv5作为目前目标检测领域最常用的开源框架之一,功能确实强大,但正因为强大,很多人拿到手就乱试——今天换个参数、明天改个网络层,结果越搞越玄,最后“从入门到入狱”。这篇笔记是我自己从零跑通YOLOv5全流程的经验汇总,覆盖基本功能使用流程、训练自己的数据集,以及我最想强调的部分:每个关键参数背后的逻辑和坑。适合刚接触目标检测、想用YOLOv5解决实际问题的同学,也能给已经跑通代码、但卡在训练细节上的朋友一点参考。
1. 环境搭建:先把“坑”填平再上车
1.1 为什么建议用Anaconda虚拟环境
我见过太多人直接往系统Python里装torch、装opencv,没过多久就发现某个库把另一个库的版本顶掉了。最典型的冲突就是numpy版本:YOLOv5要求numpy小于某个版本,而你另一个项目需要新numpy,两边打架,最后谁也跑不起来。
所以我强烈建议第一步先用Anaconda创建独立虚拟环境。这相当于给项目单独开一间“房间”,互不干扰。手动创建一个新环境其实很简单:
conda create -n yolov5 python=3.8 -y conda activate yolov5为什么选Python 3.8而不是最新的3.11?因为PyTorch和很多第三方库的预编译包对3.8的兼容性最稳定。虽然现在新版本PyTorch已经支持更高Python,但在YOLOv5项目里,3.8是经过大量人验证过不会出幺蛾子的版本。如果你用的是PyTorch 2.x,Python 3.9或3.10也可以,但别一上来就追最新。
创建好环境后记得在终端确认:python -V,确保你已经在虚拟环境里。这一步看似简单,但很多人后面报错的根本原因就是环境串了,明明在A环境装的包,却在B环境里运行代码。
1.2 PyTorch和CUDA的版本关系怎么定
PyTorch的安装命令会直接影响后面能不能用GPU训练。这里有个常见误区:以为装了NVIDIA驱动就等于能用GPU。驱动只是底层的“许可”,实际干活靠的是PyTorch调用的CUDA版本。
先确认你的显卡驱动支持什么CUDA版本,直接在终端执行:
nvidia-smi看右上角“CUDA Version”,比如显示12.1,说明驱动最高支持CUDA 12.1。然后去PyTorch官网选对应版本安装。判断是否装上GPU版,可以用一行代码验证:
import torch print(torch.cuda.is_available())如果返回True,说明GPU环境正常;如果返回False,大概率是安装的PyTorch是CPU版,或者在CPU环境下运行。我有个朋友在这步卡了一个晚上,最后发现他用pip装torch时,系统默认选了CPU版本,因为他安装的时候没指定CUDA版本号。
显卡显存也是重要参数。如果显卡只有6G显存(比如GTX 1660),训练时batch size建议从8起步,图片尺寸用640,别一上来就想着用1080P大图训练,显存一不够,程序直接报CUDA out of memory。
1.3 装依赖时最容易翻车的几个点
YOLOv5项目目录下有个requirements.txt,装依赖的常规操作是:
pip install -r requirements.txt但直接在裸环境里跑这个,经常遇到两个问题:一是下载超时,二是部分包需要特定版本。先建议换国内镜像源,能省下大量时间:
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple你可能会问:为什么用国内镜像不违规不安全?这是正规的Python包镜像服务,也是常用的国内加速方式——它和官网源内容一致,只是网络距离近、速度快。
装依赖时最常遇到的是ipython和pyqt5这类包的安装时间很长,尤其是pyqt5,动辄几百MB。如果只是训练和推理,不需要跑标注工具,其实pyqt5这类GUI依赖可以暂时不装。我一般建议按需安装,不要一股脑全装完。另一个常见报错是安装某些包时提示需要编译环境,这种基本都是Python版本太新导致的,换回3.8就能解决。
2. 基本功能使用流程:拿到权重先跑通一次
2.1 下载代码和权重文件
YOLOv5的完整代码都在GitHub仓库里,进入官方仓库后点击“Code”按钮下载zip包,或者用git命令:
git clone https://github.com/ultralytics/yolov5.git cd yolov5通过这种方式拿到的代码是官方源仓库,直接解压或克隆都能用。代码目录里比较关键的有:detect.py(推理)、train.py(训练)、val.py(验证)、data/(数据集配置)、models/(模型结构)、runs/(输出结果)。
权重文件的获取方式要和代码版本对应。你可以在仓库的README页面找到对应版本的权重下载链接,通常提供yolov5s.pt、yolov5m.pt、yolov5l.pt、yolov5x.pt这几档。其中yolov5s最轻量、速度最快,适合先跑通流程;yolov5x精度高但显存占用大。如果你只是测试流程是否通畅,直接下载yolov5s.pt即可。
我遇到过一些朋友从网上随便下载了一个权重文件,结果代码是v6.0版本、权重是v5.0的,直接报错。所以这里多提醒一句:权重版本和代码版本的匹配很重要。拿到代码后可以先查看版本信息,再找对应权重,官方仓库的Release页面会把每个版本的权重列清楚。
2.2 detect.py 参数逐个说清楚
跑通推理是检验环境是否装好的最快方式。使用默认的测试图片:
python detect.py --weights yolov5s.pt --source data/images/bus.jpg这条命令的含义是用yolov5s.pt这个权重文件,去检测bus.jpg图片中的目标。运行完会在runs/detect/exp目录下生成带检测框的结果图。如果能看到人、巴士等目标被框出来,说明环境已经跑通了。
detect.py里最常用的参数我整理过一张表,每次调试前都逐一确认:
| 参数 | 作用 | 常用示例 |
|---|---|---|
| --weights | 指定权重文件 | --weights yolov5s.pt |
| --source | 指定检测来源,支持图片、视频、文件夹、摄像头 | --source data/images/ |
| --conf-thres | 置信度阈值,低于该值的目标被过滤,默认0.25 | --conf-thres 0.4 |
| --iou-thres | 交并比阈值,用于去重重叠框,默认0.45 | --iou-thres 0.5 |
| --device | 指定运行设备,cpu或显卡编号 | --device 0 |
| --classes | 只检测指定类别 | --classes 0 2 5 |
| --save-txt | 保存检测框坐标到txt文件 | --save-txt |
| --project | 修改结果保存路径 | --project my_runs |
| --name | 修改当前实验名称 | --name test_01 |
其中置信度阈值是最常调的参数。如果你发现漏检严重,可以把conf-thres往下调,调到0.1试试,但代价是会出现很多误报框。iou-thres则是控制两个重叠框是否合并的指标,如果同一目标出现多个框,调大iou-thres可以压掉重复框。
2.3 图片、视频、摄像头三种测法
图片检测直接给图片路径即可,也可以指定一个文件夹让它批量检测。视频检测直接把source指定成视频文件路径,它会逐帧推理并输出带框的视频。摄像头检测更简单,source填0表示调用本机默认摄像头:
python detect.py --weights yolov5s.pt --source 0三种输入方式背后其实走的是同一条推理链路,只是数据源不同。我第一次拿摄像头测的时候,发现画面掉帧明显,这是因为模型推理速度没跟上视频帧率。解决方案有两个方向:换更小的权重(yolov5s换成yolov5n),或者跳过某些帧再检测(比如每隔一帧检测一次)。
这里插一个非常有用的实测经验:当你只想检测特定物体时,比如在室内只关心人,不关心杯子、椅子,加上--classes 0能显著减少误检。因为默认权重训练于COCO数据集,包含80类目标,如果不限制类别,模型会努力把每一个物体都挑出来,反而容易出现低置信度的误报框,干扰最终结果。
3. 训练自己的数据集:从标注到出权重全流程
3.1 采集和整理图片:数量与类别的平衡
跑通默认权重只是“会走路”,训练自己的数据集才是真正“跑起来”。训练前的图片采集决定了模型性能的天花板。图片数量没有绝对标准,但有个经验值:每个类别至少200到500张图片。如果做工业级应用,每类1000张以上更稳妥。
图片尺寸不需要统一手动裁剪,YOLOv5会在训练时自动缩放。但图片质量一定要把关:模糊的、曝光过度的、目标占比过小的图片,能删就删。我做过一个水果识别项目,最初训练集里有大量隔着塑料袋拍的模糊橘子照片,模型学到的特征全是塑料袋纹理,换到真实场景直接失效。这类数据放在训练集里就是噪音,不如没有。
图片的来源也值得警惕。网络爬图虽然方便,但图片尺寸、清晰度、目标的姿态分布可能和你的实际场景差异很大。最理想的做法是从实际部署场景中采集不同时间段、不同光照、不同角度的图片。这样训练出来的模型才接地气。
3.2 使用LabelImg做YOLO格式标注
目标检测的标注方式有很多流派:VOC格式是xml文件,YOLO格式是txt文本文件,COCO是json文件。YOLOv5训练时读取的是txt标注文件,所以我们要把标注结果保存成YOLO格式。
标注工具我用得最顺手的是LabelImg,用pip安装:
pip install labelimg然后在虚拟环境中启动:
labelimg打开图片文件夹,选择PascalVOC格式(默认)还是YOLO格式。我的建议是:直接选YOLO格式保存,因为YOLOv5只认这种。不过要注意,LabelImg的YOLO格式保存界面和PascalVOC的操作略有不同,需要先点击打开目录、再点击打开标注列表,图源要选中“YOLO”。每画一个框标注一个类别,然后点击保存,会在图片同目录下生成同名txt文件。
YOLO格式的txt内容长这样,每一行对应一个目标:
0 0.53125 0.46875 0.2375 0.3125这五个数字的含义分别是:类别id(从0开始)、归一化后的中心点x坐标、中心点y坐标、归一化后的框宽、框高。你需要知道这一行规则,后面排查标签错误时会很有用。
标注是纯人工活,也是最容易出错的环节。我踩过的坑是:有些图片漏标了目标,导致训练时模型把“该框的地方”学成了背景。所以一个简单的自查方法:标注完一批图后,用LabelImg的“Next/Prev”把图片重新过一遍,确认每个目标都被框到了。
3.3 写data.yaml和调模型参数
标注完成后的目录结构建议这样组织,YOLOv5官方也推荐这个结构:
datasets/ └── mydata/ ├── images/ │ ├── train/ # 训练图片 │ └── val/ # 验证图片 ├── labels/ │ ├── train/ # 训练标注txt │ └── val/ # 验证标注txt └── data.yaml # 数据配置文件train和val图片数量比例建议8:2或9:1,不要把所有图片都拿去做训练。验证集的作用是检查模型有没有过拟合、泛化能力有没有达到预期。没有验证集的训练就是盲人摸象。
data.yaml是训练时的关键配置,内容如下:
path: ../datasets/mydata # 数据集根目录 train: images/train # 训练图片目录 val: images/val # 验证图片目录 nc: 2 # 类别数 names: ['cat', 'dog'] # 类别名称,顺序和标注id对应path字段尤其重要。它建议使用相对于项目所在目录的路径,或者绝对路径。很多新手在这里填错,导致训练时报错“train dataset not found”。如果报这个错,优先检查path和train这两个字段是否正确拼接成了实际存在目录。
3.4 训练命令与结果文件解释
确认数据和配置文件无误后,就可以开始训练了:
python train.py --data data.yaml --weights yolov5s.pt --epochs 100 --batch-size 16 --img 640 --device 0这条命令的含义是:读取data.yaml配置,加载yolov5s预训练权重作为初始权重,训练100个epoch,每个批次16张图片,输入尺寸640x640。预训练权重本身在COCO数据集上训练过,用它作为起点,相当于让模型在“会看”的基础上再学你的数据,收敛速度快得多。
训练过程中终端会不断刷新loss和mAP指标。训练结束后,在runs/train/exp目录下会有几个关键文件:weights/best.pt(验证集效果最好的权重)和weights/last.pt(最后一个epoch的权重)。实际部署时用best.pt就对了。
best.pt不是靠训练loss选出来的,而是在验证集上mAP最高的权重文件。这就解释了为什么验证集这么重要——它是挑选“最优模型”的依据。如果不划分验证集,你就只能猜测哪个epoch效果最好。
4. 训练过程中的玄学与科学:超参数怎么调
4.1 学习率、batch size、imgsz怎么搭配
YOLOv5的超参数定义在data/hyps/hyp.scratch.yaml里,包含了学习率、动量、权重衰减、数据增强等设置。默认参数是官方在COCO数据集上调出来的经验值,多数场景可以直接用,不需要大改。但如果训练效果不理想,有几个参数值得关注。
初始学习率lr0默认0.01,一般不需要动。如果你发现训练loss剧烈震荡,可以把lr0降到0.001,代价是收敛变慢。数据增强参数里面,hsv_h、hsv_s、hsv_v控制颜色扰动,fliplr控制水平翻转概率。如果任务对颜色敏感(比如交通信号灯识别),建议把颜色扰动调低,否则模型容易学到错误的颜色关联。
batch size和imgsz直接决定显存占用。显存不足时,优先降低batch size,而不是降低imgsz。因为imgsz影响模型感受野和精度,而batch size主要影响训练稳定性和速度。模型输入尺寸越小,小目标越难检测,这个影响往往比batch size更明显。
4.2 训练loss下不去的排查思路
训练到一半loss不降,或者val精度一直上不去,这是最让人崩溃的。我按照排查频率给一个顺序:
第一步,看训练集loss和验证集loss的差值。如果训练loss很低、验证loss很高,说明过拟合,解决办法是增加数据量、加大增强程度,或者提前停止。如果两个loss都很高,说明模型还没学够,增加epochs试试。
第二步,检查标签是否正确。数据量不大时,可以单独抽一张标注过的图片出来,写个脚本把标注框画回去,直观看看有没有框错位置、类别标错。
第三步,检查类别是否均衡。如果你做的是5类目标,其中4类各有1000张,第5类只有50张,模型大概率把第5类学成背景。处理办法是收集更多少数类别的图片,或者对少数类别做离线增强(旋转、裁剪、调亮度)。
4.3 什么是好的mAP,别被论文指标带偏
训练结束时终端会打印mAP50和mAP50-95。mAP50指的是IoU阈值为0.5时的平均精度均值,mAP50-95则是在多个IoU阈值下的平均值,要求更严格。
很多人以为mAP必须到90%以上才算成功,其实要看任务复杂度。一个简单场景(固定位置、固定光照、少量类别)mAP95以上很正常;如果是复杂场景(多尺度、遮挡、密集目标),mAP50到80%就已经可以上线了。我自己做车牌识别时mAP50做到92%,mAP50-95只有61%,实际运行时依然能满足业务需求。
判断模型是否“够用”的最直接方式,不是盯着mAP数字,而是把best.pt跑一遍detect,用真实图片看看检测框的位置准不准、置信度稳不稳定。指标的最终目的还是服务实际效果。
5. 常见问题速查与防坑清单
5.1 环境类问题
| 报错信息 | 原因 | 解决方案 |
|---|---|---|
| torch.cuda.is_available() 返回False | 安装的是CPU版PyTorch | 重新安装对应CUDA版本的PyTorch |
| ModuleNotFoundError: No module named 'torch' | 当前环境不是之前装包的环境 | conda activate到正确的虚拟环境 |
| CUDA out of memory | 显存不足 | 降低batch size或imgsz |
| Python DLL load failed | Python版本过低或过高 | 换Python 3.8/3.9 |
环境问题最忌反复重装。我的习惯是:把能用的环境导出一份配置清单,只记录关键包版本,比如PyTorch、numpy、opencv,其余依赖不记录。这样环境崩了以后重建成本很低,也方便在其他机器上复现。
5.2 数据标注类问题
| 报错信息 | 原因 | 解决方案 |
|---|---|---|
| AssertionError: Label class X exceeds nc | 标注中出现了类别id大于nc的值 | 检查标注txt和data.yaml是否一致 |
| No labels found in train dataset | 标签目录为空或路径不对 | 确认labels/train下是否有txt文件 |
| 图片路径里有中文导致读取失败 | 中文路径编码问题 | 整个项目目录、数据集目录统一改成英文路径 |
| 标签文件比图片文件多 | 有些图片没标注就生成了空txt | 删除对应的空txt,或为漏标图片补标注 |
5.3 显存与训练中断
训练到一半程序崩了,这是最不愿意遇到的情况。除了显存不足,还有可能是显卡温度过高导致驱动重启。如果训练长时间中断,建议开启resume功能继续训练:
python train.py --resume runs/train/exp/weights/last.pt它会从上次中断的权重继续训练,而不是从头再来。这个功能救了我很多次,尤其是长时间训练时电源不稳或者系统自动更新导致重启。
5.4 检测结果不理想时检查什么
如果你训练完的模型在测试时漏检、误检严重,不要急着改超参数,按照这个优先级排查:
先看训练集和测试集的分布是否一致。模型只认识它见过的东西,如果训练图片全是室内灯光、测试全在户外强光下,性能差是必然的。数据分布不一致,后面的所有调参都是白费力气。
再看是否用了正确的best.pt。我见过有人用last.pt做推理,结果效果不对,因为last.pt保存的是最后一个epoch的权重,不一定是最优状态。训练时如果不小心把结果跑到了runs/train/exp2甚至exp3,推理时又用了runs/train/exp/weights/best.pt,新老权重混在一起,看起来像是在“微调参数”,实际问题是权重文件选错了。
最后可以试试调低conf-thres。很多时候不是模型没检测到目标,而是目标的置信度低于默认的0.25,被过滤掉了。用0.1的置信度阈值跑一遍,观察检测框是否出现。如果低阈值下能检测到但框不准确,说明模型还需更多数据训练;如果低阈值下依然检测不到,那问题出在模型本身或数据分布。
一些关于“不要乱用”的碎碎念
我自己在YOLOv5上栽过的跟头,大部分不是代码写错,而是“想得太美”——总想用一个参数解决所有问题。实际上,没有任何一个目标检测模型是万能的。YOLOv5适合大部分中高速检测场景,但如果是极端小目标、极度重叠目标,或者需要像素级分割的任务,它并不是最优解。选型比调参更值得花时间。
还有一个很容易被忽略的地方:数据集的版权和合规。网上爬图做数据集虽然方便,但涉及人物肖像、商业产品logo都存在风险。我后来做项目都优先用自己的设备采集图片,或者使用明确授权的公开数据集。这也是“功能强大不要乱用”的另一层含义——技术能力再强,也要注意使用边界。
最后分享一个我自己始终保留的习惯:每次训练前把data.yaml、超参数、训练命令、数据集版本完整记录在实验笔记里。两个月后再回来看模型,你还是能清楚知道当初是怎么训练的。这种体系化的习惯比任何调参技巧都更能帮你少走弯路。
这篇笔记是基于我个人实践整理的YOLOv5从使用到训练的完整流程,里面的参数和命令都是经过验证的。接下来我打算继续更新这一系列,比如如何优化模型速度、如何做模型迁移到嵌入式设备、如何处理训练数据不均衡的问题。如果你正在跑YOLOv5的过程里遇到什么奇怪的报错,不妨按这个思路逐项排查,很多问题在排查的过程中会自己现出原形。