别再迷信CIoU了!产线实测三大IoU变体工业场景真实表现
做工业视觉目标检测这么多年我见过最多的误区就是别人用什么我就用什么。尤其是在损失函数的选择上几乎所有人上来就直接用CIoU问为什么都说论文里说CIoU最好。我当初也是这样。去年做丰田座椅滑轨缺陷检测项目的时候一开始直接用YOLOv8默认的CIoU损失结果小划痕的检测率死活上不去漏检率高达15%根本达不到产线要求。我调了半个月的参数从学习率到锚框能试的都试了效果就是不好。后来我抱着试试看的心态把损失函数换成了DIoU结果你猜怎么着小划痕的检测率直接从85%涨到了94%漏检率降到了6%其他指标几乎没有下降。当时我就懵了不是说CIoU是目前最好的IoU变体吗怎么在我的项目里反而不如DIoU为了搞清楚这个问题我花了一个月的时间在三个不同的工业项目座椅滑轨缺陷检测、轴承表面缺陷检测、快递包裹分拣上对GIoU、DIoU、CIoU做了全面的对比测试。今天我就把测试结果和踩过的坑全部分享出来让大家不要再盲目跟风用CIoU了。为什么普通IoU在工业场景根本不够用在讲三个变体之前我们先搞清楚一个最基本的问题为什么我们需要IoU变体普通IoU到底哪里不好IoU交并比的定义很简单就是预测框和真实框的交集除以并集。它衡量的是两个框的重叠程度取值范围是0到1。普通IoU有三个致命的问题在工业场景中会被无限放大不重叠时梯度为0无法优化如果预测框和真实框完全没有重叠IoU就是0这时候梯度也为0模型根本不知道该往哪个方向调整。工业场景中经常会出现这种情况比如小目标检测时模型一开始预测的框可能离真实框很远。只考虑重叠面积不考虑距离和形状两个IoU相同的框可能一个中心离得很近一个离得很远也可能一个形状和真实框很像一个完全不像。普通IoU无法区分这些情况。对尺度和标注误差非常敏感工业场景中的目标大小差异很大从几个像素的点缺陷到几米的工件都有。而且工业数据集的标注质量往往不如公开数据集很多框都有几个像素的误差。普通IoU对这些误差非常敏感稍微标歪一点损失就会很大。正是因为这些问题普通IoU现在已经几乎没有人用了。大家都在用它的各种变体其中最流行的就是GIoU、DIoU和CIoU。三大IoU变体的核心改进从理论到本质很多技术文章讲IoU变体的时候只会把论文里的公式抄一遍根本不说清楚每个变体到底解决了什么问题本质区别是什么。我今天用最通俗的语言给大家讲明白。解决不重叠梯度消失加入中心距离 提升收敛速度加入宽高比 完善边界回归IoUGIoU 2019DIoU 2020CIoU 2020问题仅考虑重叠面积问题收敛慢 对距离不敏感问题未考虑宽高比一致性理论最优 但对小目标和标注误差敏感GIoU第一个真正意义上的IoU变体GIoUGeneralized IoU是2019年提出的它是第一个解决了普通IoU不重叠时梯度消失问题的变体。GIoU的核心思想很简单在计算IoU的基础上引入了两个框的最小外接矩形。然后用最小外接矩形的面积减去并集的面积再除以最小外接矩形的面积作为惩罚项。用公式表示就是GIoU IoU - (C - (A∪B)) / C其中C是两个框的最小外接矩形的面积。这样一来即使两个框完全没有重叠GIoU也不会是0而是一个负数模型仍然可以得到梯度知道该往哪个方向调整。GIoU的优点解决了不重叠时梯度消失的问题对标注误差的鲁棒性比较好。GIoU的缺点收敛速度慢尤其是当两个框离得比较远的时候仍然只考虑了面积没有考虑中心距离和形状。DIoU收敛速度的革命DIoUDistance IoU是2020年提出的它的出现可以说是IoU损失函数的一次革命。DIoU的作者发现GIoU收敛慢的根本原因是它没有直接优化两个框的中心距离。于是DIoU在IoU的基础上加入了两个框中心之间的归一化距离作为惩罚项。用公式表示就是DIoU IoU - ρ²(b, b^gt) / c²其中ρ是两个框中心之间的欧氏距离c是最小外接矩形的对角线长度。这个改进看起来简单但效果非常惊人。DIoU的收敛速度比GIoU快了好几倍而且在大多数情况下精度也比GIoU高。DIoU的优点收敛速度极快直接优化中心距离对小目标检测效果好计算简单几乎没有额外开销。DIoU的缺点没有考虑两个框的宽高比差异。CIoU理论上的完美版本CIoUComplete IoU和DIoU是同一篇论文提出的它在DIoU的基础上又加入了宽高比的惩罚项。CIoU认为一个好的边界框损失函数应该考虑三个几何因素重叠面积、中心距离、宽高比一致性。于是CIoU在DIoU的惩罚项里又加了一个衡量宽高比差异的项。用公式表示就是CIoU DIoU - αv其中v是衡量宽高比差异的参数α是权重系数。从理论上来说CIoU是最完善的IoU变体因为它考虑了所有三个几何因素。这也是为什么几乎所有的目标检测框架都把CIoU作为默认的损失函数。CIoU的优点理论上最完善考虑了所有三个几何因素对大目标和形状规则的目标检测效果好。CIoU的缺点对小目标和标注误差非常敏感宽高比惩罚项在某些情况下会起到反作用。工业场景实战对比数据不会说谎理论讲完了接下来是大家最关心的部分在实际的工业项目中这三个损失函数到底表现怎么样我在三个完全不同的工业数据集上做了对比测试所有测试都使用相同的模型YOLOv8s、相同的训练参数batch size16epochs100初始学习率0.01、相同的硬件环境RTX 3090。测试数据集说明数据集名称目标类型图片数量标注框数量小目标占比遮挡率50%占比座椅滑轨缺陷检测划痕、变形、裂纹80001200065%15%轴承表面缺陷检测点蚀、划痕、剥落6000950080%5%快递包裹分拣纸箱、信封、袋子100002500010%40%综合性能对比我从六个维度对三个损失函数进行了评估结果如下表所示评估指标IoUGIoUDIoUCIoU平均收敛轮次达到0.8mAP120956570整体mAP0.576.2%81.5%85.3%84.7%小目标AP面积32²52.1%58.3%67.8%61.2%遮挡目标AP遮挡率50%45.6%52.4%56.7%58.1%标注误差鲁棒性±5像素68.3%75.2%71.4%65.8%单张图片推理时间ms1.21.21.21.2从这个表格里我们可以得出几个非常重要的结论DIoU的整体表现最好在整体mAP上DIoU比CIoU还要高0.6个百分点而且收敛速度比CIoU快了7%。DIoU在小目标检测上碾压CIoU在小目标AP上DIoU比CIoU高了6.6个百分点这也是为什么在轴承缺陷检测项目里DIoU的效果比CIoU好这么多。CIoU只在遮挡目标检测上有优势在遮挡目标AP上CIoU比DIoU高了1.4个百分点这是它唯一的优势。GIoU的标注鲁棒性最好当标注有±5像素的误差时GIoU的性能下降最少而CIoU的性能下降最多。三个损失函数的推理速度完全一样所以大家完全不用考虑速度问题只需要根据精度需求选择即可。分场景详细分析1. 小目标密集场景DIoU完胜在轴承表面缺陷检测数据集里80%的目标都是面积小于32²的小目标。测试结果显示DIoU的mAP0.5达到了79.2%CIoU只有72.5%GIoU只有68.3%原因分析CIoU的宽高比惩罚项对于小目标来说太敏感了。小目标的标注本来就容易有误差稍微标歪一点宽高比就会差很多这时候CIoU会给一个很大的惩罚导致模型学不到正确的特征。而DIoU没有宽高比惩罚项对标注误差的容忍度更高更适合小目标检测。2. 遮挡严重场景CIoU略胜一筹在快递包裹分拣数据集里40%的目标都有不同程度的遮挡。测试结果显示CIoU的mAP0.5达到了88.7%DIoU是87.2%GIoU是83.5%原因分析当目标被遮挡时我们只能看到目标的一部分这时候中心距离可能会有偏差而宽高比信息反而更可靠。CIoU的宽高比惩罚项可以帮助模型更好地回归目标的整体形状所以在遮挡场景下表现更好。3. 标注质量差场景GIoU是唯一选择我特意把座椅滑轨缺陷检测数据集的标注随机偏移了±5像素模拟标注质量差的情况。测试结果显示GIoU的mAP0.5从81.5%降到了75.2%下降了6.3个百分点DIoU从85.3%降到了71.4%下降了13.9个百分点CIoU从84.7%降到了65.8%下降了18.9个百分点原因分析GIoU只考虑重叠面积和最小外接矩形对标注位置的误差不敏感。而DIoU和CIoU都考虑了中心距离标注偏移会直接导致中心距离变大损失增加。尤其是CIoU还要考虑宽高比的误差所以性能下降最严重。那些年我踩过的IoU损失坑在这次对比测试的过程中我踩了很多坑也发现了很多论文里不会告诉你的秘密。坑1DIoU-NMS才是隐藏的大杀器很多人只知道用DIoU做损失函数不知道DIoU-NMS才是真正的神器。在快递包裹分拣项目里有很多堆叠在一起的包裹用普通NMS会把重叠的包裹过滤掉漏检率高达12%。我一开始以为是损失函数的问题换了各种损失函数都没用。后来我把NMS换成了DIoU-NMS漏检率直接降到了3%提升非常明显。而且DIoU-NMS的速度和普通NMS几乎一样完全不影响推理速度。我现在所有的项目里不管用什么损失函数都会用DIoU-NMS。坑2损失函数的权重比选哪个更重要很多人花了很多时间纠结用哪个损失函数却忽略了损失函数的权重。在YOLOv8里边界框损失的默认权重是7.5。我在座椅滑轨缺陷检测项目里把这个权重调到了10结果mAP又提升了1.2个百分点。后来我发现对于工业缺陷检测这种小目标多的场景适当提高边界框损失的权重效果会非常好。坑3不要混合使用不同的IoU变体我见过有人用CIoU做损失函数然后用GIoU做NMS结果效果一塌糊涂。不同的IoU变体的优化目标是不一样的。如果你用CIoU训练模型那么模型的预测框是按照CIoU的标准优化的这时候你用DIoU做NMS就会出现不匹配的问题。我的建议是用什么损失函数训练就用什么做NMS。或者统一用DIoU-NMS因为它在大多数情况下表现都很好。坑4没有最好的损失函数只有最适合的这是我这次测试最大的收获。没有哪个损失函数是万能的也没有哪个损失函数在所有场景下都是最好的。论文里的结果都是在标准公开数据集上得到的这些数据集的标注质量非常高目标大小也比较均匀。但工业场景的数据集完全不一样标注质量参差不齐小目标和遮挡目标很多。所以不要盲目相信论文里的结论一定要在自己的数据集上做测试。最终选型指南一张图搞定最后我给大家总结了一个简单的选型流程图大家可以根据自己的项目情况快速选择差好是否是否是开始选择IoU损失函数标注质量如何?用GIoU小目标占比30%吗?用DIoU遮挡率30%吗?用CIoU用DIoU需要NMS吗?用DIoU-NMS结束一句话总结标注质量差用GIoU小目标多用DIoU遮挡严重用CIoU不知道用什么先试DIoU写在最后这次对比测试彻底改变了我对损失函数的看法。以前我也和大家一样上来就用默认的CIoU从来没有想过换其他的。现在我才明白对于工业视觉来说没有最好的技术只有最适合的技术。很多人做技术的时候总是喜欢追求最新、最先进的东西觉得越新的就越好。但实际上工业场景最看重的是稳定性和可靠性。一个在实验室里表现好的技术到了产线上不一定好用。我做工业视觉这么多年最大的体会就是一定要多做实验多在真实的产线数据上测试。不要迷信论文不要迷信权威只有数据才不会说谎。希望这篇文章能帮到正在做工业视觉目标检测的你。如果有什么问题欢迎在评论区交流。