损失函数改进:CIoU, DIoU, GIoU 对比与选用
上周调一个嵌入式端的行人检测模型,在树莓派上跑YOLO,发现边界框总是“抖”——相邻帧的预测框位置来回跳,明明目标没动。用默认的IoU Loss训练出来的模型,在嵌入式设备上部署就是这德行。问题出在哪?损失函数没选对。今天咱们就拆开说说这几个改进版IoU:GIoU、DIoU、CIoU,都是实战里踩坑踩出来的经验。问题出在普通IoU原始的IoU Loss,公式简单:1 - 交集面积/并集面积。但这里有个致命坑:当预测框和真实框没有重叠时,IoU恒为0,梯度直接消失。模型这时候学不到任何东西,相当于训练停滞了。更麻烦的是,IoU只考虑重叠面积,两个框即使中心点差很远,只要重叠面积一样,损失就一样。这导致收敛慢,框的位置回归不准——这就是我那个抖动问题的根源。GIoU:先解决梯度消失GIoU在IoU基础上加了个惩罚项:先找能包住预测框和真实框的最小外接矩形C,然后用(C - 并集)/C作为惩罚。公式是GIoU = IoU - |C - 并集|/|C|。这样一来,即使两个框不重叠,惩罚项也能提供梯度,训练不会卡住。但GIoU也有毛病。我试过在无人机目标检测项目里用GIoU,发现收敛到后期特别慢。为啥?因为一旦两个框完全包含(比如预测框比真实框大且完全包住),GIoU的惩罚项就失效了,退化回IoU。这时候模型想微调框的位置,梯度信号太弱,得迭代很久才动一点。DIoU:把中心点距离拉进来DIoU聪明了点,直接在损失里加中心点距离:DIoU = IoU - ρ²(b, b_gt)/c²。ρ是中心点欧氏距离,c是最小外接矩形的对角线长度。这个改进直击要害——框