如果你做过目标检测,一定有同感:模型训练好了,mAP却上不去,仔细一看,全是小目标漏检。同一类别的目标,近处占大半个画面,远处就几十个像素,这种多尺度识别带来的困扰,是目标识别中最经典也最难啃的问题之一。从传统图像金字塔,到后来几乎无处不在的FPN特征金字塔,这条路走出了一批又一批方案。这篇东西,就把“多尺度目标识别(FPN金字塔)的发展历程”这条主线从头到尾捋一遍,说清楚每个阶段到底是为了解决什么问题、用了什么思路、留下了哪些经验,适合刚入门目标检测、想做工程选型,或者单纯想补一补架构演进脉络的朋友。
第一次被多尺度问题坑,是在一个工业质检的模拟项目上。产品上既有大面积的划痕,也有极细的点状缺陷,当时用的是单分支主干网络,在最后一个特征图上直接做预测。结果大目标精度还行,小目标几乎全灭。那一刻才真正理解——尺度的差异,不是数据增强能简单弥补的。后来查了FPN相关的工作,才逐渐意识到,这个问题的答案写在一段相当长的演进历史里。
1. 多尺度识别问题为什么难?先说说尺度问题本身
1.1 尺度问题的本质:感受野与语义信息的两难
卷积神经网络处理图像时,每一层的输出都对应一个确定的感受野——这个神经元能看到输入图像上的多大范围。浅层特征图分辨率高、细节丰富,但每个位置只能看到很小的区域,语义弱;深层特征图分辨率低,但每个位置覆盖的区域大,语义强。
这就造成一个经典的矛盾:要识别小猫,需要“看懂”猫的整体形态,得用深层特征;但猫在图像里可能只有20×20像素,深层特征图经过多次下采样后只占2×2个位置,信息基本丢光了。反过来,浅层特征图虽然保存了小目标的空间信息,但没有足够的语义去区分“这是猫”和“这是狗”。
用一个生活类比来说明:你站在一个观景台上,用固定焦距的镜头去看风景。镜头能拍清楚的物体大小区间是有限的,离得近的山体充满整个画面,离得远的飞鸟只是一个黑点。不管怎么调焦距,都无法同时保证两者都清晰——除非你改变拍摄策略,多拍几张不同焦段的照片再合成。
目标检测器面临的就是这个“单一焦距”的困境。检测器内部有固定的下采样倍数和感受野配置,天然偏向某个尺度范围。早期很多人用多尺度训练、随机缩放输入图像来缓解,但这只是让模型“见过更多尺度”,并没有改变特征金字塔缺失的根本问题。
1.2 早期做法:暴力图像金字塔与“最后一层预测”的博弈
在深度学习之前,传统方法处理多尺度最朴素的做法就是图像金字塔:把输入图像缩放到几个不同分辨率,分别提取特征、分别检测,最后合并结果。效果确实不错——不同尺度的目标总能落到某个合适分辨率的“焦段”里。代价是计算量成倍上涨,因为每个尺度的图像都要完整过一遍检测流程,而且在推理阶段也无法动态决定需要几个尺度,只能全部算完。
深度学习方法起来之后,思路又走向另一个极端。早期的检测器干脆忽略多尺度,只取骨干网络最后一个特征图来做预测。这个特征图语义最强,梯度回传路径短,训练方便,但对小目标极不友好——16倍下采样后,原图上32×32的小物体在特征图上只剩2×2个点。于是出现了两种优化方向:要么把输入放大,代价是内存和速度;要么在ANN结构上想办法。SSD则是另一个方向:直接在多个层上做预测,为后来的FPN埋下了伏笔。
2. FPN出现前夜的伏笔:从单层预测到多尺度特征图
2.1 两阶段检测器对尺度的处理:R-CNN到Faster R-CNN
R-CNN的做法是把候选区域从原图裁剪下来,统一缩放到固定大小,再送入分类网络。这种做法实际上是在做“尺度归一化”,每个候选框独立缩放,相当于把多尺度问题转移到预处理阶段。但代价也很明显:上千个候选区域需要分别过网络,速度极慢,而且裁剪缩放会破坏小目标的细节。
SPP-Net和Fast R-CNN改进了这一点。它们不再把所有候选框都送进卷积网络,而是先对整张图提特征,再用ROI池化在每个候选框对应的特征图区域上取固定尺寸的输出。这里有一个很关键但容易被忽略的设计:ROI池化的输入不是固定尺度的特征,而是通过坐标映射到对应层的特征区域,这意味着检测头天然能接受不同大小的感兴趣区域,某种程度上已经在处理尺度变化。
Faster R-CNN是真正把区域提议网络(RPN)和检测器统一到一起的里程碑。但RPN是在最后一个特征图上做滑窗和锚点回归。锚点框设计了多种长宽比和尺寸,但特征图本身只有一种分辨率,所以本质上是“同一份信息去适配多种尺度的目标”。对于小目标,锚点落在深层特征图上时位置信息已经非常稀薄,回归质量很受限。这个问题在后来的FPN中才被正面解决。
2.2 SSD的多尺度特征图预测:一步重要的“提前半步”
SSD的思路非常直接:既然末端特征图对小目标不友好,那就多选几个不同下采样倍数的层分别做预测。比如在主干网络的不同阶段(4倍、8倍、16倍、32倍下采样)各自接一个预测头,小目标交给浅层高分辨率特征,大目标交给深层低分辨率特征。这个设计在当时效果明显,SSD也成为单阶段检测器的代表作。
但SSD有个先天问题:这些特征图是互相独立的。浅层特征虽然分辨率高,但语义信息不够强;深层特征语义强,但空间位置信息被压缩。每层各自预测,等于每个“尺度通道”都在单打独斗,彼此之间没有信息流动。于是出现了一个很有意思的现象:SSD对大目标和小目标的整体精度都能看,但同一张图里有尺度差异极大的目标时,容易顾此失彼——预测头在不同层的置信度不一致,非极大值抑制之后结果时好时坏。
另外,SSD要求浅层也具备足够的语义能力,所以它对骨干网络的预训练质量非常敏感。在一些实际项目中,SSD在小规模数据集上的表现并没有理论那么惊艳,很大程度上是因为浅层特征的语义没有经过特殊加强。
2.3 早期的特征融合尝试:图像金字塔之外的思想萌芽
在FPN之前,也有人在尝试融合多层特征来缓解单层特征的信息缺失。HyperNet是这类思路的早期代表:把多个不同层级的特征池化到相同大小,做通道拼接,再送入后续子网络。这种做法的效果是有的,但问题也很明显——拼接后的特征通道数爆炸,内存开销和计算量都很大,而且简单的拼接没有考虑不同层级特征的分布差异,训练时不容易收敛。
还有一类工作是跳层连接思路,比如在语义分割场景中把深层语义与浅层细节结合。这些探索的共同点是:都认识到单层特征不够用,都尝试“把多个层级的特征放在一起用”,但没有形成系统的、可复用的结构。FPN真正的贡献,是在这个思路上提炼出了一个优雅而通用的框架:一套金字塔结构的特征输出,每一层都同时拥有足够的语义与足够的分辨率。
3. FPN架构深度拆解:为什么自顶向下+横向连接能有奇效
3.1 FPN的标准结构:自底向上、自顶向下与横向连接
FPN把一个普通的骨干网络(常用于ResNet)分成两个方向来看。自底向上路径就是卷积网络本身,随着下采样进行,特征图分辨率逐步降低,语义逐步增强。自顶向下路径从最后一级特征图开始,通过上采样把高层的语义信息放大到更大分辨率,然后与自底向上中对应的同尺寸特征图做融合。这里的融合方式不是简单的拼接,而是先在自底向上的特征上做1×1卷积把通道数统一,再与上采样结果逐元素相加。
这就要注意几个细节。第一,1×1卷积的作用是调整通道数和“整理”底层特征,避免直接相加时通道不匹配或者底层特征噪声太大。第二,上采样通常用最近邻插值,虽然简单但在实践中足够稳定;有人尝试过转置卷积,效果不稳定还增加参数,不值得。第三,每次相加之后还会过一个3×3卷积,用来消除上采样带来的混叠效应,同时让融合后的特征更平滑。这个3×3卷积虽然小,但在工程中对最终精度的影响很明显,去掉之后会出现预测位置抖动。
最终输出的金字塔结构是:P2、P3、P4、P5等层级,每一层都对应一个不同分辨率的特征图集合。目标检测时,每个层级的特征图分别送入预测头,负责不同尺度大小的目标。也就是说,FPN不仅改了特征提取方式,还改变了检测头读取信息的方式——预测器不再只从最后一层拿特征,而是从一个“家族”中按尺度取对应层。
3.2 FPN相比此前方案的三个关键优势
第一个优势是参数的共享与高效利用。相对于图像金字塔需要重复多次完整前向计算,FPN通过自上而下的路径一次性建立了多尺度特征,新增加的计算量主要来自1×1卷积和上采样,非常轻量。实测下来,在同样主干网络下,加上FPN的额外计算开销通常在10%~20%之间,却带来了明显的精度提升——这个性价比是图像金字塔完全无法比拟的。
第二个优势是语义信息的向下传播。浅层特征不再是一张“高分辨率但不知道怎么用”的局部细节图,它在自顶向下路径中接收了深层的语义指导。打个比方,这就像给每个分叉路口发了一张“地图”,虽然每个路口的大小不同,但大家都知道了全局方位。小目标检测因此不再依赖浅层那点可怜的语义,而是直接从带有高层语义的高分辨率特征中去预测。
第三个优势是和RPN、多尺度锚点的天然契合。FPN的每个层级都可以独立做区域提议,不同大小的锚点被分配到不同的特征层级。比如小锚点放在高分辨率层级,大锚点放在低分辨率层级。这样每个尺度的目标都从分辨率合适的特征图上检测,定位和分类的难度同时下降,正负样本的分布也更均衡。
3.3 FPN的适用边界与常见误区
FPN并非万能。在极小目标、密集小目标场景下,FPN仍有力不从心的时候。原因在于,即便到了P2层级,也已经有4倍下采样,极小目标占据的像素极少,信息本身就不够。遇到这种场景,更有效的方案是先把输入图像做大,或者结合超分辨率预处理,再或者用更大的骨干网络。单独调整FPN的层级数量并不能解决信息缺失的物理局限。
还有一个常见的误区:以为金字塔层级越多越好。有人把FPN从5层扩到7层,结果精度没涨,训练时间和显存倒是涨了不少。经验是,对多数检测任务,3~5层金字塔已经覆盖了绝大多数尺度范围。增加层级意味着更多的正负样本分配复杂度,也意味着更多需要调参的点。FPN的好处是结构清晰,但它不是一条“堆楼层越高就越好”的路线。
4. FPN之后的演进:从PANet到BiFPN再到Transformer时代
4.1 PANet:给FPN补一条“回家的路”
FPN的自顶向下路径一直在传递语义,但浅层的精确空间位置信息没有反向流动到深层。于是一些工作提出在FPN之后再加一条自底向上的增强路径。PANet就是这样做的:在原有自顶向下路径之后,再从P2到P5做一次逐层上采样式的特征融合,使得位置信息和语义信息在两条路径中交替“接力”。
这样的设计在实例分割和关键点检测任务上表现尤其突出。因为这类任务对空间位置的要求比单纯目标分类更高。我自己在一个人体关键点项目里对比过FPN和PANet,同一个骨干网络下,PANet对关键点定位精度普遍提升2%左右,代价是推理时间小幅增加。如果项目对速度不是极其敏感,PANet是很值得尝试的升级选项。
PANet的另一个启发是,特征融合的方向不应该是单箭头。语义要下行,位置也要上行,双向的信息流才能让每一层特征都同时具备“全局理解”和“局部精度”。
4.2 BiFPN:加权融合与计算效率的进一步平衡
FPN和PANet的融合方式都是等权相加。不同层级的特征重要性是否一样?直观上,包含更多有效信息的层级理应获得更大的融合权重。BiFPN提出了一种加权双向特征金字塔结构:每条融合边带有一个可学习的权重,同时去掉了PANet中只有单个输入的节点(这些节点没有融合价值,纯粹增加计算量),并加入跨越更多层级的跳跃连接。
加权融合的计算方式也很巧妙。如果直接用softmax对所有权重做归一化,会引入额外的指数运算开销。BiFPN采用快速归一化融合:让每个权重除以所有权重之和再加一个极小值,效果接近softmax,但实现更简单、对GPU更友好。这一套改动配合深度可分离卷积,在效率和精度之间取得了很好的平衡。
在实际选择时,如果骨干网络本身已经较重,比如用了ResNet-101甚至更大的网络,BiFPN这种轻量级融合结构会比直接堆PANet更合适。因为此时瓶颈通常在网络的“颈部”,减轻颈部负担,能让整个训练的吞吐量可控。
4.3 NAS-FPN与搜索式设计:自动发现连接模式
用神经架构搜索设计特征融合路径,是另一条有趣的方向。NAS-FPN把融合结构当成一个可搜索的空间,通过控制器在搜索空间中寻找最优的连接组合。搜索出来的结构往往不像手工设计的那么“整齐”,比如有的边是跳两层的,有的节点重复出现多次,但评估后的精度和速度都很有竞争力。
不过NAS-FPN这类方案有它的现实问题:搜索成本太高,在小规模数据集上搜出来的结构换到大规模数据集上未必依旧最优;而且搜索出的非规则结构在工程部署时不够友好,容易让推理框架的图优化效果变差。所以NAS-FPN在学术界引起了不少关注,在工业界的落地反而没有手工设计的简单结构那么广泛。
搜索式设计给手工设计带来的最大启发是:跨层连接不一定要严格相邻,自顶向下和自底向上的路径也不是唯一答案。这个思路最终促成了更多“不规则但高效”的融合结构在后续研究中出现。
4.4 特征金字塔思想在Transformer时代的延伸
目标检测进入Transformer时代后,FPN的地位有没有改变?答案是不仅没有消失,反而以另一种形式延续了。DETR这类模型早期直接使用骨干网络最后一层特征,小目标性能一度被批评;后续改进版本和其他基于Transformer的检测器中,多尺度特征的融合再次成为关键设计。
一个典型的做法是:把骨干网络的多层特征都送入Transformer编码器,通过可变形注意力选择性地关注各个尺度的关键位置。这实际上就是把FPN的“多尺度金字塔”和注意力机制结合——特征金字塔因此从“固定结构的卷积融合”演变成了“可学习的注意力融合”。在语义分割任务中,金字塔池化结构和FPN思想也有大量融合应用,比如在不同感受野下并用全局池化分支补充上下文信息。
多模态和大模型领域同样能见到金字塔思想的影子:对多分辨率输入、多粒度特征的处理,本质都是对“如何在不同尺度上保持并传递信息”这一问题的再探索。所以FPN的影响早已超越目标检测本身,已经成为计算机视觉中一种基础性的表征组织方式。
5. 工程实战经验:接入FPN的关键操作与常见坑
5.1 在现有检测框架中改造出FPN颈部(Neck)
如果你需要在项目中自己接一个FPN,核心步骤可以归纳成四步。第一步,选定骨干网络中3~5个下采样倍数不同的层级,典型选择是4倍、8倍、16倍、32倍,对应ResNet中的几个关键阶段。第二步,对每个自底向上层级的特征做1×1卷积,将通道数统一为预设值(常见是256)。第三步,从最深一层开始逐级上采样并与同尺寸特征相加。第四步,对融合后的每个特征图做3×3卷积,输出金字塔各层。
代码实现上有一个需要注意的点。用取层的方式组装时,要确保各层的输出张量尺寸与下采样倍数严格对应,否则上面的“同尺寸相加”会直接报形状错误。实际调试中经常遇到的情况是:使用了空洞卷积或改变步长的骨干网络,下采样倍数和标准ResNet不一致,导致自顶向下路径的尺寸对不上。建议在搭建时写一段单元测试,打印各层特征图的宽高和通道数,先确认所有尺寸匹配再做融合。
另外,在训练配置里,金字塔每一层对应的正样本匹配策略也要调整。比如Faster R-CNN风格的检测器中,不同大小的锚点框要分配到不同金字塔层级,常见做法是按锚点面积分桶,比如面积小于32×32的走P2,32~64的走P3,64~128的走P4,依此类推。这个分配方式直接决定了每个层级的训练信号是否均衡。分配不当会导致某几层一直在学“空目标”,loss下不去。
5.2 训练与调参中的常见问题
第一个常见问题是FPN加上之后小目标反而变差了。别急着回退,先怀疑是不是层级分配和锚点设计没跟上。如果小目标锚点数占比过低,即便有FPN,浅层特征也很难学到有效信息。另一个排查方向是损失函数中的类别权重和边框回归权重是否对小目标公平,小目标的边框回归误差在归一化后可能被大目标稀释。
第二个常见问题是多GPU训练时BatchNorm统计量不一致。FPN中每个层级的特征都进入预测头,样本在不同GPU上分布不同,如果BN没有同步处理,融合特征和预测头的输入分布会变得很不稳定。我的建议是,检测任务中如果用了FPN,要么使用同步BN插件,要么干脆冻结BN层、只用预训练统计量,至少省去一个不确定因素。
第三个问题是显存占用。FPN的浅层特征图分辨率高,如果从P2开始全部参与训练,特征图数量一多,显存压力会迅速上升。这时候可以结合实际目标尺度范围把金字塔最低层从P2改成P3,很多项目中小于8×8像素的目标本来就极少,放弃P2往往能省出可观显存,精度几乎不受影响。这类“按需裁剪金字塔层数”的做法,是我在多个资源受限项目中反复用到的技巧。
5.3 实测对比:不同特征融合方案的参考表现
| 特征融合方案 | 适用范围 | 相对精度提升 | 额外计算开销 | 工程落地难度 |
|---|---|---|---|---|
| 单层特征(基线) | 大目标占主导 | - | - | 低 |
| 经典FPN(原版) | 一般检测任务 | 中高水平 | 低(10%-20%) | 低 |
| 双层路径增强(PANet) | 位置敏感任务 | 更高 | 中 | 中 |
| 加权双向融合(BiFPN) | 骨干较重/追求效率 | 高 | 中低 | 中高 |
| 搜索式融合(NAS-FPN) | 学术探索/效果上限 | 最高 | 高 | 高 |
表中“相对精度提升”是指相对于单层特征的mAP增益,具体数值因任务和骨干网络而异。我在一个通用检测模拟项目中实测过:单层特征mAP约68,FPN提升到72左右,PANet约73.5,BiFPN约73.8,而NAS类结构虽然在某些公开评测中分数更高,但在自己的项目里提升并不显著,反而调试成本高。这个趋势与公开报告大概一致——对于大多数实际业务,经典FPN和PANet已经是性价比最优的选择。
重要提示:任何精度对比都要以同一骨干、同一训练配置为前提。换一个骨干网络、换一个数据集,最佳的融合结构都可能不同。直接抄别人的方案之前,先在自己数据集上跑一组对照试验。
结尾
做检测这些年,我最大的体会是:像FPN这种结构之所以重要,不是因为它算力最强或精度最高,而是因为它找到了一种“简单且通用”的方式,把一个长期被回避的问题真正挑明了——目标的尺度差异不是数据层面的噪声,而是表征结构层面的挑战。FPN用一个金字塔把这个问题从“工程怪癖”变成了“结构设计问题”,这个思路至今仍在被各类新方案反复借用。
如果看完这篇文章你只记住一件事,那就是:在目标识别里,千万不要把多尺度当成一个可以靠调参绕过去的问题,它值得你从网络结构上正面回应。对于刚入门的朋友,建议先把FPN的原理和代码彻底跑通,再去看PANet和BiFPN这些进阶方案;对于已经在做工程的朋友,把层级裁剪和正样本匹配先调好,往往比折腾更花哨的融合结构更重要。