[YOLO系列④] YOLOv5模型训练与流程解析
1.基本使用
1.YOLOv5整体概述
YOLOv5本质上是一个经过大量优化的工程项目,不像前几代那样有对应的学术论文。它主要是在YOLOv4的基础上做了更实用的工程改进,让使用者能更轻松地应用到实际场景中。主要有以下特点:
- 工程优化为主
- 没有官方论文,核心改进在于代码实现,比如训练效率、代码可读性
- 相比YOLOv4,工程结构更简洁,配置更直观,适合直接拿来训练自己的数据
- 使用体验升级
- 作者把数据增强、模型结构(如CSP、SPP模块)等复杂逻辑封装得很好,使用者几乎不用改代码
- 支持混合精度训练,训练速度更快,对硬件要求更友好
- 简化训练自定义数据
- 不需要用庞大的COCO数据集,准备好自己的标注数据(格式和目录按规范整理)就能直接开跑
- 数据增强、模型配置都通过配置文件(YAML)管理,改几个参数就能适配不同任务
- 代码简洁
- 相比YOLOv3/v4的“堆料式”代码,V5的代码结构清晰,模块化程度高,容易二次开发
- 项目文档详细,从安装到训练、测试都有现成指令,能快速上手
YOLOv5 的代码量虽然多一点,但设计非常细致、实用,并且持续更新维护,不同于很多“一发论文就停止维护”的学术项目。
2.训练自定义数据集
如何训练自定义数据集,可分为三步:
- 下载(准备)标注好的数据集
- 按指定文件夹结构存放
- 改配置文件里的路径和类别数
训练数据也可以从Roboflow上下载,Roboflow 是一个面向开发者和企业的端到端计算机视觉(CV)开发平台,可以帮助用户高效构建、训练、部署和管理AI视觉模型,上面也有多个轻量级的目标检测数据集(如手写数字、象棋、扑克牌、口罩等),比较适合单机或低配置训练。
我们选择口罩数据集,下载的时候选择格式为 YOLOv5 PyTorch(.txt 标签格式),下载后将数据集解压到与 YOLOv5 源码(如 yolov5-master)同级目录下,例如:mask_wearing_data。
1 | mask_wearing_data/ |
配置文件(data.yaml)需要指定图像路径、标签路径、类别数(如口罩数据集为2类:戴口罩 / 未戴口罩)。
1 | data.yaml/ |
标签为 .txt 格式,第一列是类别编号,后四列是归一化后的边框坐标(YOLO格式)。标签文件需与图片文件名对应,如果想定义自己的数据集可以参考这个数据格式。
1 | 126202-untitled-design-13_jpg.rf.baa3d2e55d469ae5d5d4cd81c4603e1d.txt |
YOLOv5 会在训练时自动生成缓存文件(如 .cache),提高后续训练速度。
2.下载预训练模型与配置参数
YOLOv5给我们提供了很多预训练模型,这些模型在参数量、计算量和性能上都有所区别,主要面向不同的应用场景和硬件需求。模型名称后缀越大,参数量越多,精度越高,但训练速度会越慢:
- YOLOv5n(Nano)
- 参数量:约 1.9M
- 计算量:约 4.5 GFLOPs
- 适用场景:移动端/嵌入式设备(如 Jetson Nano、树莓派)或对实时性要求极高的场景。
- YOLOv5s(Small)
- 参数量:约 7.2M
- 计算量:约 16.5 GFLOPs
- 适用场景:轻量级通用检测,平衡速度与精度,适合边缘计算设备(如 Jetson TX2)。
- YOLOv5m(Medium)
- 参数量:约 21.2M
- 计算量:约 49.0 GFLOPs
- 适用场景:通用场景下的实时检测(如视频监控、无人机航拍)。
- YOLOv5l(Large)
- 参数量:约 46.5M
- 计算量:约 109.1 GFLOPs
- 适用场景:服务器端或高性能 GPU,对精度要求较高的任务。
- YOLOv5x(X-Large)
- 参数量:约 86.7M
- 计算量:约 205.7 GFLOPs
- 适用场景:研究或高精度需求场景(如医学图像分析、卫星图像检测)。
一般我们在学习和测试的时候建议先用 yolov5s,好处是小模型、十几 MB,训练速度快一些。
使用train.py
训练当前自定义数据集mask_wearing_data
命令:
1 | python train.py --data ../mask_wearing_data/data.yaml --cfg models/yolov5s.yaml --weights yolov5s.pt --batch-size 16 --freeze 10 --epochs 10 |
如果命令在运行的时候判断如果指定模型结构还没有下载预训练模型就会自动下载到项目根目录。
参数 | 作用 |
---|---|
--data |
指定数据配置文件 data.yaml ,描述数据集路径、类别数、类别名称等信息 |
--cfg |
指定模型结构配置文件 yolov5s.yaml ,定义 YOLOv5s 的网络结构 |
--weight |
使用yolov5s预训练权重,可加速收敛并提升精度 |
--batch-size |
设置每个批次的样本数为 16,影响训练速度和显存占用 |
--freeze |
冻结骨干网络的前 10 层,减少计算量 |
--epochs |
训练轮数 |
最后的一个Epoch+summary日志:
2.数据处理
下面就来分析一下YOLOv5的代码,看看如何实现,如何加载数据集, 数据增强特别是 Mosaic 的实现逻辑,最终返回可用于训练的数据与标签
1.数据加载
utils/dataloaders.py
文件是 YOLOv5 的数据加载和处理模块,支持多种训练和推理场景,大致包含以下主要功能:
- 数据加载器:支持图像/视频文件、实时视频流、屏幕截图及分类数据集的加载(
LoadImages
/LoadStreams
/LoadImagesAndLabels
等) - 预处理与增强:包含图像缩放、填充、Mosaic/MixUp增强、随机透视变换、HSV调整等,支持训练时动态数据增强
- 视频处理:多线程处理本地视频、YouTube流和IP摄像头,实现高效帧读取
- 数据集管理:提供缓存机制、数据集验证、自动分割(训练/验证/测试)及统计信息生成(
HUBDatasetStats
) - 分布式训练支持:通过
SmartDistributedSampler
实现多GPU数据分配,确保数据加载与并行训练协调 - 格式转换工具:自动转换图像路径到标签路径、处理EXIF信息、验证数据合法性(
verify_image_label
) - 性能优化:采用内存/磁盘缓存、多线程加载、批处理优化(如四合一拼接)加速数据流水线
- 错误处理:检测损坏图像/标签,记录异常并跳过无效数据,保障训练稳定性
- 分类任务扩展:专用
ClassificationDataset
支持图像分类数据加载与增强 - 导出与兼容性:支持数据集压缩、格式转换及统计报告生成,便于模型部署和迁移
如何取数据,来看看create_dataloader
的各个参数
1 | utils/dataloaders.py |
返回值:
- loader: 配置好的 DataLoader 实例,用于迭代训练数据
- dataset: 数据集对象,可用于获取样本数、类别数等元信息
2.数据增强
数据和标签已经准备好了接下来要读取每一个样本并进行处理(如数据增强)
整体流程如下:
- 调用
__getitem__
加载图像 - 判断是否启用 Mosaic 增强
- 随机设定 Mosaic 中心点
- 拼接 4 张图像(1 当前索引 + 3 随机图)
- 将图像和标签重新组合,作为一个新的训练样本返回
1.__getitem__
1 | def __getitem__(self, index): |
__getitem__
核心作用:
- 动态数据增强:通过Mosaic、MixUp、空间/颜色变换等提升模型泛化能力
- 多策略采样:支持多种索引分配方式,适配不同训练需求
- 坐标系统一:确保标签在不同增强步骤后仍保持归一化格式
- 格式标准化:输出直接适配模型训练的Tensor格式
2.Mosaic 增强
load_mosaic
是用于实现Mosaic数据增强的核心函数,其主要作用是将四张图像拼接成一张大图,并调整对应的标注信息,以提升模型训练时的数据多样性
1 | def load_mosaic(self, index): # index(当前样本的索引) |
3.网络结构
从输入层到输出层,讲解网络各层及结构的逻辑 会用清晰的“主线逻辑”串联复杂结构
1.网络结构可视化
如果想要更直观的查看模型结构,可以使用模型可视化工具,比如Netron,但如果直接导入yolov5s.pt
模型时,展示的结构会不完整,只显示模块名称,看不出实际的数据流动细节,这时需要将pt
格式转化为onnx
格式。
ONNX(Open Neural Network Exchange) 是一种开放格式,用于表示和交换深度学习模型。它的核心作用是让不同框架(如PyTorch、TensorFlow)训练的模型能够互相转换和运行。
1.ONNX模型导出
1 | 先安装 |
2.ONNX模型可视化
Netron支持多种方式可视化,我们可以通过浏览器地址Netron加载.onnx
模型:
2.网络结构配置解读
1.核心模块
1.Conv模块(标准卷积模块)
结构:Conv → BatchNorm → SiLU(激活函数)
作用:
- 提取局部特征(边缘、纹理、角点等)
- 下采样(如果步长 > 1)
- 控制通道数量,压缩或扩展特征图维度
2.C3模块(残差模块)
结构:
1 | ┌────────────┐ |
- 输入被一分为二
- 一部分走多个 Bottleneck 残差单元(默认含卷积 + 残差连接)
- 一部分不变
- 最后两者 Concatenate → 再接个卷积融合
作用: - 提高特征提取能力
- 控制模型计算量(参数量比 ResNet 少)
- 保留不同路径的特征信息(浅+深)
3.SPPF模块(Spatial Pyramid Pooling - Fast)
结构:
1 | input ──────────────┐ |
- 连续做 3 次相同核大小的最大池化
- 所得多个特征图拼接
- 最后再通过卷积融合
作用: - 扩展感受野:融合不同尺度空间上下文信息
- 增强特征表达:尤其适合大目标或上下文强依赖的情况
4.Concat(特征拼接)
结构:
Concat 模块没有卷积,它只是把来自不同层的特征图在通道维度拼接在一起
作用:
- 融合上采样后的特征图和 backbone 中较浅层(如 P3/P4)的特征
- 提高模型对不同尺度目标的检测能力
5.上采样模块(nn.Upsample)
结构:
PyTorch 内置上采样模块
1 | nn.Upsample(scale_factor=2, mode='nearest') |
作用:
将特征图放大(恢复空间分辨率),常用于:
- 将深层(小尺寸)特征图上采样,和浅层(大尺寸)特征图进行拼接
- 类似 U-Net 中的上采样路径
5.Detect
为每个网格(每个 anchor)预测:
- 边界框坐标(x, y, w, h)
- 置信度(objectness)
- 类别概率(cls)
2.网络结构
YOLOv5s(small 版本)网络结构,包括超参数、骨干网络(backbone)和检测头(head):
1 | models/yolov5s.yaml/ |
3.模型解析
1.模型构建
DetectionModel.__init__
1 | def __init__(self, cfg="yolov5s.yaml", ch=3, nc=None, anchors=None) |
- 加载并解析 YAML 配置文件,构建模型字典 self.yaml
- 如果传入 nc 或 anchors 会覆盖配置文件中的默认值
- 调用 parse_model(…) 来解析模型结构(构建 backbone、neck、head 等)
- 设置类别名 self.names,默认是 [0, 1, …, nc-1]
- 若最后一层是 Detect 或 Segment,还会:
- 构建 stride(下采样倍数)
- 调整 anchors(除以 stride)
- 初始化偏置项 self._initialize_biases()
- 初始化网络权重:initialize_weights(self)
- 打印模型信息:self.info()
2.前向传播阶段
调用 model(x) 会触发:
1 | def forward(self, x, augment=False, profile=False, visualize=False) |
- 默认进入 _forward_once(x)
- 如果 augment=True,则走增强推理 _forward_augment(x) 分支(多尺度+翻转)
- profile 和 visualize 是可选功能:性能分析、特征可视化
3.forward_once
1 | def _forward_once(self, x, profile=False, visualize=False) |
- 遍历 self.model 中的每一层模块
- 如果 m.f != -1,说明当前模块依赖前面某一层的输出
- 执行前向传播:x = m(x)
- 如果 m.i in self.save,就将输出 x 保存到 y 中
- 如果 visualize=True,还会进行特征可视化
最终返回最后一层输出 x,对于 Detect/Segment 模块,输出格式如下:
1 | # Detect: |
最终返回最后一层输出 x,对于 Detect/Segment 模块,输出格式如下:
4.Detect/Segment 模块解析
Detect 是检测 head,会根据 anchor/grid 解码预测框:
- 分类数 nc,每个输出通道为 no = nc + 5(中心、宽高、置信度、分类概率)
- anchor/grid 是在首次前向推理中动态计算的
- 推理时输出 (batch, anchors × grid_x × grid_y, no)
Segment 继承自 Detect,额外处理 mask 信息:
- 输出通道为 no = 5 + nc + nm,其中 nm 是 mask 数量
- 使用 Proto 结构生成原型掩膜
5.增强推理(_forward_augment)
通过缩放和翻转图像进行多尺度推理增强:
1 | def _forward_augment(self, x): |
- 对每个缩放比例和翻转方向进行推理
- 对输出结果反向还原:_descale_pred()
- 拼接所有预测结果:torch.cat(…)
- 修剪增强推理中的冗余部分:_clip_augmented(…)
4.训练流程与策略
1.训练流程
1.日志记录与文件保存
YOLOv5 在训练过程中,不仅会在控制台输出训练信息,还会将大量有价值的训练信息保存到日志中。每次训练都会在runs/train下生成一个exp文件夹:
1 | runs/train/exp4/ |
2. 模型加载与初始化
训练开始前,YOLOv5 会进行一系列初始化设置:
- 设置随机种子,保证结果可复现
- 读取数据配置文件(如 data.yaml),确定类别数和路径
- 检查数据集路径和配置是否正确,防止路径错误导致训练失败
3.模型构建与加载权重
模型的构建依赖配置文件(如 yolov5s.yaml),源码会根据结构定义逐层构建模型。
如果本地已经存在预训练模型(如 yolov5s.pt),则会优先加载本地模型;否则,会从 YOLOv5 的官方仓库自动下载。建议提前下载,以避免自动下载速度较慢。
4.迁移学习与冻结层设置
YOLOv5 支持迁移学习,即在预训练模型基础上进行微调。你可以选择是否“冻结”部分网络层(通常是 backbone 部分)来保留其预训练特征。
实践中发现:即便只用几十张图片,在不冻结层的情况下也能获得不错的检测效果。因此除非数据量特别小或训练不稳定,通常不需要特意冻结层。
5.梯度累积机制:nbs 参数的作用
YOLOv5 中引入了 梯度累积(Gradient Accumulation) 机制,主要通过 nbs 参数控制。
举个例子:
- 如果 batch size 为 16,nbs 为 64,那么模型会累积 4 个 batch 的梯度再进行一次反向传播更新。
- 优点:在显存受限的设备上模拟更大的 batch size,提高训练稳定性和效果。
这个机制通过代码实现了变相扩大 batch size,有助于更稳定地更新模型权重。
6.优化器与学习率调度
优化器方面,YOLOv5 将模型参数分组处理(如偏置项、权重项分别优化),并支持如下优化策略:
- 初始学习率、动量、权重衰减等参数可配置
- 支持多种 学习率衰减策略(如余弦衰减 CosineLR)
- 提供完整的学习率调度函数,借鉴了多个经典文献
虽然这部分源码涉及的数学细节较多,但理解其核心目的即可——随着训练迭代,逐步降低学习率,提高模型稳定性与精度。
2.训练策略
1.断点续训逻辑
YOLOv5 支持断点续训,便于训练中断后的恢复。其机制如下:
- 加载断点模型
- 当我们指定了一个断点模型(如 –weights=weights/last.pt),YOLOv5 会自动加载上次训练时保存的所有状态(模型参数、优化器状态、学习率调度器状态、EMA等)。
- 自动判断是否继续训练
- 假设我们上次训练了 150 个 epoch,现在使用 –epochs 100 启动新的训练。
- YOLOv5 会检查当前模型的已训练轮数。如果已经超过 100(如已训练 150),则不会再训练;如果未达到(如当前为 80),则会 继续训练剩余的轮数(此例中为 20)。
- 额外保存模型(双重保险)
- 加载断点模型后,YOLOv5 会额外保存一次模型权重。这一操作的初衷似乎是为了保险——防止覆盖原有模型。
- 实测表明:加载模型并不会覆盖原始权重文件。这个多保存一次的逻辑目前看起来意义不大,反而增加了存储负担,不过可以理解为一种“冗余备份机制”。
2.图像尺寸校验逻辑(gs 检查)
在训练前,YOLOv5 会校验输入图像的尺寸是否符合网络结构要求。主要逻辑如下:
- YOLOv5 的 backbone 下采样倍数为 32,因此输入图像尺寸必须能被 32 整除(如 640×640)。
- gs(grid size) 就是该下采样因子。如果尺寸不满足要求,会报错或自动调整图像尺寸。
这一检查确保了网络中卷积和特征图尺寸的兼容性,是非常基础但关键的一步。
3.EMA(滑动平均)机制的作用
YOLOv5 默认启用了 EMA(Exponential Moving Average):
- 通过对模型参数的历史状态进行滑动平均,生成一个更稳定的权重;
- EMA 权重会用于最终评估和保存(best.pt),因为其结果通常更平滑、鲁棒性更强。
5.总结
YOLOv5是一个高度工程优化的目标检测框架,核心特点包括:
- 工程友好:模块化代码结构清晰,支持快速训练自定义数据集(只需规范数据格式并修改YAML配置)
- 高效训练:集成Mosaic/MixUp数据增强、梯度累积(nbs参数)、EMA权重平均等技术,提升模型泛化能力
- 灵活部署:提供Nano到XLarge多规格预训练模型,适配从嵌入式设备到服务器的不同场景
- 全流程支持:训练中自动记录日志、可视化指标(如PR曲线)、保存最佳模型(best.pt),便于调试和部署