075.小目标检测优化:针对YOLO的小目标检测改进策略
一、深夜调参现场:为什么我的YOLO总是漏掉远处的小车?
上周三凌晨两点,实验室的咖啡机已经空转了三轮。显示器上,测试视频里那些远处的小车像幽灵一样,在YOLOv5的检测框里时隐时现。mAP看着还行,但实际场景里小目标的漏检率让人抓狂——这不是数字游戏,是自动驾驶项目里要命的问题。
小目标检测的痛点太典型了:像素少、特征弱、容易被背景噪声淹没。YOLO这类单阶段检测器天生对尺度敏感,默认的anchor设置和特征金字塔设计,往往更偏爱中大型目标。今天我们就拆开YOLO的“黑盒子”,聊聊那些真正在工程里踩过坑的优化策略。
二、从数据层面:别急着改模型,先看看你的数据“喂饱”没
很多团队一上来就魔改网络结构,其实数据层面的优化往往性价比最高。小目标检测的第一道坎,是数据本身。
数据增强要带脑子做。Mosaic增强确实能模拟小目标场景,但别无脑用——小目标经过随机缩放后可能变得比像素点还小,反而引入噪声。建议加个尺寸过滤,比如目标宽度小于4像素的直接舍弃。代码里可以这么写:
# 过滤过小目标,避免增强后变成噪声
if w < 4 or h < 4:
continue # 跳过这个目标,别让噪声进训练集
过采样小目标丰富的图片。数据集里通常小目标占比少,训练时模型自然“偷懒”。简单粗暴但有效的方法:统计每张图里小目标数量,对前20%的图片做重复采样。注意别过度,否则容易过拟合到特定场景。
标签要不要做模糊处理? 小目标的边界框本身就有歧义,几个像素的偏差IoU就掉很多。有人尝试对小目标标签做轻微模糊(比如框扩大1-2像素),在实测中能提升1-2个点的召回率,但前提是后处理NMS阈值要相应调整。
三、网络结构改动:动刀子的三个关键位置
如果数据清洗完了效果还不理想,就得动模型了。这里有三处改动值得优先尝试。
1. 输入端:自适应锚框计算
YOLO默认的锚框是基于COCO等通用数据集聚类的,你的小目标场景很可能不匹配。跑一遍你自己的数据集聚类:
# 用自己的数据重新聚类锚框
python utils/autoanchor.py --data your_data.yaml
聚类时注意限制最大锚框尺寸,避免锚框都偏向大目标。我一般会设个上限(比如stride的4倍),强迫算法关注小尺度。
2. 特征金字塔:加一层更浅的检测头
YOLO的检测头通常接在P3、P4、P5特征层(对应下采样8、16、32倍)。小目标在P3上都已经只剩几个像素了。最直接的改进:加一个P2检测头(下采样4倍)。但这里有个坑——浅层特征语义信息弱,直接接检测头效果很差。
正确做法:在PANet结构里,让P2层不仅接收自上而下的特征,还要做一次额外的浅层融合。比如从backbone的早期阶段引一条跳跃连接,和降采样后的特征做concat。注意通道数对齐,别让参数量爆炸。
3. 检测头解耦:分类和回归任务分开
小目标对定位精度更敏感,而分类任务相对容易。YOLO的检测头通常共享卷积,但分类和回归的需求本质不同。可以试试解耦头(Decoupled Head)——用两个分支分别处理分类和回归。实测在小目标上,解耦头能稳定提升0.5-1%的mAP,代价是推理速度下降5-10%。工程上要权衡。
四、损失函数调优:让模型“更在意”小目标
损失函数是引导模型学习的指挥棒。默认的损失函数里,小目标因为数量少、损失值小,容易被大目标“淹没”。
1. 回归损失用CIoU,但加尺度权重
CIoU比GIoU更适合小目标,因为它考虑了中心点距离。但还不够——在CIoU基础上,给每个目标加一个尺度权重系数:
# 给小目标更高的回归权重
scale_weight = 2.0 / (w * h).sqrt() # 面积越小,权重越高
loss_box *= scale_weight.mean()
注意要做归一化,否则训练会不稳定。这个trick在无人机检测项目里,让小目标召回率提升了3个百分点。
2. 分类损失的温度系数
小目标特征模糊,分类置信度普遍偏低。可以尝试在分类损失里加温度系数,软化标签:
# 软化分类标签,给模型更多学习空间
cls_targets = cls_targets * 0.9 + 0.1 / num_classes # 别用太狠,0.9-0.95之间
这招对密集小目标场景(比如人群计数)特别有用。
五、后处理陷阱:NMS是怎么“误杀”小目标的
模型输出不错,但最后的结果还是漏?问题可能出在后处理。标准NMS(非极大值抑制)有个隐藏的坑:它按置信度排序,依次抑制重叠框。小目标往往置信度偏低,容易被旁边大目标的框抑制掉。
改进方案1:改用Soft-NMS
Soft-NMS不直接删除重叠框,而是降低它们的置信度。对于小目标密集场景(比如卫星图像里的车辆),改用Soft-NMS能让小目标存活率明显提升。代码实现简单,但推理速度会慢一点。
改进方案2:分尺度做NMS
更工程化的做法:把检测结果按目标尺寸分组,分别做NMS。大目标组用高IoU阈值(如0.7),小目标组用低阈值(如0.4)。最后再合并结果。这个方法在计算量上稍微增加,但避免了尺度间的相互压制。
六、工程经验:哪些策略真的值得上线
折腾了这么多策略,不是所有都值得部署到生产环境。根据我们团队在安防、自动驾驶、遥感三个领域的落地经验,给出以下建议:
数据层面必须做透。数据增强、过采样、标签清洗,这些工作性价比最高,且不影响推理速度。特别是小目标尺寸过滤,几乎零成本但效果显著。
网络改动优先加P2检测头。这是提升小目标性能最直接的手段,虽然计算量增加,但可以通过剪枝或量化弥补。解耦头可以尝试,但要注意速度损耗。
损失函数调优要谨慎。加尺度权重效果明显,但一定要做好归一化,否则训练容易崩。温度系数是个双刃剑,调不好反而会让分类模糊。
后处理改进上线风险低。Soft-NMS或分尺度NMS不涉及模型重训,可以快速A/B测试。建议作为标准后处理选项之一。
最后说个反直觉的发现:有时候降低输入分辨率反而能提升小目标检测率。特别是当原始图像里小目标已经小于检测网络的最小感受野时,降采样反而能让特征更紧凑。不妨试试把输入从640降到512,观察小目标召回率的变化。
七、写在最后:小目标检测没有银弹
小目标检测是个系统工程问题,从数据标注质量到模型部署,每个环节都可能成为瓶颈。我的经验是:先保证数据质量,再调模型结构,最后优化损失和后处理。别迷信某个“神奇”的改进模块,多在自己的数据集上做消融实验。
最深的那个坑,往往不在算法里,而在业务逻辑和实际场景的错配。比如,你以为的“小目标”在算法眼里可能已经是噪声。多跑实地测试,多看bad case,比刷高那0.1%的mAP更有价值。
调小目标检测就像在显微镜下修手表——需要耐心,更需要知道哪里是真正的发力点。祝各位调参顺利,少掉头发。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)