4. YOLOv5训练自己的数据集:配置文件修改,训练参数调优,断点续训与迁移学习
说实话,YOLOv5 的代码库是我见过最友好的之一。但再友好的框架,到了自己数据集上,该踩的坑一个都不会少。这一章,我就带你走一遍完整的流程——从改配置文件,到调参数,再到断点续训和迁移学习。这些都是我实际项目中反复用到的套路。
4.1 数据集准备与标注格式
YOLOv5 用的是标准的 YOLO 格式标注。说白了,就是每个图片对应一个同名的 .txt 文件。文件里每一行代表一个目标:class_id x_center y_center width height。注意,坐标都是归一化到 0~1 的。
我习惯用 LabelImg 或者 labelme 来标注。标注完以后,用脚本转成 YOLO 格式。这里有个坑——类别编号必须从 0 开始,不能从 1 开始。我曾经有个项目,标注的时候从 1 开始编号,结果训练出来的模型永远检测不到第一个类别。排查了半天才发现是这个问题。
python -c "from utils.datasets import LoadImagesAndLabels; print('OK')" 快速验证标注文件是否能被正确加载。
数据集划分我一般按 8:1:1 或者 9:0.5:0.5 来分。训练集、验证集、测试集。测试集不是必须的,但建议留一点,方便最后评估泛化能力。
4.2 配置文件修改:三件套
YOLOv5 的训练需要三个配置文件:data.yaml、模型 yaml、超参数 yaml。我管它们叫「三件套」。
4.2.1 data.yaml
这个文件告诉 YOLOv5 你的数据在哪。格式很简单:
# data.yaml
train: ./datasets/your_dataset/images/train
val: ./datasets/your_dataset/images/val
test: ./datasets/your_dataset/images/test
nc: 3 # 类别数量
names: ['person', 'car', 'bicycle'] # 类别名称
路径可以用路径,也可以用相对路径。我个人习惯用相对路径,方便在不同机器之间迁移。注意,nc 和 names 的顺序要一一对应。
4.2.2 模型 yaml
YOLOv5 提供了 s、m、l、x 四种规模的模型。你可以在 models/ 目录下找到对应的 yaml 文件。比如 yolov5s.yaml:
# yolov5s.yaml
nc: 80 # 这里要改成你自己的类别数
depth_multiple: 0.33 # 模型深度缩放因子
width_multiple: 0.50 # 模型宽度缩放因子
你只需要改 nc 就行。其他参数一般不动。但如果你想要更小的模型,可以调 depth_multiple 和 width_multiple。比如改成 0.25 和 0.25,模型会更轻量,但精度会下降。
4.2.3 超参数 yaml
超参数文件在 data/hyps/ 目录下。默认的 hyp.scratch.yaml 已经调得不错了。但有几个参数我建议你关注一下:
| 参数 | 默认值 | 我的建议 |
|---|---|---|
| lr0 | 0.01 | 小数据集可以降到 0.001 |
| lrf | 0.2 | 一般不动 |
| momentum | 0.937 | 保持默认 |
| weight_decay | 0.0005 | 过拟合时可以加大到 0.001 |
| warmup_epochs | 3.0 | 小数据集可以减到 1.0 |
4.3 训练参数调优
训练命令长这样:
python train.py --data data.yaml --cfg models/yolov5s.yaml --weights '' --batch-size 16 --epochs 100 --img 640
参数看着多,其实核心就几个:
- batch-size:显存够就大一点。我一般 16 起步,能上 32 就上 32。太小了梯度不稳定。
- epochs:小数据集 100~200 就够了。大数据集 300 起步。
- img:输入图片大小。640 是默认,如果目标很小,可以试试 1280。
- workers:数据加载的线程数。我习惯设成 8,但不要超过 CPU 核心数。
workers 或者 batch-size。有时候是数据加载成了瓶颈。
还有一个参数 --cache,可以把图片缓存到内存里。如果你的内存够大(32G 以上),加上这个参数能明显加快训练速度。我第一次用的时候,训练时间直接缩短了 30%。
4.4 断点续训
训练到一半断电了?或者 loss 突然炸了?别慌,YOLOv5 支持断点续训。
你只需要在训练命令里加上 --resume 参数:
python train.py --resume runs/train/exp/weights/last.pt
它会自动读取上次的 last.pt 权重文件,恢复优化器状态、学习率调度器、epoch 进度。说白了,就跟没断过一样。
我有个项目训练了 300 个 epoch,跑到第 247 个 epoch 的时候服务器重启了。当时我心态差点崩了。但用了 --resume 之后,从第 247 个 epoch 继续跑,最后模型效果一点没受影响。
--data 或者 --cfg,可能会出问题。所以训练前最好把参数记下来。
4.5 迁移学习实战
迁移学习是 YOLOv5 最强大的功能之一。说白了,就是拿别人在大数据集上训好的权重,在自己的小数据集上微调。
YOLOv5 官方提供了在 COCO 数据集上预训练的权重:
yolov5s.pt— 轻量级,适合移动端yolov5m.pt— 中等规模yolov5l.pt— 大型,精度高yolov5x.pt— 超大型,精度最高
使用方式很简单:
python train.py --data data.yaml --cfg models/yolov5s.yaml --weights yolov5s.pt --batch-size 16 --epochs 50
这里有个关键点:--weights 指定预训练权重后,YOLOv5 会自动把最后一层的类别数改成你的 nc。你不需要手动改模型结构。
迁移学习的好处是收敛快。我做过对比:
| 训练方式 | 达到 mAP@0.5=0.8 所需 epoch | 最终 mAP@0.5:0.95 |
|---|---|---|
| 从头训练 | 120 | 0.52 |
| 迁移学习(冻结 backbone) | 30 | 0.58 |
| 迁移学习(全量微调) | 20 | 0.61 |
你看,迁移学习不仅收敛快,最终精度也更高。原因很简单——预训练权重已经学会了通用的特征提取能力,你只需要微调一下就能适配自己的数据。
--freeze 10 冻结前 10 层,训练 20 个 epoch。然后解冻全部层,再训练 30 个 epoch。这样既快又稳。
嗯,到这里,YOLOv5 训练自己数据集的完整流程就讲完了。从改配置文件到调参数,从断点续训到迁移学习,每一步都有坑,但也都有解法。你动手试试看,遇到问题再回来翻翻这一章。