YOLOv5完整教程(二)
目录
损失函数演进
1. 早期方法:L1/L2损失
在YOLOv5之前,目标检测框回归通常采用简单的距离损失:
L e a r l y = ( x − x ^ ) 2 + ( y − y ^ ) 2 + ( w − w ^ ) 2 + ( h − h ^ ) 2 L_{early} = (x - \hat{x})^2 + (y - \hat{y})^2 + (w - \hat{w})^2 + (h - \hat{h})^2 Learly=(x−x^)2+(y−y^)2+(w−w^)2+(h−h^)2
缺点:仅考虑坐标差值,忽略了预测框与真实框的形状和重叠关系。
2. IOU损失(Intersection over Union)
IOU反映了两个框的重叠程度,是更好的评估指标:
I O U = A r e a i n t e r s e c t i o n A r e a u n i o n IOU = \frac{Area_{intersection}}{Area_{union}} IOU=AreaunionAreaintersection
优点 :能够度量框之间的重叠关系
缺点:当两个框完全不相交时,IOU=0,无法提供优化方向
3. GIOU损失(Generalized IOU)
为解决IOU的不足,GIOU引入了外接矩形的概念:
G I O U = I O U − C − U C GIOU = IOU - \frac{C - U}{C} GIOU=IOU−CC−U
其中:
- C C C = 包含两个框的最小外接矩形面积
- U U U = 两个框的并集面积
性质:
- 取值范围: [ − 1 , 1 ] [-1, 1] [−1,1]
- 当框完全重合时,GIOU = 1
- 当框完全不相交时,GIOU ∈ [ − 1 , 0 ) [-1, 0) [−1,0)
缺点:当两个框的中心点位置不同,但外接矩形相同时,GIOU值相同,无法区分
4. DIOU损失(Distance IOU)
DIOU加入了中心点之间的距离约束:
D I O U = I O U − ρ 2 ( b , b g t ) c 2 DIOU = IOU - \frac{\rho^2(b, b^{gt})}{c^2} DIOU=IOU−c2ρ2(b,bgt)
其中:
- ρ ( b , b g t ) \rho(b, b^{gt}) ρ(b,bgt) = 预测框和真实框中心点间的欧式距离
- c c c = 最小外接矩形的对角线长度
改进:能够更好地考虑框的位置关系
5. CIOU损失(Complete IOU)
CIOU在DIOU的基础上,加入了宽高比的约束:
C I O U = I O U − ρ 2 ( b , b g t ) c 2 − α ⋅ v CIOU = IOU - \frac{\rho^2(b, b^{gt})}{c^2} - \alpha \cdot v CIOU=IOU−c2ρ2(b,bgt)−α⋅v
其中:
v = 4 π 2 ( arctan w g t h g t − arctan w h ) 2 v = \frac{4}{\pi^2}(\arctan\frac{w^{gt}}{h^{gt}} - \arctan\frac{w}{h})^2 v=π24(arctanhgtwgt−arctanhw)2
α = v ( 1 − I O U ) + v \alpha = \frac{v}{(1-IOU) + v} α=(1−IOU)+vv
优势:综合考虑了重叠面积、中心距离和宽高比,是YOLOv5采用的主要损失函数
正负样本匹配规则
匹配原则
在YOLOv5中,正样本匹配基于网格划分和坐标范围判断。
坐标范围扩展
原始坐标范围: [ 0 , 1 ] [0, 1] [0,1]
扩展范围: [ − 0.5 , 0.5 ] [-0.5, 0.5] [−0.5,0.5]
这个扩展的目的是:
- 允许目标中心点出现在相邻网格单元的边界附近
- 增加正样本数量,缓解样本不均衡问题
- 使模型对边界位置的目标更敏感
匹配过程
- 确定目标所在的主网格:根据目标中心点所在的网格单元
- 扩展匹配范围:检查相邻网格单元是否满足匹配条件
- 坐标判断 :
- 如果 x < 0.5 x < 0.5 x<0.5 且 y > 0.5 y > 0.5 y>0.5,则该网格作为正样本
- 对所有相邻网格进行相同判断
正负样本不均衡处理
问题:扩展匹配后,正样本数量仍可能不足,导致正负样本比例严重失衡
解决方案:
- 对正样本的损失乘以缩放因子
- 对负样本的损失乘以相应权重
- 使模型更关注有限的正样本
IOU系列详解
IOU的几何意义
真实框(绿色) 预测框(红色)
┌─────────┐
│ ┌───┐ │
│ │ ∩ │ │
└──┼───┼──┘
└───┘
交集面积(∩)
IOU = ─────────────
并集面积(∪)
四种IOU对比
| 损失函数 | 取值范围 | 优点 | 缺点 |
|---|---|---|---|
| IOU | [0, 1] | 基础指标 | 不相交时梯度为0 |
| GIOU | [-1, 1] | 考虑外接矩形 | 无法区分不同位置 |
| DIOU | [-1, 1] | 加入中心距离 | 未考虑宽高比 |
| CIOU | [-1, 1] | 全面考虑 | 计算复杂度最高 |
CIOU的理论优势
CIOU同时优化三个方面:
- 重叠面积 ( I O U IOU IOU):鼓励框的交集更大
- 中心距离 ( ρ 2 / c 2 \rho^2/c^2 ρ2/c2):鼓励中心点对齐
- 宽高比 ( α v \alpha v αv):鼓励尺度匹配
结合这三项约束,模型能够更快收敛,检测效果更好。
YOLOv5模型结构
主要特点
YOLOv5相比YOLOv4的改进:
- 更优美的代码结构
- 灵活的模型缩放方案
- 官方支持更好
模型架构
YOLOv5由三个部分组成:
- Backbone(主干网络):特征提取
- Neck(颈部网络):多尺度融合
- Head(头部网络):目标检测
深度参数(Depth)
深度参数控制网络的层数。在主干网络中体现为不同的C3模块堆叠:
Backbone中的模块序列:C3-C3-C3-C3
YOLOv5s: 深度系数 = 0.33
3 × 0.33 = 1 (3个C3)
6 × 0.33 = 2 (6个C3)
9 × 0.33 = 3 (9个C3)
3 × 0.33 = 1 (3个C3)
结果:1-2-3-1
YOLOv5m: 深度系数 = 0.67
结果大约为:2-4-6-2
YOLOv5l: 深度系数 = 1.0
结果:3-6-9-3
YOLOv5x: 深度系数 > 1.0
结果:更深的网络结构
宽度参数(Width)
宽度参数控制卷积核的数量:
原始卷积核数 × 宽度系数 = 实际卷积核数
示例:
64 × 0.5 = 32 (模型变小)
128 × 0.5 = 64
64 × 1.0 = 64 (原始大小)
128 × 1.0 = 128
64 × 2.0 = 128 (模型变大)
128 × 2.0 = 256
模型版本对比
| 版本 | 深度系数 | 宽度系数 | 相对大小 | 推理速度 | 精度 |
|---|---|---|---|---|---|
| YOLOv5n | 0.33 | 0.25 | 最小 | 最快 | 较低 |
| YOLOv5s | 0.33 | 0.5 | 小 | 快 | 中等 |
| YOLOv5m | 0.67 | 0.75 | 中等 | 中等 | 中上 |
| YOLOv5l | 1.0 | 1.0 | 大 | 慢 | 较高 |
| YOLOv5x | 1.33 | 1.25 | 最大 | 最慢 | 最高 |
性能对比示例
输入尺寸:640×640
| 版本 | 参数量 | mAP@0.5 | mAP@0.5:0.95 | GPU速度(ms) |
|---|---|---|---|---|
| YOLOv5n | 1.9M | 45.7 | 28.0 | 6.3 |
| YOLOv5s | 7.2M | 56.8 | 37.3 | 6.4 |
| YOLOv5m | 21.2M | 60.3 | 42.5 | 8.1 |
| YOLOv5l | 47.0M | 63.4 | 45.1 | 10.1 |
| YOLOv5x | 87.7M | 68.9 | 49.0 | 15.5 |
关键发现:
- YOLOv5x虽然参数增加了一倍,但精度提升有限
- 推理速度明显变慢
- 实际应用中需根据硬件条件选择合适版本
项目实战
环境配置
1. 克隆YOLOv5仓库
bash
git clone https://github.com/ultralytics/yolov5.git
cd yolov5
2. 安装依赖
bash
pip install -r requirements.txt
3. 验证环境
bash
python detect.py --weights yolov5s.pt --source 0 # 使用摄像头测试
项目结构
yolov5/
├── data/ # 数据集配置
│ ├── coco128.yaml
│ ├── coco.yaml
│ └── custom.yaml # 自定义数据集配置
├── models/ # 模型定义
│ ├── yolov5s.yaml
│ ├── yolov5m.yaml
│ └── common.py # 通用模块(C3、Focus等)
├── utils/ # 工具函数
│ ├── datasets.py # 数据加载
│ ├── general.py # 通用函数
│ └── metrics.py # 评估指标
├── detect.py # 推理脚本
├── train.py # 训练脚本
├── val.py # 验证脚本
└── requirements.txt # 依赖列表
推理(检测)
使用预训练模型进行推理
bash
# 检测图片
python detect.py --weights yolov5s.pt --source data/images
# 检测视频
python detect.py --weights yolov5s.pt --source video.mp4
# 使用摄像头实时检测
python detect.py --weights yolov5s.pt --source 0
# 自定义输出目录
python detect.py --weights yolov5s.pt --source data/images --project runs/detect --name exp1
推理脚本示例
python
import torch
from models.common import DetectMultiBackend
from utils.general import non_max_suppression
# 加载模型
model = DetectMultiBackend('yolov5s.pt', device='cuda')
# 前处理
img = torch.randn(1, 3, 640, 640).cuda()
# 推理
pred = model(img)
# 后处理(NMS)
det = non_max_suppression(pred, conf_thres=0.25, iou_thres=0.45)
print(det) # 检测结果:[x1, y1, x2, y2, conf, class]
训练自定义数据集
1. 准备数据集
数据集格式(VOC或COCO):
dataset/
├── images/
│ ├── train/
│ ├── val/
│ └── test/
└── labels/
├── train/
├── val/
└── test/
标签格式(YOLO格式):
<class_id> <x_center> <y_center> <width> <height>
2. 创建数据集配置文件
创建 data/custom.yaml:
yaml
path: /path/to/dataset
train: images/train
val: images/val
test: images/test
nc: 3 # 类别数
names: ['helmet', 'vest', 'person'] # 类别名称
3. 开始训练
bash
# 基础训练
python train.py --img 640 --batch 16 --epochs 100 --data data/custom.yaml --weights yolov5s.pt
# 从头训练
python train.py --img 640 --batch 16 --epochs 100 --data data/custom.yaml --weights ''
# 指定GPU
python train.py --img 640 --batch 16 --epochs 100 --data data/custom.yaml --weights yolov5s.pt --device 0,1,2,3
训练参数说明
| 参数 | 说明 | 默认值 |
|---|---|---|
--img |
输入图片尺寸 | 640 |
--batch |
批大小 | 16 |
--epochs |
训练轮数 | 100 |
--data |
数据集配置文件路径 | - |
--weights |
预训练权重 | yolov5s.pt |
--device |
GPU设备ID | 0 |
--workers |
数据加载线程数 | 8 |
4. 训练输出
训练完成后,结果保存在 runs/train/exp/ 目录:
exp/
├── weights/
│ ├── best.pt # 最优模型
│ └── last.pt # 最后一个模型
├── results.png # 训练曲线
├── confusion_matrix.png # 混淆矩阵
└── results.csv # 训练指标
验证
bash
# 验证训练效果
python val.py --weights runs/train/exp/weights/best.pt --data data/custom.yaml --img 640 --batch 16
模型导出
bash
# 导出为ONNX格式
python export.py --weights yolov5s.pt --include onnx
# 导出为TorchScript
python export.py --weights yolov5s.pt --include torchscript
# 导出为TensorFlow Lite
python export.py --weights yolov5s.pt --include tflite
总结
YOLOv5相比之前版本的优势:
- 更优的损失函数:采用CIOU全面优化框回归
- 灵活的缩放方案:通过深度和宽度参数灵活调整模型大小
- 更好的样本匹配:扩展坐标范围增加正样本
- 优美的代码结构:易于理解和改进
- 良好的官方支持:持续维护和更新
在计算机视觉领域,YOLOv5无疑是最璀璨的明星,广泛应用于工业场景,也激励了众多后续版本(YOLOv6、YOLOv7等)的发展。