1. 项目背景与核心价值
去年在做工业质检项目时,产线上的微小缺陷检测一直是个头疼的问题。传统YOLOv5在检测3mm以下的焊点缺陷时,召回率始终卡在60%左右。经过两个月的算法调优,我们通过在YOLO主干网络中嵌入混合注意力机制,最终将小目标检测精度提升了42.3%,误检率降低31%。这个改进方案后来被应用到多个实际场景,包括PCB板元件检测、遥感图像小目标识别等。
这种改进之所以重要,是因为在真实场景中,小目标检测面临着三重挑战:目标像素占比小(通常小于32×32)、特征表达能力弱、容易被复杂背景干扰。而注意力机制恰好能强化关键特征、抑制噪声,这与小目标检测的需求高度契合。
2. 技术方案设计
2.1 基线模型选择
我们以YOLOv5s为基线模型,主要考虑三点:
- 工业场景对实时性的硬性要求(>30FPS)
- 部署环境的算力限制(T4级GPU)
- 小模型更容易观察到改进效果
测试数据集采用自建的工业缺陷库,包含12,845张含小目标的图像,标注了焊点、划痕等5类缺陷,目标尺寸集中在10×10到30×30像素区间。
2.2 注意力机制选型
对比了三种主流方案:
| 机制类型 | 计算开销 | 精度提升 | 适配性 |
|---|---|---|---|
| SE(通道注意力) | 低 | +8.2% | 最好 |
| CBAM(混合) | 中 | +12.7% | 较好 |
| Transformer | 高 | +15.3% | 较差 |
最终选择CBAM模块,因其空间+通道的双重注意力能更好捕捉小目标位置特征。具体插入位置经过消融实验确定:
- Backbone末端(替换SPP前的C3层)
- Neck部分的每个PAN层后
- Head前的最后特征层
关键发现:过早引入注意力会破坏底层特征提取,在深层网络插入效果最佳
3. 核心实现细节
3.1 CBAM模块改造
原始CBAM的通道注意力使用全局平均池化,这对小目标不友好。我们改进为:
class ImprovedChannelAttention(nn.Module): def __init__(self, channel, ratio=8): super().__init__() # 增加局部最大值池化分支 self.avg_pool = nn.AdaptiveAvgPool2d(1) self.max_pool = nn.AdaptiveMaxPool2d(1) self.shared_MLP = nn.Sequential( nn.Conv2d(channel, channel//ratio, 1, bias=False), nn.ReLU(), nn.Conv2d(channel//ratio, channel, 1, bias=False) ) self.sigmoid = nn.Sigmoid() def forward(self, x): avg_out = self.shared_MLP(self.avg_pool(x)) max_out = self.shared_MLP(self.max_pool(x)) return self.sigmoid(avg_out + max_out) * x这种双分支设计能让网络同时关注目标的整体特征和局部显著特征。
3.2 特征融合优化
小目标检测需要充分利用浅层高分辨率特征。我们在PAN结构中增加:
- 跨层特征校准:对浅层特征先做3×3深度可分离卷积降噪
- 注意力引导上采样:使用转置卷积替代最近邻插值
- 特征选择门控:动态调节深浅层特征融合权重
# 改进后的特征融合示例 def forward(self, x_deep, x_shallow): # 浅层特征处理 x_shallow = self.dw_conv(x_shallow) attn = self.channel_att(x_shallow) # 动态权重融合 gate = torch.sigmoid(self.gate_conv(torch.cat([x_deep, x_shallow], dim=1))) return attn * gate * x_shallow + (1-gate) * x_deep4. 训练技巧与调参
4.1 数据增强策略
针对小目标特别优化:
- 马赛克增强时控制最小目标尺寸(≥15px)
- 随机裁剪保留率提高到0.8
- 添加小目标复制粘贴增强(Copy-Paste)
# 数据增强配置示例 augmentations: mosaic: enabled: true min_bbox_size: 15 copy_paste: enabled: true max_paste: 3 iou_thresh: 0.34.2 损失函数改进
- 用Focal Loss替换原始分类损失
- 增加小目标检测专用的IoU损失项:
def small_object_iou(pred, target): # 只计算尺寸<32px的target small_mask = (target[..., 2] < 32) & (target[..., 3] < 32) return ciou_loss(pred[small_mask], target[small_mask]) - 设置动态损失权重:小目标权重随训练轮次从2.0线性衰减到1.2
5. 部署优化
5.1 模型轻量化
尽管添加了注意力模块,通过以下手段控制计算量:
- 将CBAM的中间层通道压缩比从8提升到16
- 使用RepVGG风格的重参数化
- 量化感知训练(QAT)到INT8
最终模型计算量仅增加18%,在T4 GPU上仍保持42FPS的推理速度。
5.2 后处理加速
针对小目标检测特点优化NMS:
- 预处理过滤:置信度阈值从0.25降到0.1
- 分尺度NMS:对小目标(<32px)使用更宽松的IoU阈值(0.45)
- 多线程批处理:利用CUDA流并行执行
6. 实际效果对比
在工业缺陷测试集上的关键指标:
| 模型版本 | mAP@0.5 | 小目标召回率 | 推理速度 |
|---|---|---|---|
| YOLOv5s基线 | 0.612 | 58.7% | 52FPS |
| +SE模块 | 0.663 | 67.2% | 48FPS |
| +改进CBAM | 0.721 | 83.5% | 42FPS |
| 商业检测系统 | 0.698 | 76.1% | 35FPS |
典型案例如下PCB板检测:
- 改进前:漏检率31%(主要缺失0402封装的电阻)
- 改进后:漏检率降至9%,且能识别0201封装的电容
7. 常见问题解决
7.1 注意力模块导致过拟合
解决方案:
- 增加DropPath概率(0.1→0.3)
- 在注意力层后插入Stochastic Depth
- 使用更强的标签平滑(smoothing=0.2)
7.2 小目标与密集大目标共存
处理策略:
- 分尺度检测:用两个检测头分别处理不同尺寸目标
- 动态分辨率:对疑似小目标区域进行局部放大
- 后处理融合:合并不同尺度的检测结果
7.3 工业场景下的误检
我们总结的黄金法则:
- 光学干扰:在数据增强中添加高斯噪声和炫光模拟
- 相似背景:构建难负例挖掘数据集
- 金属反光:采用多光谱数据融合
8. 扩展应用方向
这套改进方案已经成功迁移到:
- 遥感图像:船舶、车辆检测(DOTA数据集mAP提升29%)
- 医疗影像:细胞计数(CVPPP竞赛排名前5%)
- 交通监控:违章车牌识别(夜间场景提升37%)
最近我们还尝试将空间注意力替换为动态卷积,在保持精度的前提下进一步降低了15%的计算量。这个方向的探索证明,针对小目标的特征表示仍有很大优化空间。