查看全课大纲(第 58 / 93 节)
  1. 1.计算机视觉概述
  2. 2.计算机视觉应用场景
  3. 3.困难与挑战
  4. 4.开源库介绍
  5. 5.图像显示与存储
  6. 6.CLAHE
  7. 7.腐蚀膨胀与开闭运算
  8. 8.滤波与边缘填充
  9. 9.各种滤波
  10. 10.图像金字塔
  11. 11.傅里叶变换
  12. 12.短时傅里叶变换与小波变换
  13. 13.颜色特征与颜色直方图
  14. 14.几何特征_边缘
  15. 15.几何特征-角点与斑点
  16. 16.局部特征-SIFT特征描述子
  17. 17.局部特征-SURF特征描述子
  18. 18.局部特征-ORB特征描述子
  19. 19.其他特征描述子
  20. 20.传统图像分割技术
  21. 21.GraphCut
  22. 22.GrabCut
  23. 23.人脸检测的传统方法
  24. 24.行人检测的传统方法HOG+SVM
  25. 25.行人检测DPM
  26. 26.人工神经网络的架构
  27. 27.目标函数与梯度下降
  28. 28.误差反向传播
  29. 29.可手算的神经网络
  30. 30.改进目标函数与克服梯度消散
  31. 31.神经网络之传统神经网络与深度网络的差异
  32. 32.各种梯度下降算法
  33. 33.如何选择合适的梯度下降算法
  34. 34.避免过适应
  35. 35.CNN的架构
  36. 36.CNN的误差反向传播_卷积层
  37. 37.CNN的误差反向传播_池化层
  38. 38.分类所用的数据集
  39. 39.Alexnet详解
  40. 40.VGG详解
  41. 41.GoogLeNet_v1
  42. 42.BatchNormalization
  43. 43.GoogLeNet_v3v4
  44. 44.ResNet
  45. 45.ResNeXt
  46. 46.CNN设计准则
  47. 47.图像检索与推土机距离
  48. 48.基于颜色相似性
  49. 49.基于形状相似性
  50. 50.基于纹理相似性
  51. 51.基于局部特征相似性
  52. 52.DL的二值哈希编码
  53. 53.高维空间中检索KDTree
  54. 54.高维空间中检索LSH
  55. 55.目标识别任务综述
  56. 56.RCNN
  57. 57.SPP-Net
  58. 58.Fast R-CNN
  59. 59.Faster R-CNN
  60. 60.R-CNN系列模型回顾
  61. 61.R-FCN的设计思路
  62. 62.R-FCN的实现
  63. 63.YOLOv1
  64. 64.YOLOv2_9000
  65. 65.YOLOv3
  66. 66.图像分割应用场景与数据集
  67. 67.上采样的实现方式
  68. 68.FCN网络架构的由来
  69. 69.FCN构建细节
  70. 70.DeepLabv1
  71. 71.CRF
  72. 72.DeepLabv2
  73. 73.DeepLabv3
  74. 74.特定的医学影像分割任务
  75. 75.U-Net
  76. 76.3D U-Net
  77. 77.V-Net
  78. 78.DenseNet
  79. 79.病理切片分析任务及数据集
  80. 80.病理切片分析
  81. 81.图说任务及其传统处理方法
  82. 82.深度语言模型与RNN
  83. 83.LSTM及其变种
  84. 84.NIC模型
  85. 85.SAT模型
  86. 86.图说的性能指标
  87. 87.判别模型与生成模型
  88. 88.KL散度与JS散度
  89. 89.VAE
  90. 90.GAN的基本原理
  91. 91.DCGAN与CGAN
  92. 92.Wasserstein GAN
  93. 93.SRGAN

Fast R-CNN

小象实战讲义 · 基于深度学习的计算机视觉

在上一节我们学习了SPP-Net,它通过共享卷积计算和空间金字塔池化,大幅提升了R-CNN的检测速度。然而,SPP-Net仍然存在训练流程复杂、无法端到端优化等问题。本节将介绍目标检测发展史上的又一里程碑——Fast R-CNN。它通过引入感兴趣区域池化(RoI Pooling) 和多任务损失函数(Multi-task Loss),首次在R-CNN系列中实现了真正的端到端训练,在速度与精度上均取得了显著提升。

💡 核心导读

  • 核心改进:Fast R-CNN在SPP-Net基础上,用RoI Pooling替代SPP层,并设计多任务损失函数将分类与回归统一。
  • 端到端训练:首次在R-CNN系列中把分类与回归并入同一个网络,一次前向、一次反向即可完成训练,所有网络层参数都能参与微调。
  • 性能飞跃:相比R-CNN,训练速度提升近9倍,单图检测速度提升146倍,同时平均精度(mAP)还有所提高。
  • 关键技术:理解RoI Pooling如何将不同尺寸的候选区域映射为固定尺寸特征,以及多任务损失函数如何平衡分类与定位误差。

从SPP-Net到Fast R-CNN的演进

Fast R-CNN的提出,旨在解决R-CNN和SPP-Net遗留的几个关键问题:

  1. 多阶段训练:R-CNN/SPP-Net需要独立训练卷积网络、SVM分类器和边界框回归器,流程繁琐。
  2. 特征存储开销大:需要将中间特征(如fc7层特征)写入磁盘,供SVM和回归器训练,耗费大量存储空间和时间。
  3. SPP-Net的微调限制:由于SPP层的特殊结构,SPP-Net无法对SPP层之前的卷积层参数进行有效的反向传播和微调(fine-tuning)。
  4. 速度仍有瓶颈:尽管SPP-Net共享了卷积计算,但特征提取和后处理流程仍不够高效。

Fast R-CNN的作者Ross Girshick针对这些问题,提出了两个核心创新,一举将目标检测推向了端到端训练的新阶段。

核心创新一:感兴趣区域池化(RoI Pooling)

RoI Pooling可以看作是SPP(Spatial Pyramid Pooling)的一个单层特例。它继承了SPP的核心思想——将任意尺寸的输入转换为固定尺寸的输出,但设计更为简洁高效。

RoI Pooling的工作原理

假设我们有一个候选区域(Region of Interest, RoI),在卷积特征图上的对应区域尺寸为 h × w(例如 5×7,即5行7列)。我们的目标是将它池化为一个固定尺寸 H × W 的输出(在Fast R-CNN的VGG16实现中,常设为 7×7)。

RoI Pooling的步骤如下:

  1. 网格划分:将 h × w 的特征区域划分为 H × W 个大小近似相等的子窗口(bin)。每个子窗口的高度约为 h/H,宽度约为 w/W。由于 h/H 和 w/W 可能不是整数,实际划分时会取整,允许子窗口大小有细微差异。
  2. 最大池化:对每个子窗口内的所有特征值进行最大池化(Max Pooling)操作。
  3. 输出:得到 H × W 的固定尺寸输出。
import numpy as np

# 模拟一个RoI在特征图上的数据 (假设为单通道,便于演示)
# 尺寸为 5行 x 7列
roi_feature_map = np.array([
    [1, 2, 5, 2, 3, 1, 0],
    [8, 4, 6, 7, 2, 1, 3],
    [3, 5, 9, 2, 1, 4, 6],
    [4, 6, 8, 1, 3, 7, 2],
    [2, 3, 4, 5, 6, 2, 1]
], dtype=np.float32)

print("原始RoI特征图 (5x7):")
print(roi_feature_map)
print()

# 目标池化尺寸 H=2, W=2
H, W = 2, 2
h, w = roi_feature_map.shape

# 计算每个bin的大致尺寸
bin_h = h / H  # 2.5
bin_w = w / W  # 3.5

# 进行RoI Pooling
output = np.zeros((H, W), dtype=np.float32)

for i in range(H):
    for j in range(W):
        # 计算当前bin的起始和结束行列索引 (使用取整)
        h_start = int(np.floor(i * bin_h))
        h_end = int(np.ceil((i + 1) * bin_h))
        w_start = int(np.floor(j * bin_w))
        w_end = int(np.ceil((j + 1) * bin_w))
        
        # 确保索引不越界
        h_start, h_end = max(h_start, 0), min(h_end, h)
        w_start, w_end = max(w_start, 0), min(w_end, w)
        
        # 提取当前bin的区域
        bin_region = roi_feature_map[h_start:h_end, w_start:w_end]
        
        # 执行最大池化
        output[i, j] = np.max(bin_region)

print(f"经过RoI Pooling (目标尺寸 {H}x{W}) 后的输出:")
print(output)
原始RoI特征图 (5x7):
[[1. 2. 5. 2. 3. 1. 0.]
 [8. 4. 6. 7. 2. 1. 3.]
 [3. 5. 9. 2. 1. 4. 6.]
 [4. 6. 8. 1. 3. 7. 2.]
 [2. 3. 4. 5. 6. 2. 1.]]

经过RoI Pooling (目标尺寸 2x2) 后的输出:
[[9. 7.]
 [9. 7.]]

与SPP的对比:

  • SPP:使用多个尺度的网格(如 4×4, 2×2, 1×1),然后将所有尺度的池化结果拼接起来,形成一个固定长度的特征向量(如 16+4+1=21 个空间bins)。
  • RoI Pooling:只使用单一尺度的网格(如 7×7),结构更简单。在这个框架下单尺度网格已经够用:Fast R-CNN 用 RoI Pooling 取得了 66.9% 的 mAP,高于 SPP-Net 的 63.1%;论文把这一提升主要归因于多任务联合训练与卷积层可微调,而不是池化网格的复杂度差异。

RoI Pooling的反向传播

在训练时,RoI Pooling层也需要进行误差反向传播。一个关键细节是:当两个不同的RoI在特征图上存在重叠区域时,该重叠区域的特征点会参与两个RoI的池化计算。

在反向传播时,该特征点将接收来自所有相关RoI的梯度。具体实现中,梯度是累加的。即,对于特征图上的某个点,其梯度等于所有以其作为最大池化响应来源的RoI的梯度之和。

假设特征图上点(x,y)是RoI_A中Bin1的最大值,同时也是RoI_B中Bin2的最大值。
前向传播:
  RoI_A_Bin1的输出 = 值(x,y)
  RoI_B_Bin2的输出 = 值(x,y)

反向传播:
  设RoI_A_Bin1传回的梯度为g_a,RoI_B_Bin2传回的梯度为g_b。
  那么特征图上点(x,y)收到的总梯度 = g_a + g_b。

核心创新二:多任务损失函数(Multi-task Loss)

这是Fast R-CNN实现端到端训练的关键。它不再使用独立的SVM分类器和边界框回归器,而是将分类任务和边界框回归任务统一到一个网络框架下,并用一个联合损失函数进行优化。

边界框回归(Bounding Box Regression)回顾

在R-CNN中我们已介绍过,边界框回归的目的是对Selective Search提出的候选框进行微调,使其更接近真实标注框(Ground Truth)。

对于一个候选框 P=(Px,Py,Pw,Ph)P = (P_x, P_y, P_w, P_h) 和其对应的真实框 G=(Gx,Gy,Gw,Gh)G = (G_x, G_y, G_w, G_h),我们学习一个变换,使得预测框 G′≈GG' \approx G。

变换通过四个参数 (dx,dy,dw,dh)(d_x, d_y, d_w, d_h) 实现:

  • 平移:Gx′=Pwdx(P)+PxG'_x = P_w d_x(P) + P_x, Gy′=Phdy(P)+PyG'_y = P_h d_y(P) + P_y
  • 缩放:Gw′=Pwexp⁡(dw(P))G'_w = P_w \exp(d_w(P)), Gh′=Phexp⁡(dh(P))G'_h = P_h \exp(d_h(P))

需要注意的是,这四个变换是按类别分别学习的:飞机的机翼很长、长颈鹿的脖子很长,不同类别从候选框到真实框的偏移规律并不相同,因此每个类别都要单独训练一组 (dx,dy,dw,dh)(d_x, d_y, d_w, d_h)。

我们需要学习的是这四个函数 d∗(P)d_*(P)。按论文的记号,网络对每个类别输出的预测偏移量记为 tu=(txu,tyu,twu,thu)t^u = (t^u_x, t^u_y, t^u_w, t^u_h),它就是上面四个变换参数在该类别上的取值;而回归目标 v=(vx,vy,vw,vh)v = (v_x, v_y, v_w, v_h) 由真实框 GG 与候选框 PP 直接算出:

vx=(Gx−Px)/Pwvy=(Gy−Py)/Phvw=log⁡(Gw/Pw)vh=log⁡(Gh/Ph)\begin{aligned} v_x &= (G_x - P_x) / P_w \\ v_y &= (G_y - P_y) / P_h \\ v_w &= \log(G_w / P_w) \\ v_h &= \log(G_h / P_h) \end{aligned}

训练的目标就是让网络对真实类别的预测 tut^u 逼近 vv。

这里取对数是为了保证缩放因子 exp⁡(dw)\exp(d_w) 为正数,使预测的宽度和高度始终为正。

多任务损失函数定义

Fast R-CNN的损失函数由两部分加权求和而成:

L(p,u,tu,v)=Lcls(p,u)+λ[u≥1]Lloc(tu,v)L(p, u, t^u, v) = L_{\text{cls}}(p, u) + \lambda [u \geq 1] L_{\text{loc}}(t^u, v)

让我们逐一解析:

  1. Lcls(p,u)L_{\text{cls}}(p, u):分类损失

    • p=(p0,p1,...,pK)p = (p_0, p_1, ..., p_K) 是网络预测的 Softmax 概率分布,共 K+1K+1 个类(K个目标类 + 1个背景类)。
    • uu 是该RoI的真实类别标签(u=0u=0 代表背景,u∈{1,...,K}u \in \lbrace 1, ..., K\rbrace 代表目标类别)。
    • 分类损失采用交叉熵损失(Cross-Entropy Loss),即负对数似然: Lcls(p,u)=−log⁡puL_{\text{cls}}(p, u) = -\log p_u 当预测正确(pup_u 接近1)时,损失接近0;预测错误(pup_u 接近0)时,损失很大。
  2. Lloc(tu,v)L_{\text{loc}}(t^u, v):定位损失

    • tu=(txu,tyu,twu,thu)t^u = (t^u_x, t^u_y, t^u_w, t^u_h) 是网络对真实类别 uu 预测的偏移量,即上面 (dx,dy,dw,dh)(d_x, d_y, d_w, d_h) 这四种变换。
    • v=(vx,vy,vw,vh)v = (v_x, v_y, v_w, v_h) 是由真实框 GG 与候选框 PP 按上面公式算出的回归目标。
    • 定位损失采用 Smooth L1 损失。对于每个坐标 i∈{x,y,w,h}i \in \lbrace x, y, w, h\rbrace: smoothL1(z)={0.5z2if ∣z∣<1∣z∣−0.5otherwise\text{smooth}_{L_1}(z) = \begin{cases} 0.5 z^2 & \text{if } |z| < 1 \\ |z| - 0.5 & \text{otherwise} \end{cases}
      • 当预测值与目标值相差不大时(∣z∣<1|z|<1),使用类似L2损失(平方项),梯度稳定。
      • 当相差较大时(∣z∣≥1|z| \geq 1),使用L1损失(线性项),对异常值(outliers)不敏感,防止梯度爆炸。
    • 总定位损失是四个坐标 Smooth L1 损失的和: Lloc(tu,v)=∑i∈{x,y,w,h}smoothL1(tiu−vi)L_{\text{loc}}(t^u, v) = \sum_{i \in \lbrace x,y,w,h\rbrace } \text{smooth}_{L_1}(t^u_i - v_i)
  3. [u≥1][u \geq 1]:指示函数

    • 这是一个艾弗森括号(Iverson bracket),当条件为真时值为1,否则为0。
    • 只有当前RoI是目标(u≥1u \geq 1)时,定位损失才被计入总损失。 对于背景RoI(u=0u=0),定位损失被忽略,因为背景不需要定位。
  4. λ\lambda:平衡权重

    • 用于平衡分类损失和定位损失的量级。在论文中,λ=1\lambda = 1。
import numpy as np

def smooth_l1_loss(x):
    """计算Smooth L1损失值"""
    abs_x = np.abs(x)
    return np.where(abs_x < 1, 0.5 * abs_x ** 2, abs_x - 0.5)

# 模拟数据
# 假设一个RoI的真实类别是第2类 (u=2,背景为0)
u = 2
K = 20  # 假设有20个目标类别

# 网络预测的Softmax概率 (随机生成,仅演示)
np.random.seed(42)
p = np.random.rand(K + 1)
p = p / p.sum()  # 归一化为概率
print(f"预测概率分布 p (前5个): {p[:5]} ...")
print(f"真实类别 u={u} 对应的概率 p_u = {p[u]:.4f}")

# 计算分类损失
L_cls = -np.log(p[u])
print(f"分类损失 L_cls = -log({p[u]:.4f}) = {L_cls:.4f}")
print()

# 定位部分
# 网络预测的偏移量 t^u (对应四个变换参数)
t_u = np.array([0.15, -0.05, 0.4, 0.1])
# 由真实框与候选框算出的回归目标 v
v = np.array([0.2, -0.1, 0.3, -0.05])

print(f"预测偏移量 t^u: {t_u}")
print(f"回归目标 v:     {v}")
print(f"差值 (t^u - v):  {t_u - v}")

# 计算Smooth L1损失
loc_loss_per_coord = smooth_l1_loss(t_u - v)
L_loc = loc_loss_per_coord.sum()
print(f"各坐标Smooth L1损失: {loc_loss_per_coord}")
print(f"定位损失 L_loc = {L_loc:.4f}")
print()

# 计算总损失 (lambda=1)
lambda_param = 1
# 指示函数: u>=1 为 True,背景(u=0)为False
indicator = 1 if u >= 1 else 0
total_loss = L_cls + lambda_param * indicator * L_loc
print(f"指示函数 [u>=1] = {indicator}")
print(f"总损失 L = {L_cls:.4f} + {lambda_param} * {indicator} * {L_loc:.4f} = {total_loss:.4f}")
预测概率分布 p (前5个): [0.03835183 0.09735042 0.07495408 0.06130091 0.01597586] ...
真实类别 u=2 对应的概率 p_u = 0.0750
分类损失 L_cls = -log(0.0750) = 2.5909

预测偏移量 t^u: [ 0.15 -0.05  0.4   0.1 ]
回归目标 v:     [ 0.2  -0.1   0.3  -0.05]
差值 (t^u - v):  [-0.05  0.05  0.1   0.15]
各坐标Smooth L1损失: [0.00125 0.00125 0.005   0.01125]
定位损失 L_loc = 0.0188

指示函数 [u>=1] = 1
总损失 L = 2.5909 + 1 * 1 * 0.0188 = 2.6096

Fast R-CNN网络架构与训练细节

整体架构

Fast R-CNN的整体流程清晰体现了端到端的思想:

  1. 输入整图:将整张图像输入卷积网络(如VGG16)。
  2. 生成候选区域:使用Selective Search在原始图像上提取约2000个候选区域(RoIs)。Selective Search 是类别无关的,RoI 本身只带坐标;类别标签 uu 与回归目标 vv 是训练时另外提供的监督信号。
  3. 共享特征提取:图像经过卷积网络,得到共享的卷积特征图。
  4. RoI Pooling:对于每个候选区域,根据其在原始图像上的位置,映射到卷积特征图上对应的区域,然后通过RoI Pooling层得到固定尺寸(如7×7×512)的特征块。
  5. 全连接与输出:将固定尺寸的特征块展平,送入一系列全连接层。网络最后有两个并行的输出层:
    • Softmax分类层:输出K+1个类别的概率。
    • 边界框回归层:为每个目标类别各输出4个偏移量 (dx,dy,dw,dh)(dx, dy, dw, dh),共 4K4K 个。注意,计算损失时只采用真实类别 uu 对应的那4个值。
输入图像
     |
     v
卷积网络 (VGG16 Conv1-5)
     |                         生成共享特征图
     v
卷积特征图 (例如: 512通道)
     |                         Selective Search提取RoIs
     |--------------------------------------|
     v                                      v
   RoI Pooling层 (例如: 7x7)           RoI列表 (N个,每个为: 图片索引+4个框坐标)
     |
     v
展平特征向量
     |
     v
全连接层 (FC6, FC7, 例如: 4096维)
     |
     |-----------------------|
     v                       v
Softmax分类层 (K+1维)    Bbox回归层 (4K维)
     |                       |
     v                       v
类别概率                各类别的边界框偏移量

训练策略

  1. 分层采样(Hierarchical Sampling):

    • 由于一张图有约2000个RoI,如果全部用于训练,很多区域是高度相关的(重叠)。Fast R-CNN采用小批量(Mini-batch)训练。
    • 每个Mini-batch包含 2张图像,每张图像采样 64个RoI(共128个)。
    • 这64个RoI中,25%(即16个)是正样本(与某个真实框的IoU ≥ 0.5),75%(即48个)是负样本(IoU在[0.1, 0.5)区间)。设置IoU低阈值0.1是为了挖掘困难负样本(Hard Negative)。
  2. 全连接层加速:

    • 由于RoI数量多,全连接层的前向计算成为瓶颈。Fast R-CNN论文提出使用截断奇异值分解(Truncated SVD) 来加速大型全连接层。
    • 将一个全连接层 y=Wxy = Wx(WW尺寸为 u×vu \times v)近似分解为两个更薄的全连接层:y=W2(W1x)y = W_2(W_1 x),其中 W1W_1 尺寸为 t×vt \times v,W2W_2 尺寸为 u×tu \times t,且 t<min⁡(u,v)t < \min(u, v)。这样可以将计算复杂度从 O(u×v)O(u \times v) 降低到 O(t×(u+v))O(t \times (u + v))。
  3. 微调所有层:

    • 与SPP-Net不同,Fast R-CNN可以通过RoI Pooling层将梯度有效地反向传播到之前的卷积层,因此可以对整个网络的所有层进行端到端的微调。

性能表现与意义

Fast R-CNN在PASCAL VOC数据集上取得了突破性的成果:

模型训练时间 (小时)单图测试时间 (秒)mAP (%)
R-CNN8447.066.0
SPP-Net252.363.1
Fast R-CNN9.50.3266.9
  • 速度:训练速度比R-CNN快8.8倍,测试速度更是快了146倍,达到了接近实时的水平(0.3秒/张)。
  • 精度:mAP不仅远超SPP-Net,甚至比原始的R-CNN还高了0.9%,实现了又快又好。
  • 存储:无需将特征写入磁盘,节省了大量存储空间。
  • 简洁性:统一的模型、端到端的训练流程,大大简化了目标检测系统的开发和训练。

Fast R-CNN的提出,标志着两阶段目标检测器在速度和精度上达到了一个完美的平衡点,并为后续Faster R-CNN的诞生铺平了道路。

📝 动手练一练

  1. 概念辨析:Fast R-CNN中的RoI Pooling与SPP-Net中的SPP层主要区别是什么?为什么RoI Pooling这种简化设计在实验中并没有导致精度下降?
👉 点击查看参考答案

主要区别:

  • 结构复杂度:SPP层使用空间金字塔,即多个尺度的网格(如4×4, 2×2, 1×1),然后将所有结果拼接,形成较长(如21倍通道数)的特征向量。RoI Pooling只使用单一尺度的网格(如7×7),结构更简单。
  • 输出维度:SPP的输出维度是固定的,但由多个尺度的bins拼接而成。RoI Pooling的输出维度就是 H × W × C。

精度未下降的原因:

  1. 信息冗余:深层卷积特征本身具有较高的抽象性和空间不变性。单一尺度的精细网格(如7×7)可能已经足够捕捉到RoI内目标的关键空间信息,多尺度金字塔带来的信息增益有限。
  2. 训练方式带来的增益大于池化网格的差异:Fast R-CNN 让整个网络(含卷积层)参与微调,并用多任务损失联合训练分类与回归。SPP 与 RoI Pooling 本身都是无参数的池化操作,并不存在“参数更少”的区别,精度提升主要来自训练范式的改变。
  3. 训练更稳定:端到端的训练方式使得网络可以自适应地学习如何从固定尺寸的RoI Pooling输出中提取最有效的特征,以完成分类和回归任务。

需要说明的是,Fast R-CNN 论文并没有做“SPP 结构 vs RoI Pooling”的消融实验;它的实测结果是 66.9% mAP,高于 SPP-Net 的 63.1%,论文把差距归于多任务训练与卷积层微调。可以说单尺度网格在这个框架下已经够用,而 RoI Pooling 在速度和简洁性上的优势是确定的。

  1. 损失函数计算:假设在一个Fast R-CNN训练批次中,有一个RoI被标记为背景(u=0)。网络为其预测的Softmax概率分布为 p = [0.8, 0.1, 0.1](假设共3类:背景、猫、狗)。同时,网络还预测了回归偏移量 t^u = [0.1, 0.2, 0.3, 0.4](虽然背景不需要)。请计算该RoI对总损失函数的贡献。设平衡权重 λ=1\lambda = 1。
👉 点击查看参考答案

已知:

  • 真实类别 u = 0 (背景)
  • 预测概率 p = [0.8, 0.1, 0.1],因此 p_u = p[0] = 0.8
  • 网络预测的回归偏移量 t^u 在计算背景损失时不被考虑。

计算:

  1. 分类损失: Lcls=−log⁡(pu)=−log⁡(0.8)≈0.2231L_{\text{cls}} = -\log(p_u) = -\log(0.8) \approx 0.2231

  2. 定位损失: 由于 u = 0,指示函数 [u≥1]=0[u \geq 1] = 0。 因此,无论回归损失 LlocL_{\text{loc}} 是多少,其贡献都为 00。

  3. 总损失: L=Lcls+λ×[u≥1]×Lloc=0.2231+1×0×Lloc=0.2231L = L_{\text{cls}} + \lambda \times [u \geq 1] \times L_{\text{loc}} = 0.2231 + 1 \times 0 \times L_{\text{loc}} = 0.2231

结论:该背景RoI对总损失的贡献仅为分类损失,约为0.2231。回归损失被忽略,这与“背景区域无需精确定位”的直觉一致。

本章小结

Fast R-CNN是目标检测发展史上承前启后的关键模型。它吸收了SPP-Net共享卷积计算的思想,并通过RoI Pooling和多任务损失函数两大创新,成功解决了之前模型训练流程繁琐、存储开销大、无法端到端优化等问题。

  • RoI Pooling:将任意尺寸的候选区域特征转换为固定尺寸,结构比SPP更简洁,且便于梯度反向传播。
  • 多任务损失函数:将分类(交叉熵损失)和边界框回归(Smooth L1损失)统一到一个框架下,通过指示函数和平衡权重协调两者,实现了真正的端到端联合训练。
  • 性能飞跃:在PASCAL VOC 2007数据集上,Fast R-CNN在训练速度、测试速度和检测精度上全面超越了R-CNN和SPP-Net,为实时目标检测奠定了基础。

用今天的眼光看,Fast R-CNN(2015)已是两阶段检测器演进史上的一个阶段:RoI Pooling的坐标量化取整会带来特征错位,2017年被Mask R-CNN的RoI Align取代;检测主流也早已转向YOLO这类单阶段模型与DETR这类Transformer架构。它真正留下的,是“共享卷积 + RoI池化 + 多任务损失”这套训练范式。

Fast R-CNN的成功证明了端到端深度学习在复杂视觉任务中的强大潜力。然而,其候选区域生成模块(Selective Search)仍然是独立、耗时的。这引出了下一个问题:能否用神经网络来生成候选区域,实现完全的端到端? 这正是我们下一节要学习的Faster R-CNN所要回答的。

📋 行动清单

  • 理解RoI Pooling如何将不同大小的区域映射为固定大小的特征,并手动演算一个小例子。
  • 掌握Fast R-CNN多任务损失函数的构成,能明确写出分类损失和定位损失的计算公式,并解释指示函数的作用。
  • 对比R-CNN、SPP-Net和Fast R-CNN在训练流程、速度、精度上的差异,梳理出目标检测模型向端到端演进的清晰脉络。

—— 小象教研组