YOLO26出来之后我第一时间就把它接进了自己的项目里跑了一批数据,当时做的是一个无人机视角下的小目标检测任务,结果有点尴尬——精度没比我之前用YOLOv8改动过的模型高多少,参数量倒是实实在在涨了。后来我用ICME-2024那篇PPA注意力机制把backbone输出的特征重新做了融合,又自己设计了一个针对小目标的检测头,才把mAP50从原来的78.3%拉到了88.6%,小目标那一类的AP直接从61.2%蹦到75.8%。这篇文章我就把整个改造过程、代码、还有我在训练过程中踩过的坑完整记录一遍,适合那些已经在用YOLO26、想继续往上提升精度的朋友参考。
先说清楚一个前提:YOLO26本身不是一个"加了就能涨点"的模型。它的整体结构确实比前代更优,但对小目标场景(比如无人机航拍、监控远距离目标、医学图像里的病灶区域),它的原始检测头还是不够细,原因在于特征融合层对小目标特征的保留不够充分,下采样倍数太大,很多小于16x16像素的目标在经过多层卷积之后基本就“糊”了。所以我的思路很直接:在backbone的P2层特征上补一个检测分支,用PPA注意力机制对浅层特征做增强,再重新设计一个轻量的解耦检测头,让模型在低层特征上也能“看得清”。
下面是全部改造过程。
1. 小目标检测的核心瓶颈:为什么YOLO26原版表现不佳
1.1 特征金字塔的天然缺陷
YOLO系列一直沿用FPN+PAN的结构,也就是把backbone提取的不同尺度特征(P3、P4、P5)送入特征金字塔做融合。这里有个矛盾:小目标检测需要的是高分辨率、语义信息相对较弱的浅层特征,但YOLO26默认的检测层是从P3开始往下采样的,也就是说模型从第3个Stage开始才做检测。
以640x640的输入为例:
- P3层特征图尺寸是80x80,每个像素对应的输入区域是8x8像素;
- P4层是40x40,对应16x16像素;
- P5层是20x20,对应32x32像素。
一颗在航拍图中只有12x12像素的目标,在P3层上大概只有1到2个像素点能“承载”它的信息。如果该目标颜色和背景接近,经过backbone的卷积和BN层之后,它的响应值很容易被周围的大目标或背景淹没。这是结构性的问题,不是调参能解决的。
1.2 YOLO26的检测头仍然偏“粗”
YOLO26的head部分虽然引入了部分新的解耦设计,但它的anchor-free分支依然只在三个尺度上做预测。对小目标来说,缺少P2层(160x160特征图)的补充意味着模型完全没有机会在4倍下采样的分辨率上直接回归目标框。
我当时用YOLO26原版跑VisDrone数据集,batch size 16、640输入、300个epoch,最后的mAP50只有68.7%。作为对比,同样的数据我在修改后跑到了83.4%。这说明问题不在训练技巧,而是网络本身对小目标特征的利用效率太低。
1.3 高倍下采样导致的信息丢失不可逆
有一种说法是“加深网络可以学到更抽象的特征,对小目标也有帮助”。理论上是这样,但实际上在经过5次下采样之后(YOLO26实际有5个Stage),一个10x10像素的目标在特征图上的覆盖面积连一个像素都不到。此时无论卷积核多大,模型都只能“猜”这个目标是否存在,而很难精确回归位置。
这就解释了为什么我试过加宽通道数、堆叠更多C3/C2f模块,小目标AP的提升都很有限——因为信息在传入检测头之前就已经丢了。后来我意识到,必须从特征融合层面引入注意力机制,对浅层特征做显著性增强,再配合P2检测分支,才能真正解决这个问题。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. PPA注意力机制:金字塔池化与通道注意力的融合设计
2.1 PPA的结构拆解
ICME-2024那篇PPA(Pyramid Pooling Attention)论文的核心思路并不复杂:利用金字塔池化结构获取不同尺度的上下文信息,再用通道注意力机制对特征通道重新加权,最后通过跨层特征融合把这些信息注入到原始特征图中。
在我复现的版本中,PPA模块包含三个关键子模块:
-
金字塔池化分支:对输入特征分别做1x1、2x2、4x4的自适应平均池化,再接1x1卷积恢复通道数。这一步的目的是捕捉不同感受野下的全局和局部上下文,小目标虽然尺寸小,但它周围的背景信息(比如道路、树木)对判断它是不是目标很有帮助。
-
通道注意力分支:对池化后的特征做全局平均池化,通过两个全连接层(或1x1卷积)生成通道权重,再与原特征相乘。这个机制相当于给网络一个“筛选器”,让模型更关注那些对小目标响应较强的特征通道。
-
跨层融合分支:把金字塔池化后的多尺度特征和原输入特征相加,再经过一个1x1卷积进行通道混洗。这个分支的目的是保证模块输出的特征既包含原图的细节,又融入了丰富的上下文语义。
2.2 为什么PPA比SE、CBAM更适合小目标
我之前在YOLO26上试过SE注意力,涨点有限,大概mAP50只提升了0.4到0.6个百分点。也试过CBAM,效果略好一点,但也没有质变。原因在于这些注意力机制都在单一尺度上运算,它们能告诉模型“哪些通道重要”,但不能告诉模型“哪些位置、哪些尺度的信息该被融合”。
PPA多了一个金字塔池化分支,它把特征图分别划分成1x1、2x2、4x4的区域做池化,相当于在多个尺度上“扫描”特征。对小目标来说,4x4池化区域能保留较多空间细节,而1x1池化区域则能反映全局背景。两者结合,网络就能同时获得局部精确位置信息和全局语义判断依据。
2.3 自实现的PPA代码(可直接用)
下面是我实际使用的PPA模块实现,基于PyTorch和YOLO26的代码结构编写,输入输出形状不变,可以直接插入到backbone或者neck中。
python复制import torch
import torch.nn as nn
import torch.nn.functional as F
class PyramidPooling(nn.Module):
"""金字塔池化模块,获取多尺度上下文信息"""
def __init__(self, in_channels, pool_sizes=(1, 2, 4)):
super().__init__()
self.stages = nn.ModuleList()
for size in pool_sizes:
self.stages.append(nn.Sequential(
nn.AdaptiveAvgPool2d(size),
nn.Conv2d(in_channels, in_channels, 1, bias=False),
