目标检测中的FPN(Feature Pyramid Network)。你将学习FPN的自顶向下路径、横向连接、多尺度特征融合、与小目标检测的关系、在Faster R-CNN中的应用,以及FPN如何解决多尺度目标检测问题提升小目标检测精度,适合CV工程师学习。

学习提示

需要学习FPN特征金字塔,感知模型(BEVFormer/PointPillars)基于深度学习架构。本篇涵盖CNN/RNN/Transformer、反向传播、正则化、训练技巧,帮助你理解深度模型原理与调优。

目录
  1. 可视化演示
  2. AI 应用场景
  3. Python 演示
  4. 常见误区
  5. 面试题

可视化演示

目标检测中的FPN(Feature Pyramid Network)。你将学习FPN的自顶向下路径、横向连接、多尺度特征融合、与小目标检测的关系、在Faster R-CNN中的应用,以及FPN如何解决多尺度目标检测问题提...

多尺度难题

目标检测这栋大楼里,要抓的“人”有大有小:近处的行人像半身像,远处的人像芝麻点。只站在一层看,芝麻点倒是清楚,但你不知道它是人还是杂物;只站在顶楼看,你知道那是人,但芝麻点已经模糊成一团。单一特征层天然只能顾一头。如果只用最后一层高层特征,小目标在 1/32 比例下可能连一个像素都占不满;如果只用第一层低层特征,又缺少“这到底是不是目标”的全局判断。

朴素的做法是图像金字塔:把原图缩成好几个尺寸,分别塞进模型,如同让安保团队坐直升机在不同高度拍照。精度有提升,但计算量成倍增加,推理速度让很多落地项目无法接受。另一个思路是直接在多个特征层上做预测,也就是“多层预测雏形”,但高层语义没有真正回流到低层,低层依然缺少上下文,小目标容易被漏掉。

FPN 的解题思路完全不同:不重复计算整张图,只利用 CNN 天然逐层下采样形成的特征层级,再人为加一条自上而下的通路,把高层的全局语义“广播”到低层。这就是特征金字塔,而不是图像金字塔。像在每层楼安装信息管道,让顶层情报直达每个楼层的保安室,成本低,效果却脱胎换骨。

特征层级

CNN 本身就是一座天然的楼层。最早的卷积层像一楼大厅的保安,能看到每个人的鞋带、耳机线这些局部细节,但不知道这个人要去哪里;越往后的卷积层像越来越高层的指挥官,视野越来越宏观,能说出“这是一个人”,但细节轮廓越来越模糊。这就是特征层级:分辨率从高到低,语义信息从弱到强。

在 ResNet 这类骨干网络里,我们习惯把第 2 到第 5 个阶段的输出称为 C2、C3、C4、C5。C2 分辨率最高,比如原图的 1/4,保留大量边缘和纹理;C5 分辨率最低,比如原图的 1/32,但包含最完整的“目标是什么”的语义。问题是,分辨率与语义在这个天然金字塔里是反向的:想看清小目标,应该用高分辨率;想判断目标类别,应该用高语义。二者在一张特征图里难以兼得。

所以早期检测器往往强行选一层:选高层,大目标分类准,小目标检测差;选低层,小目标定位准,大目标理解差。FPN 的出发点很朴素:既然低层有细节、高层有语义,那就把它们连接起来,让每一层都拥有“高低搭配”的能力。

自顶向下路径

要让每一层都懂全局,首先得把高层的“城市摘要”送下来。想象顶楼会议室有一张巨大的城市全景图,现在要把这张图复印到下面每一层。由于楼层越高,对应的“地图”越小,往下走时必须把地图放大到和下一层相同尺寸。这就是自顶向下路径:从 P5 开始,反复使用上采样操作,把高层特征逐级放大。

Ql=Up2×(Pl+1)\displaystyle Q_l = \mathrm{Up}_{2\times}\left(P_{l+1}\right)
  1. P_{l+1}上一轮已经融合好的高层特征图,也就是楼层更高、视野更大的那个特征。
    Pl+1P_{l+1}
  2. Up_{2\times}(\cdot)两倍上采样操作,把高层地图的长宽各放大一倍。
    Up2×(⋅)\mathrm{Up}_{2\times}(\cdot)
  3. Q_l放大后的临时特征,它只携带高层语义,还没有加入当前层的局部细节。 自顶向下路径一路从 P5 走到 P2,就像电梯逐层停靠。但如果只靠放大顶楼地图,边缘会被磨平,细节像被反复拉伸的照片一样发虚。所以,光有电梯还不够,每一层还需要横向走廊,把本层保安看到的真实细节接进来。
    QlQ_l

横向连接

横向连接是 FPN 最关键的一步。电梯带来的是“模糊但懂全局”的语义地图,本层原始特征提供的是“清晰但不懂全局”的细节图。二者需要合并。但 C 层和 P 层的通道数往往不同,比如 ResNet 的 C5 可能是 2048 通道,而统一金字塔要求 256 通道,直接相加维度不匹配。于是先用一个 1x1 卷积做横向投影,把通道数对齐,再与上采样后的高层特征逐元素相加。

Pl=Conv1×1(Cl)⊕Up2×(Pl+1)\displaystyle P_l = \mathrm{Conv}_{1\times 1}\left(C_l\right) \oplus \mathrm{Up}_{2\times}\left(P_{l+1}\right)
  1. C_lCNN 第 l 个阶段输出的原始特征图,空间细节最丰富。
    ClC_l
  2. Conv_{1\times 1}1x1 卷积,负责把通道数统一到 256,同时做通道间的信息重标定。
    Conv1×1\mathrm{Conv}_{1\times 1}
  3. Up_{2\times}(P_{l+1})上一层融合结果放大后的高层语义图。
    Up2×(Pl+1)\mathrm{Up}_{2\times}\left(P_{l+1}\right)
  4. \oplus逐元素相加,让本层细节和高层语义落在同一张特征图上。 相加之后,每个 P 层还会再接一个 3x3 卷积做平滑修正,消除上采样产生的锯齿和混叠。最高层 P5 没有更高层可上采样,所以它只由 C5 横向投影后卷积得到。至此,每一层既保留了本地细节,又拿到了全局语义,像每个楼层的保安都带上了总部的实时对讲机。
    ⊕\oplus

金字塔构建

有了电梯和走廊,整栋楼就形成了一个完整的 P2 到 P5 金字塔。每个 P 层对应一个步长,步长决定了原图中的一个小区域会被压缩成几个像素。P2 的步长是 4,P3 是 8,P4 是 16,P5 是 32,逐层减半,正好形成一座下宽上窄的楼。

stride(Pl)=2l,l∈{2,3,4,5}\displaystyle \mathrm{stride}\left(P_l\right) = 2^l,\quad l \in \{2,3,4,5\}
  1. stride(P_l)第 l 层金字塔特征图上每个像素对应原图区域的边长。
    stride(Pl)\mathrm{stride}\left(P_l\right)
  2. 2^l2 的 l 次方,P2 是 4,P3 是 8,P4 是 16,P5 是 32。
    2l2^l
  3. l \in \{2,3,4,5\}金字塔只保留这四层,兼顾计算量和多尺度能力。 同时,所有 P 层的通道数统一为 256。这带来一个工程上的好处:检测头可以完全共享。每层都配同一套“安保设备”,不需要分别为每一层设计独立分类器。共享检测头让模型参数更少,也让不同尺度的目标在训练时相互促进。
    l∈{2,3,4,5}l \in \{2,3,4,5\}

小目标检测

小目标为什么难?因为目标尺寸一旦小于步长,下采样后可能只剩一个像素甚至消失。P5 的步长是 32,一个 32 像素高的小人在特征图上只有 1 像素,基本无法提取形状。而 P2 的步长是 4,同一个目标还有 8 像素,足够保留轮廓。FPN 的高明之处,就是让高分辨率的 P2/P3 也获得高层语义,不用再担心“看得清但看不懂”。

为了让小目标匹配到合适层级,FPN 给不同 P 层分配不同大小的锚框:P2 用最小的锚框,越往上锚框越大。基础锚框边长可以写成:

al=32×2 l−2\displaystyle a_l = 32 \times 2^{\,l-2}
  1. 32P2 层的基础锚框边长,专门用来匹配小目标。
    3232
  2. 2^{l-2}层级每升高一层,边长按 2 的幂放大,P2 是 1 倍,P3 是 2 倍,P4 是 4 倍。
    2l−22^{l-2}
  3. a_l第 l 层金字塔使用的基础锚框边长。 训练时,小目标锚框更可能与真实目标框产生足够大的 IoU,从而被选为正样本参与学习。过去小目标在低分辨率特征图上“无框可配”,现在则能在 P2/P3 找到高分辨率落脚点,小目标检测精度自然显著提升。
    ala_l

FPN与检测框架

FPN 不是一个独立检测器,而是一套可插拔的骨架方案。在 Faster R-CNN 中,骨干网络从“只输出最后一层特征”改成“输出 P2 到 P5 金字塔”,RPN 会在每一层上滑动生成候选框。每个 P 层共享同一套 RPN 头,只是锚框尺寸不同。这相当于每个楼层的保安都用同一套设备,但各自巡逻不同尺度的目标。

RPN 生成候选框后,还需要决定从哪个 P 层裁剪特征供分类回归。FPN 论文用了一个层级分配公式:

k=⌊k0+log⁡2wh224⌋\displaystyle k = \left\lfloor k_0 + \log_2 \frac{\sqrt{w h}}{224} \right\rfloor
  1. k_0基准层级,论文中取 4,表示中等目标默认分到 P4。
    k0k_0
  2. \sqrt{w h}目标框宽高的几何平均,用来近似目标尺度。
    wh\sqrt{w h}
  3. 224ImageNet 预训练输入尺寸,作为归一化参考比例。
    224224
  4. \lfloor \cdot \rfloor向下取整,保证 k 一定是整数层级。 大目标会分到 P5 这样低分辨率高层级,小目标会分到 P2 这样高分辨率低层级。Mask R-CNN 也沿用了 FPN 骨架,只是把检测头扩展成“分类 + 回归 + 分割”三路输出。可以说,FPN 之后,多尺度特征金字塔成了目标检测框架的默认标配。
    ⌊⋅⌋\lfloor \cdot \rfloor

AI 应用场景

自动驾驶中的远距离小目标检测

阶段:模型架构设计与选型

解决的问题:高速公路上的行人、锥桶往往距离摄像头很远,在常规 1/32 特征图上只有几个像素,传统单层检测头极易漏检。FPN 把高分辨率 P2/P3 与高层语义结合,让远处小目标也能被稳定识别,同时不会拖慢单次前向推理。

具体案例:某自动驾驶团队在原有 Faster R-CNN 基础上,把骨干从 VGG16 换成 ResNet50+FPN,远程行人的召回率大幅提升,尤其解决了一百五十米外行人在黄昏场景下的漏检问题。

相关角色:计算机视觉算法工程师

卫星遥感与无人机巡检的密集目标识别

阶段:特征提取与检测头设计

解决的问题:遥感图像中车辆、船只、光伏板裂纹都极小且密集,如果使用图像金字塔反复缩放整张图,计算资源会失控。FPN 用一次前向就得到多尺度特征,配合小锚框,能兼顾密集小目标。

具体案例:在无人机拍摄的输电线路巡检图中,使用 FPN 作为 Faster R-CNN 骨架检测绝缘子缺陷和细小锈蚀点,相比单层特征方法,微小缺陷的召回率明显提高。

相关角色:AI 算法工程师

工业质检中的微小表面缺陷检测

阶段:模型训练与调优

解决的问题:流水线上的划痕、针孔、焊点偏移常常只有几十个像素,和背景高度相似。FPN 让低层细节不因下采样而丢失,又让高层语义帮助判断“这是缺陷还是纹理”。

具体案例:PCB 板质检系统中,使用 FPN+RetinaNet 替代手工特征加单层检测器,微小焊点缺陷的漏检率降低约一半,同时保持实时检测帧率。

相关角色:视觉检测算法工程师

Python 演示

python45 行
import torchimport torch.nn as nnimport torch.nn.functional as F  class SimpleFPN(nn.Module):    """A minimal FPN that accepts [C2, C3, C4, C5]."""     def init(self, in_channels_list, out_channels=256):        super().init()        self.lateral_convs = nn.ModuleList()        self.smooth_convs = nn.ModuleList()        for in_ch in in_channels_list:            self.lateral_convs.append(nn.Conv2d(in_ch, out_channels, 1))            self.smooth_convs.append(nn.Conv2d(out_channels, out_channels, 3, padding=1))     def forward(self, feats):        laterals = []        for conv, feat in zip(self.lateral_convs, feats):            laterals.append(conv(feat))         outs = []        prev = laterals[-1]        for i in range(len(laterals) - 1, -1, -1):            if i < len(laterals) - 1:                up = F.interpolate(prev, size=laterals[i].shape[-2:], mode='nearest')                prev = laterals[i] + up            outs.append(prev)        outs.reverse()        outs = [smooth(out) for smooth, out in zip(self.smooth_convs, outs)]        return outs  if name == "main":    torch.manual_seed(0)    fpn = SimpleFPN([64, 128, 256, 512])    inputs = [        torch.randn(1, 64, 56, 56),        torch.randn(1, 128, 28, 28),        torch.randn(1, 256, 14, 14),        torch.randn(1, 512, 7, 7),    ]    outputs = fpn(inputs)    for i, out in enumerate(outputs):        print("P%d: %s" % (i + 2, tuple(out.shape)))

常见误区

误区新手看结构图时,以为 FPN 把 C2 到 C5 全部放大到同一尺寸后加在一起,得到一个“超级特征图”,然后在这个图上检测所有目标。

正解FPN 不是把所有层直接相加。它是相邻层级逐级融合:高层特征只先传给紧邻的下一层,和那一层的横向投影相加,得到新 P 层,再继续往下传。每层保留自己的分辨率和步长,形成真正的多尺度金字塔,而不是一张大杂烩地图。

为何常见:结构图里多条连线汇聚到同一处,很容易让人以为是“全部上采样后相加”;忽略了逐级传递的楼梯结构。

误区FPN 很高效,原图只需要一次前向,所以图像金字塔应该被彻底淘汰,多尺度测试完全没有必要。

正解FPN 解决的是“一次输入下的多尺度特征”问题;图像金字塔通过多次缩放输入,捕获更大的尺度变化,精度上限更高,但计算成倍增加。两者不是绝对替代关系,追求极限精度时常常叠加使用,比如在测试阶段把多尺度测试和 FPN 结合。

为何常见:论文强调 FPN 高效,读者容易把它绝对化成“万能替代品”,忽略了精度与算力的权衡。

误区既然要融合,把 C_l 原始特征和上采样高层特征直接相加就行,不需要额外的卷积操作。

正解原始 C 层通道数和金字塔统一通道数通常不同,比如 C5 可能是 2048 通道,而 P 层是 256 通道,直接相加会维度不匹配。1x1 卷积除了对齐通道,还能做跨通道的信息重标定,让融合更稳定。

为何常见:结构图中“加法”符号最显眼,而紧跟 C 层的 1x1 卷积比较小,容易被一眼略过。

误区因为自顶向下路径不断上采样,最终所有 P 层都会变成和 P2 一样的高分辨率。

正解每一层只上采样一次到下一层的分辨率。P2 仍是原图 1/4,P3 是 1/8,P4 是 1/16,P5 是 1/32。它们只是通道数统一为 256,所以能共享检测头,分辨率并没有被强行拉齐。

为何常见:看到“上采样”三个字就容易想到“放大到最大”,忽略了 FPN 是逐级传递而非全局放大。

误区小目标在 P5 上太小,FPN 通过上采样把小目标区域放大,所以检测器终于能看清它。

正解FPN 的上采样是放大“语义特征图”,不是放大输入图像。小目标真正受益于 P2/P3 本身的高分辨率,它们从下采样开始就没有丢失太多像素;FPN 只是给这些高分辨率层补上了高层语义。目标在特征图上并没有变大,而是被分配到了更合适的层级。

为何常见:上采样和“放大小目标”画面相似,导致把特征图放大误当成图像放大。

面试题

Q1. 在目标检测中使用传统图像金字塔的主要缺点是?

单选题 · easy

  • A.无法检测小目标
  • B.计算成本显著增加← 正确答案
  • C.无法提取语义特征
  • D.特征图分辨率降低

答案:B。图像金字塔通过多次缩放原图来检测多尺度目标,每次缩放都要完整跑一遍网络,计算量成倍增加。它并不是不能检测小目标或不能提取语义,而是太贵,所以 B 正确。

Q2. 关于 FPN 的横向连接,下列说法正确的是?

多选题 · mid

  • A.使用 1x1 卷积对齐通道← 正确答案
  • B.直接删除底层特征
  • C.与上采样特征逐元素相加← 正确答案
  • D.只在高维特征上操作

答案:AC。横向连接先用 1x1 卷积把 C 层通道统一到 256,再与上采样后的高层特征逐元素相加。它不会删除底层特征,也不是只在高维特征上操作,所以 A、C 正确。

Q3. FPN 中所有 P 层统一将通道数设为多少?

单选题 · easy

  • A.64
  • B.128
  • C.256← 正确答案
  • D.512

答案:C。FPN 将 P2 到 P5 的通道数统一为 256。通道一致才能让所有层级共享同一个检测头,减少参数并提高训练稳定性。

Q4. 若 P2 的步长为 4,则 P5 的步长是?

单选题 · mid

  • A.8
  • B.16
  • C.32← 正确答案
  • D.64

答案:C。P2 对应原图 1/4,P3 是 1/8,P4 是 1/16,P5 是 1/32。步长逐级翻倍,所以 P5 的步长是 32。

Q5. FPN 自顶向下路径中,用什么操作扩大高层特征图?

单选题 · easy

  • A.反卷积
  • B.上采样← 正确答案
  • C.空洞卷积
  • D.全局池化

答案:B。FPN 使用上采样把高层特征图的长宽放大两倍,一般是最近邻插值或双线性插值。反卷积也可以放大,但 FPN 原文采用的是无参数上采样,更简洁高效。

Q6. 在 Faster R-CNN 中,RPN 与 FPN 的配合方式是?

单选题 · mid

  • A.只在最高的 P5 层生成候选框
  • B.共享检测头在所有 P 层生成候选框← 正确答案
  • C.每个 P 层独立训练一个完整分类器
  • D.用图像金字塔分别送入 RPN

答案:B。RPN 在 FPN 的每个 P 层上都滑动生成候选框,各层共享同一套卷积头,只是锚框尺寸不同。这样每层负责一个尺度范围,而不是只在最高层工作。

Q7. 以下关于 FPN 的说法正确的是?

多选题 · mid

  • A.P2 分辨率高于 P5← 正确答案
  • B.P 层通道数均为 256← 正确答案
  • C.高层语义会逐级向下传递← 正确答案
  • D.FPN 替代全部锚框机制

答案:ABC。P2 步长小于 P5,所以分辨率更高;所有 P 层通道统一为 256;自顶向下路径让高层语义逐级传递。FPN 并不替代锚框机制,它只是重新分配锚框到不同层级,所以 D 错。

Q8. FPN 将 RoI 分配到特征层的公式中,向下取整的作用是?

单选题 · hard

  • A.提高检测精度
  • B.保证层级为整数← 正确答案
  • C.增大特征分辨率
  • D.减少计算量

答案:B。RoI 分配公式计算出的 k 可能是小数,而我们只能把目标送到 P2、P3、P4、P5 这样的整数层,因此需要向下取整。它的目的不是提高精度或减少计算,而是让分配结果合法。

Q9. FPN 提升小目标检测的主要原因包括?

多选题 · hard

  • A.高分辨率的 P2/P3 参与检测
  • B.小目标不再需要高层语义
  • C.高层语义被补充到低层← 正确答案
  • D.所有目标均被放大处理
  • E.空间细节会大量丢失
  • F.参数数量会成倍增加
  • G.破坏多尺度金字塔结构
  • H.训练过程会容易发散

答案:C。FPN 的核心是让每层保留自己对应的尺度信息,最终在不同分辨率上分别预测。如果全部拉齐到同一分辨率再相加,就只剩一个尺度,等于毁掉了多尺度金字塔结构,也就失去 FPN 的意义。