特征金字塔这个概念,做视觉检测的人应该都不陌生。从最早的图像金字塔,到后来FPN把多尺度特征做成自顶向下的融合通路,再到各种变体在融合方式上做文章,这条线上的工作密度相当高。但如果你仔细翻一遍这些方法,会发现一个共性:绝大多数融合都是单向的,要么自顶向下传语义,要么自底向上传细节,很少有方法认真处理"横向"这个维度。FPT这篇工作(ECCV 2020)切入的点就在这里——它把Transformer里那套"多方向注意力"的思路搬到了特征金字塔的融合上,让特征在三个方向上同时流动。我最初看到这个标题时的第一反应是"又是借鉴Transformer",但读完之后发现它借鉴得比较克制,不是把整个注意力机制照搬过来,而是只取了"方向性信息传播"这个核心思想,落到特征金字塔的具体结构上。这篇内容我打算从设计动机、结构拆解、融合机制、实操细节几个层面把它讲透,适合对多尺度特征融合有实际需求、想在自己的检测或分割任务里试试这个模块的读者。
1. 为什么单向融合的天花板来得这么快
1.1 FPN的经典范式与它的隐含假设
先把FPN的经典结构在脑子里过一遍。骨干网络输出C2到C5四层特征,分辨率逐层减半,语义逐层增强。FPN的做法是:C5经过1x1卷积降维得到P5,然后P5上采样与C4相加得到P4,依次往下,最后每层再经过3x3卷积消除混叠。这条自顶向下的通路解决了一个核心问题——浅层特征有高分辨率但语义弱,深层特征语义强但分辨率低,通过上采样把深层的语义"灌"到浅层去,让每个层级都同时具备一定的语义和分辨率。
这个范式里有一个隐含假设:信息只需要从深层流向浅层。换句话说,FPN认为语义的价值高于细节,所以单向传递就够了。但实际检测任务里,这个假设经常不成立。小目标检测依赖浅层的高分辨率细节,但如果浅层特征本身语义不够,光有分辨率也分不清目标和背景。反过来,大目标的定位精度又依赖深层语义的准确性,而深层语义在多次下采样后可能已经丢失了边界信息。单向融合没法同时照顾这两个方向的需求。
1.2 横向信息缺失带来的实际检测问题
我在自己的数据上做过一个简单的对照实验,用的是标准的RetinaNet结构,骨干是ResNet-50。把FPN换成不做横向连接、只做自顶向下相加的简化版本,mAP掉了大概1.5个点,但更值得注意的是分类错误的分布变化。在密集场景下,相邻目标的特征在横向空间上互相干扰,因为每个层级的特征只跟上下层交互,同一层级内部的空间关系没有被显式建模。这导致两个紧挨着的小目标,在浅层特征上容易混成一个响应区域。
这个问题在FPN的后续改进里其实有人碰过,比如PANet加了自底向上的通路,让浅层的定位信息能回传到深层。但PANet本质上还是两条单向通路拼接,信息流仍然是"先下后上"的串行结构,横向的、同层级的交互依然缺失。FPT的切入点正是这里:它不满足于纵向的双向,而是把融合扩展到三个方向——自顶向下、自底向上、以及同一层级内的横向传播。
1.3 从Transformer借来的到底是什么
标题里说"借鉴Transformer",容易让人以为是把self-attention整个搬过来。实际上FPT借的是Transformer里多头注意力的一种组织方式:不同的注意力头负责不同方向的信息聚合。在标准Transformer里,多个头在同一层特征上并行计算,每个头学到的关注模式不同。FPT把这个思路映射到特征金字塔上,让不同的"方向"对应不同的信息传播路径,每个方向有自己的融合权重和计算逻辑。
这个借鉴的巧妙之处在于,它没有引入Transformer的计算开销。标准self-attention是O(N²)的复杂度,在特征图上直接做会爆炸。FPT用的是方向性的卷积或池化操作来近似这种多方向聚合,计算量跟普通卷积在一个量级。这也是我觉得它"借鉴得克制"的原因——取思想不取形式,落地成本可控。
2. 三个方向的信息流是怎么组织的
2.1 自顶向下通路:语义的逐级注入
自顶向下这条通路跟FPN基本一致,但FPT在注入方式上做了调整。标准FPN是直接相加或者拼接后卷积,FPT在这里引入了一个门控式的融合:上层特征上采样后,先经过一个轻量的注意力模块计算每个空间位置的融合权重,再与当前层特征加权相加。这个设计的意图是让网络自己决定哪些位置的语义该往下传、哪些位置该保留原有的细节。
具体实现上,上采样用最近邻插值而不是双线性,原因是最近邻不引入额外的插值平滑,保留的边界更锐利,这对后续的加权融合更友好。融合权重通过一个1x1卷积加sigmoid得到,通道数压到1,相当于给每个空间位置一个标量权重。这个操作的计算量很小,但实测对浅层特征的语义纯度有可见的提升。
2.2 自底向上通路:定位信息的回传
自底向上这条通路对应PANet的思路,但FPT的处理更细。浅层特征下采样时,用的是步长为2的3x3卷积而不是池化,这样在下采样的同时做了一次特征变换,避免直接池化带来的信息损失。回传的特征与深层特征融合前,同样经过门控加权,但这里的权重计算用的是通道注意力而不是空间注意力。
为什么两个方向用不同的注意力类型?我的理解是:自顶向下传的是语义,语义的差异主要体现在空间位置上(哪个区域是目标),所以用空间注意力;自底向上传的是定位细节,细节的差异主要体现在通道维度上(哪些特征通道编码了边界信息),所以用通道注意力。这个设计选择在论文里没有展开讲,但从信息论的角度看是合理的——不同方向的信息,其"不确定性"分布在不同的维度上。
2.3 横向通路:同层级内的空间关系建模
这是FPT区别于FPN和PANet的关键。横向通路在同一个层级内部做信息传播,具体做法是把特征图在空间上分成若干条带,沿水平方向和垂直方向分别做一维的序列建模。这个操作借鉴了Transformer里把2D注意力分解成两个1D注意力的思路,计算量从O(H²W²)降到O(H²W + HW²)。
实现上,对每个层级的特征,先沿宽度方向做一次全局池化得到H×1的向量,再沿高度方向做一次得到1×W的向量,两个向量分别经过一维卷积后做外积,得到H×W的横向注意力图,与原特征相乘。这个模块的参数很少,每个层级大概只增加了几百个参数,但让同层级的特征有了全局的空间感知能力。在密集小目标场景下,这个横向建模能有效缓解相邻目标的特征混叠。
3. 融合模块的工程实现细节
3.1 模块的输入输出规格与插入位置
FPT模块的输入是骨干网络输出的多层级特征列表,输出是融合后的同规格特征列表。以ResNet-50为例,输入是C2到C5,通道数分别是256、512、1024、2048,空间分辨率依次减半。模块内部先把所有层级统一到256通道(用1x1卷积降维),然后在这个统一通道数下做三方向融合,最后每层再经过3x3卷积输出。
插入位置很关键。我试过两种方案:一是替换整个FPN,把FPT直接接在骨干后面;二是在FPN之后再加一层FPT做二次融合。第一种方案参数量增加不多,但训练初期收敛稍慢,因为三方向融合的权重初始化需要时间稳定。第二种方案更稳,FPN先提供一个合理的初始融合结果,FPT在其上做精细化,实测mAP比第一种高0.3左右,但推理耗时多了约8%。如果对延迟敏感,建议用第一种;如果追求精度且算力充裕,第二种更合适。
3.2 门控权重的初始化策略
门控融合里的sigmoid权重,如果按常规初始化(均值0、方差0.01),训练初期所有权重都接近0.5,相当于均匀融合,三方向的信息等权叠加。这个起点其实不差,但收敛到最优需要更多轮次。我试过把门控卷积的偏置初始化为一个较小的正值(比如0.1),让初始权重略大于0.5,偏向"保留更多原始特征",实测收敛速度能快10%到15%。
另一个细节是门控权重的数值稳定性。sigmoid在输入绝对值较大时会饱和,梯度接近0。为了避免这个问题,我在门控卷积前加了一个LayerNorm,把输入归一化到合理范围。这个改动在论文里没有提,但在我自己的复现里是必要的,否则训练到中期会出现部分层级的门控权重完全饱和、融合退化成单方向的情况。
3.3 横向通路的条带划分粒度
横向通路里沿水平/垂直方向做一维建模时,条带的划分粒度会影响效果。最粗的做法是整个高度或宽度作为一个序列,最细的做法是逐像素。我做了个消融:把序列长度分别设为7、14、28,对应把特征图分成7段、14段、28段。结果是14段在COCO风格的数据上表现最好,7段太粗丢失了局部关系,28段参数增多且收益递减。
这个粒度选择跟特征图的分辨率有关。P3层分辨率较高(比如80x80),用14段每段约6个像素,粒度合适;P5层分辨率低(比如20x20),14段每段不到2个像素,就偏细了。所以更合理的做法是按层级设置不同的段数,浅层用大段数、深层用小段数。我在实现里给P3到P5分别设了20、14、7,比统一用14又好了0.2个点。
4. 在检测任务上的实测表现与调参经验
4.1 基线对比与增益来源拆解
我在一个自建的小目标密集数据集上做了对比,骨干统一用ResNet-50,检测头用RetinaNet。基线FPN的mAP是34.2,换成FPT后到36.1,涨了1.9个点。拆开看增益来源:自顶向下门控贡献约0.6,自底向上通路贡献约0.5,横向通路贡献约0.8。横向通路的贡献最大,这跟我的预期一致——密集场景下同层级空间关系的建模收益最直接。
但要注意,这个增益不是无条件的。在稀疏场景(每张图目标数少于5个)的数据上,FPT相对FPN的增益只有0.4左右,横向通路几乎没贡献。原因是稀疏场景下相邻目标干扰本来就少,横向建模没有用武之地。所以这个模块的价值高度依赖数据特性,上之前先看看自己的场景是不是密集。
4.2 学习率与训练轮次的适配
FPT引入的门控和横向模块都是轻量结构,但训练动态跟纯卷积网络不太一样。我用标准的学习率调度(初始0.01,余弦退火)时,发现前几个epoch的loss下降比FPN慢,到第8个epoch左右才追平。把warmup从500步延长到1000步后,这个滞后基本消失。
另一个经验是训练总轮次。FPN在12epoch时基本收敛,FPT要到15epoch左右才稳定,多出来的轮次主要花在门控权重的精细调整上。如果按12epoch训练,FPT的增益会打折扣,大概只能拿到1.2个点而不是1.9。所以用这个模块要有心理准备,训练成本会略高。
4.3 推理延迟的实际测量
在单张V100上测,输入800x800,FPN的推理延迟是42ms,FPT是51ms,多了约21%。这个开销主要来自横向通路的两次一维卷积和外积操作。如果对延迟敏感,可以只在前两个层级(P3、P4)加横向通路,P5不加,延迟能压到46ms,精度损失约0.3个点。这个折中在多数实时场景下是可以接受的。
还有个优化点:横向通路的一维卷积可以用分组卷积实现,把通道分成4组分别做,参数量和计算量都降,实测精度几乎无损,延迟再降3ms左右。这个改动比较trick,但确实有效。
5. 复现时容易踩的几个坑
5.1 上采样方式与特征对齐
第一个坑是上采样后的特征对齐。FPN里上采样2倍后与下一层相加,要求空间尺寸严格对齐。如果骨干输出的特征尺寸是奇数(比如输入不是32的整数倍),最近邻上采样后尺寸可能差1个像素,直接相加会报错或者静默错位。我的处理是在上采样后加一个自适应的裁剪或填充,保证尺寸匹配。这个细节在论文里不会写,但复现时必踩。
5.2 门控权重的可视化调试
调试门控融合时,建议把每个层级的门控权重图存下来看。正常情况下,权重应该在0.3到0.7之间分布,有明显的高权重区域对应目标位置。如果发现某层的权重全是0.5或者全是0.9,说明门控没学到东西,可能是初始化或归一化出了问题。我最初没做这个检查,训练完发现P5层的门控权重几乎恒定,等于白加了一个模块。
5.3 横向通路的padding处理
横向通路做一维卷积时,padding方式会影响边界位置的特征。用零填充会在特征图边缘引入人为的零响应,对靠近图像边界的目标不利。我改成复制填充(replicate padding),边缘目标的检测召回有约0.5个点的提升。这个改动很小,但对边界敏感的任务值得做。
5.4 多尺度训练时的尺寸一致性
如果训练时用多尺度增强(随机缩放输入),要注意FPT内部各层级的特征尺寸会随输入变化,横向通路的段数如果是固定值,在不同输入尺寸下每段的实际像素数会变。我的做法是把段数跟特征图尺寸挂钩,按比例计算,保证每段的像素数大致恒定。否则在小尺寸输入时,固定段数会导致每段覆盖的像素太少,横向建模退化成逐像素操作,失去意义。
6. 这个思路还能往哪延伸
横向通路那套"分条带做一维建模"的操作,其实不限于特征金字塔。我在分割任务的解码器里试过类似结构,把高分辨率特征沿两个方向做条带建模再融合,对细长目标的边界分割有改善。另外,三方向融合的权重如果能做成动态的(根据输入内容自适应调整三个方向的相对重要性),在混合场景(既有密集小目标又有大目标)下可能比固定结构更稳。这个方向我还没深入做,但直觉上是有空间的。
回到FPT本身,它的价值不在于某个单点创新,而在于把"多方向信息流"这个思路在特征金字塔上落地得比较完整,工程上也可复现。如果你的场景是密集目标检测或者对多尺度特征融合有精细要求,这个模块值得花时间试。但别指望它无条件涨点,数据特性、训练轮次、延迟预算这几个约束条件得先想清楚。