4. YOLOv5 损失函数:CIoU Loss、二元交叉熵与调优实战
损失函数,说白了就是告诉模型「你错哪儿了」。YOLOv5 的损失函数由三部分组成:边界框回归损失、置信度损失和分类损失。我刚开始接触时也觉得公式多,但拆开看其实就两套逻辑:一套管位置准不准,一套管分类对不对。
4.1 边界框回归:从 IoU 到 CIoU
早期 YOLO 用 MSE 算框的偏差,但 MSE 对尺度太敏感。大框和小框同样偏移 10 像素,损失值一样,但实际影响天差地别。后来大家改用 IoU 系列损失,YOLOv5 选的是 CIoU Loss。
4.1.1 IoU 的演进路线
| 损失函数 | 核心思想 | 解决的问题 |
|---|---|---|
| IoU Loss | 直接优化交并比 | 尺度不变性 |
| GIoU Loss | 引入最小外接矩形惩罚项 | 两框不重叠时梯度消失 |
| DIoU Loss | 加入中心点距离惩罚 | GIoU 收敛慢、退化问题 |
| CIoU Loss | 中心点距离 + 长宽比一致性 | 框的形状也参与回归 |
YOLOv5 用的是 CIoU,公式长这样:
CIoU = IoU - (ρ²(b, b_gt) / c²) - αv
其中:
ρ²(b, b_gt) = 预测框与真实框中心点的欧氏距离平方
c = 最小外接矩形的对角线长度
v = (4/π²) * (arctan(w_gt/h_gt) - arctan(w/h))²
α = v / ((1 - IoU) + v) # 平衡系数
嗯,这里要注意 α 的设计。当 IoU 很小时,α 也小,模型优先对齐位置;当 IoU 变大后,α 增大,开始精细调整长宽比。这个自适应机制很巧妙。
4.2 分类与置信度:二元交叉熵损失
YOLOv5 的分类和置信度都用了 二元交叉熵损失(BCE Loss)。为什么不用多分类 Softmax?因为 YOLOv5 支持多标签分类——一个目标可以同时是「车」和「红色车」。Softmax 强制互斥,BCE 则允许每个类别独立判断。
BCE Loss = -[y * log(p) + (1 - y) * log(1 - p)]
其中:
y = 真实标签(0 或 1)
p = 模型预测的概率
你想想看,如果一张图里同时有猫和狗,Softmax 会把概率总和压成 1,猫 0.6 狗 0.4,这显然不合理。BCE 则各自独立,猫 0.9 狗 0.8,互不影响。
4.2.1 置信度损失的特别之处
置信度损失只对 正样本 和 负样本 计算,忽略忽略样本(ignored)。正样本是匹配到 GT 的 anchor,负样本是 IoU 低于阈值的 anchor。中间那些 IoU 在 0.2~0.5 之间的,直接跳过——它们太模糊,硬学反而有害。
4.3 损失平衡策略:三部分怎么加权
YOLOv5 的总损失是三个损失的加权和:
Total Loss = λ_box * CIoU Loss + λ_obj * BCE(obj) + λ_cls * BCE(cls)
默认权重是:
| 损失项 | 默认权重 | 作用 |
|---|---|---|
| λ_box | 0.05 | 边界框回归 |
| λ_obj | 1.0 | 置信度(有无目标) |
| λ_cls | 0.5 | 类别预测 |
为什么 λ_box 这么小?因为 CIoU 的值域在 [0, 2] 左右,而 BCE 在 [0, 1]。如果不降权,框的损失会主导梯度,分类几乎学不动。我习惯把 λ_box 调到 0.05~0.1 之间,具体看数据集的框大小分布。
4.3.1 正负样本平衡:Focal Loss 的影子
YOLOv5 没有直接用 Focal Loss,但做了类似的事:对负样本的置信度损失降权。具体来说,负样本的损失乘以一个系数 (1 - p_obj)^γ,γ 默认 0。如果你想开启难例挖掘,把 γ 设成 1.5 或 2.0 就行。
4.4 超参数调优:我的实战经验
调损失函数的超参数,说白了就是找平衡。我总结了一套「三步走」策略:
- 先固定 λ_box 和 λ_cls,只调 λ_obj。因为置信度是 YOLO 的命脉,框再准,置信度判错也没用。
- 观察训练曲线:如果 CIoU 损失降得慢,适当增大 λ_box;如果分类精度上不去,增大 λ_cls。
- 用验证集 mAP 做最终裁决:不要只看损失值,损失低不一定 mAP 高。
| 场景 | 建议调整 | 原因 |
|---|---|---|
| 小目标多 | λ_box 增大到 0.1 | 小框的 CIoU 对位置更敏感 |
| 类别不平衡 | λ_cls 增大到 0.7 | 让分类损失多贡献梯度 |
| 误检率高 | λ_obj 增大到 1.5 | 压制负样本的置信度 |
| 漏检率高 | 降低负样本降权系数 | 让模型更「大胆」地预测 |
4.5 损失函数整体流程
下面这张图把 YOLOv5 的损失计算流程串起来了,我建议你对照着看:
从流程图能看出来,三个分支各自独立计算,最后加权求和。正负样本筛选在中间层做了一次「过滤」,把模糊样本剔除掉。这个设计让梯度更干净,训练更稳定。
4.6 小结
YOLOv5 的损失函数设计,核心就三句话:
- 框回归用 CIoU,兼顾位置、距离和形状
- 分类和置信度用 BCE,支持多标签,独立判断
- 三部分加权求和,权重靠经验和实验调
调参没有银弹,但记住一个原则:先让模型学会「有没有目标」,再学「在哪儿」,最后学「是什么」。按这个顺序调 λ_obj → λ_box → λ_cls,基本不会跑偏。