目标检测文献阅读与理解之Fast R-CNN

Posted by Hebi on May 2, 2018

论文题目: Fast R-CNN

论文作者: Ross Girshick

1. 文章梗概

  • 基于R-CNN与SPPnet, 提出了一个clean and fast update——Fast R-CNN

  • Fast R-CNN: 训练、测试时间、mAP较R-CNN有很大的提升(9×, 213× faster, 更高), 较SPPnet也有提升(3×, 10× faster, 更高), 均基于PASCAL VOC2012与VGG16 network

  • Fast R-CNN:

要点1: 一张图片一次性通过CNN提取特征, 再进行selective search与detection
要点2: 去掉warp过程, 增加ROI pooling layer, 目的是为了固定大小, 配合后面的全连接层
要点3: 把SVM检测器换成softmax检测器
要点4: 建立多任务loss函数(对于每个labeled RoI), 联合训练分类与bounding-box回归
要点5: 除selective search之外, 其他都整合为一个过程
要点6: 不需要disk storage(供特征提取使用)

Fast R-CNN 结构图如下(来源于论文Fast R-CNN):

image

2. 研究背景

  • 现有的目标检测模型都是多阶段训练的, 这些模型是slow and inelegant

  • 相比图像分类, 目标检测需要精确的定位, 而这会导致两个问题. 一是要处理的候选proposals非常多. 二是这些候选proposal只能提供粗放的定位. 因此, 对这些问题的解决方案要综合考虑速度、精度、简单度.

2.1. R-CNN的缺点

R-CNN目标检测系统的示意图如下, 下图1来自R-CNN论文, 图2来自Girshick et al. CVPR14

image

image

2.1.1. 多阶段训练

  • fine-tuning: 首先利用log loss微调ConvNet(输入是region proposals), 输出ConvNet features
  • 训练SVMs: 输入是ConvNet features, 这些SVMs取代上述fine-tuning阶段的softmax分类器
  • 训练bounding-box回归器(输入是ConvNet pool5 features)

2.1.2. 训练在空间与时间上消耗大

  • SVM与bounding-box regression训练阶段所需的features从每张图片中的每一个region proposal中提取, 这些特征需要存储在硬盘中, 以供训练SVM与bounding-box regressor

  • 训练耗时多, 存储特征需要很大的空间, 比如采用VGG16网络与VOC2007 trainval set, 训练用时为2.5天, 需要几百GB的存储空间用于存储特征.

2.1.3. 检测慢

  • 采用VGG16网络, 在一块Nvidia K40 GPU(overclocked to 875 MHz)上, 测试时间为47s / image
  • 慢的原因是每一个region proposal都要经过一次ConvNet, 每张图片在选择性搜索阶段产生 ~2000个region proposal, 也就是每张图片就要进行约2000次关于卷积神经网络的计算.

2.2 SPPnet

2.2.1. 共享计算

  • 计算整张图片的卷积feature map, 这份map被用于后续的步骤
  • 加入spatial pyramid pooling layer, 将多种size的feature map池化为固定大小的feature map, 这是为了适配后续的fc layers.
  • SPPnet在检测阶段比RCNN快了10—100倍, 训练阶段比R-CNN快了3倍, 因为共享特征图

下图来自SPPnet论文

image

image

2.2.2. 缺点

  • 与R-CNN一样, 训练都是多阶段进行的, 包含特征提取, 基于log loss微调网络, 训练SVMs, 最后训练bouning-box回归器
  • features也要写入磁盘, 用于后续步骤
  • 在微调阶段, 无法更新spatial pyramid pooling layer之前的卷积层, 这必然会影响检测精度.

3. Fast R-CNN

为解决R-CNN与SPPnet的缺点, 提出Fast R-CNN.

3.1. Fast R-CNN检测系统

  • 检测步骤如下:
    1) 图片通过selective search, 生成region proposals, 作为候选box
    2)该图片再通过ConvNet, 生成一个feature map
    3)feature map与region proposals一起进入ROI Pooling layer, 生成固定规格(7×7)的RoI features
    4)RoI features通过两层fc layers, 生成固定大小的feature vectors, 这份vectors被复制为两份
    5)分类: 一份进入关于分类的fc lyaer, 得到维度为K+1(e.g., 21)的向量cls_score, 再通过softmax layer得到维度为K+1的向量cls_prob
    6) 位置: 一份进入关于位置的fc layer, 得到维度为(K+1)*4(e.g., 84)的向量bbox_pred
    7) 优化: bbox_pred通过bbox regressors(K+1个)生成新的bbox_pred
    

    疑问: bbox regressors在哪个阶段进行训练的??? 这个问题, 现在看起来, 很显然, 只要得到了training RoI的真实targets与预测targets, 计算Loss, 再反向传播, 更新参数, 使得 targets 预测值不断趋近

  • 优点如下:
1)比R-CNN、SPPnet的检测质量(mAP)都高
2) 除了selective search, 其他过程都可以一起训练
3) 采用了多任务loss
4)训练阶段可以更新所有网络层
5) 不需要保存特征, 用于训练, 这是训练一体化的结果

3.2. ROI pooling layer

RoI pooling layer将每个RoI的feature map转换为固定大小的RoI feature map, 伪码如下:

pooled_width = W
pooled_height = H
channels = C
spatial_ratio = 1/16  # 这是图片经过ConvNet缩小的比例
conv_feature_map = ConvNet(image)
RoIs = region_proposal(image)
for roi in RoIs:
    # roi左上、右下顶点的像素坐标, 相对于原图
    roi_x1, roi_y1 = [roi[0], roi[1]] * spatial_ratio  #  左上顶点
    roi_x2, roi_y2 = roi[2], roi[3] * spatial_ratio #  右下顶点
    roi_width = roi_x2 - roi_x1
    roi_height = roi_y2 - roi_y1
    # roi的索引
    roi_index = roi[4]
    # pooled_map的每个像素点的对应的roi区域的宽高, 即构成了pool时的窗口
    window_width = roi_width / pooled_width  
    window_height = roi_height / pooled_height 
    for i in range(pooled_height):
        start_h = roi_y1 + i * window_height
        end_h = roi_y1 + (i + 1) * window_height
        for j in range(pooled_width):
            start_w = roi_x1 + j * window_width
            end_w = roi_x1 + (j + 1) * window_width
            for c in range(channels):
                pooling_conv_map = conv_feature_map[start_h:end_h,  start_w:end_w, c]
                pooled_map[roi_index, i,j, c] = max(pooling_conv_map)

3.3. Fast R-CNN的训练过程

3.3.1. 从预训练模型中初始化

在实验中, 使用了三个预训练模型, 它们具备5个max pooling layer、5-13个conv layer, 它们分别是

  • CaffeNet:AlexNet版的R-CNN, 命名为model S
  • VGG_CNN_M_1024:与model S一样深, 但更宽, 命名为model M
  • VGG16: 这个模型是三个中最深的, 命名为model L

用上述三个预训练模型初始化前, 需要做出三个修改:

  • 用RoI pooling layer取代最后的max pooling layer, 其中RoI pooling layer的输出的宽高是固定的, 这是为了适配后面的fc layer.
  • 用两个slibing layers(fc layer + softmax (K+1 classes), class-specific bounding-box regressors(K+1 个))取代最后的fc layer与softmax layer(1000-classes)
  • 网络的输入改为两个:图片list, 这些图片中的RoIs list

3.3.2. 关于检测的微调

可以利用back-propagation训练所有的参数, 这是Fast R-CNN一项重要的能力.

3.3.2.1 SPPnet无法更新spatial pyramid pooling layer之前层的参数的原因
  • 由于每个训练样本(RoI)来自不同的图片, 经过spatial pyramid pooling layer的back-propagation是高度低效的.
  • 上述低效是由“每个RoI都有感受野(receptive field), 这些感受野常常跨越整张图片”造成的: 由于forward pass必须处理整个感受野, 则训练时的输入是巨大的, 常常是整张图片
3.3.2.2 提出一种更高效的训练方法
  • 本文利用训练阶段的特征共享, 提出一种更高效的训练方法:采用分层抽样, 假设每个mini-batch抽样 R 个RoI, 则先抽样 N 张图片, 再从每张图片中抽样 R/N 个RoI. 如此, 在forward与backward阶段, 来自相同图片的RoIs可以共享计算与内存.

  • 减小 N, 可以减少mini-batch的计算量. 比如, 令 N = 2, R = 128, 上述方法比从128张图片中分别抽样1个RoI(这是SPPnet、R-CNN的抽样策略)快了大约64倍

除了分层抽样, Fast R-CNN把微调过程整合成一条流水线(一同训练, 不需要分段训练), 这个流水线联合训练softmax classifier、class-specific bounding-box regressors, 而不是像R-CNN那样在三个不同的阶段训练softmax分类器、SVMs、bounding-box回归器. 联合训练用到了multi-task loss.

3.3.3. 多任务loss

3.3.3.1. Fast R-CNN的两个输出

Fast R-CNN最后有两个输出, 对于一个training RoI

  • 第一个输出是(K+1)个类别的离散概率分布, 预测该training RoI属于各个类别的概率, 即

通常, $p$ 通过softmax计算最后一个fc layer的(K+1)维输出得到

  • 第二个输出是 $K+1$ 个类别的bounding-box regression targets $t^k$, 即该training RoI 与 潜在 gt box 的bbox regression targets预测值, 有对于 class $k \in \{1,2,..,K\}$,

$t^k$刻画了属于class $k$ 的一个RoI propasal的尺度不变(x轴方向、y轴方向)转换值、对数下高/宽转换值, 具体可看R-CNN中的bounding-box回归.

注意, 这里预测了 K+1 个 bbox regress targets, 实际上计算Loss时只会用到一个类别的 targets 预测值, 具体看下面Loss

3.3.3.2. 定义multi-task loss

每一个training RoI, 都被一个ground-truth class $u \in \; K+1\;\text{classes}$这个$u$怎么定义的? 见下面) 与一个ground-truth bounding-box regression target $v$ 所标记, 这样的training RoI被称之为labled RoI.

基于项目源码, 再复述一下上面的话, 对于一个training RoI,

  1. 找到该training RoI的对应gt box 通过计算它与所有gt box的IoU, 取最大IoU对应的gt box作为该RoI的对应gt box
  2. 确定标记该training RoI的类别 $u$ : 其对应gt box所属类别, 即为该RoI的类别
  3. 计算该training RoI与其对应gt box的bbox regress target实际值 $v$

接下来, 对于上述training RoI, 模型会做出两个预测:

  1. 该 traing RoI 所属(K + 1)个类别的概率 $p = (p_0,\;p_1,\;...,\;p_K)$.
  2. 该 traing RoI 的 (K + 1)个 bbox regress targets 预测值$t^k = (t^k_x,\; t^k_y,\; t^k_w,\; t^k_h)$

注意, 虽然模型预测了 (K+1)个 bbox regress targets, 但计算 Loss 时只用到一个, 该 training RoI 所属类别的 targets, 即$t^u = (t^u_x,\; t^u_y,\; t^u_w,\; t^u_h)$

为了联合训练分类器与bounding-box回归器, 下面为每一个labled RoI( 这个RoI被标记为ground-truth class $u$ 与 ground-truth bounding-box regression target $v$ )定义multi-task loss $L$

其中:

  • 分类 Loss 为
  • $[u \geq 1]$定义如下:

注意到, 被标记为 $u=0$ 的 training RoI 属于 background class, 没有对应的 ground-truth bounding-box, 它们在 $L_\text{loc}$ 中是被忽略的.

有了上述规定后, 对于bounding-box regression, 定义loss

其中,

需要指出的是, 当$|x|$很大时, 上述 $\text{smooth}_{L_1}(x)$$L_1$ loss, 比$L_2$ loss 更不敏感, 更具鲁棒性

3.3.4. mini-batch采样

在微调阶段, mini-batch采取以下抽样策略:

  • ims_per_batch=2:在每个SGD的mini-batch中, 从训练图片集中均匀地随机抽取2张图片(在实际操作中, 在mini-batch训练前, 对整个训练图片集进行shuffle, 最后会得到一个索引list, 该list每个元素中含两张图片, 如此, mini-batch训练时依次从索引list提取一个元素作为mini-batch)
  • mini_batch_size=128: 每个mini-batch会从该批次的图片中, 抽样提取128个RoI, 即从每张图片中提取64个RoI
  • 25%:在mini-batch的128个RoI中, 有25%(32个)的RoIs是这样进行抽样的, 它们从 “与一个ground-truth bounding-box$\text{IoU} \in [0.5,\; 1]$ ” 的RoIs中抽样得到. 这些RoIs被标记为(foreground object)class $u \; \in \{1, 2, ..., K \}$

疑问:这样标记RoI, 不会造成“一个RoI会标记为多个class”吗, 因为一个RoI与多个属于不同类别的ground-truth bounding-box的IoU可能都大于0.5

回答上述疑问: 根据作者给出的源码, 每个 training RoI 事先会有一个”max_overlaps” 与 “max_classes”, 即该 training RoI 与 所有 gt boxes 的 IoU 的最大值, 其对应 gt box 的类别为 “max_classes”该值作为取样时的参考. 因此, 一个 sampling RoI 只会有一个标签.

按照上述理解, 个人认为论文写得不够严谨. “与一个ground-truth bounding-box$\text{IoU} \in [0.5,\; 1]$ ” 应该改为 “与所有ground-truth bounding-boxes的最大 $\text{IoU} \in [0.5,\; 1]$

  • 75%:余下的75%(96个)RoI是这样抽样的, 它们从“与ground-truth bounding-box具有最大IoU属于 [0.1, 0.5) 的RoIs”中抽样得到, 这些RoI称之为”background examples”, 标记为 $u=0$$u$表示class index)

疑问:为什么要“最大IoU”?是不是要跟所有ground-truth bounding-box计算IoU进行比较?论文里没有说明白.

回答上述疑问: 根据作者给出的项目源码, 的确是最大, 是要跟所有ground-truth bounding-box计算IoU进行比较.

在实际操作中, 每个 training RoI 都带有两个属性: roidb['max_classes'], roidb['max_overlaps'], 计算该 training RoI 与 所有 gt boxes 的 IoU, 经过最大值及其索引后, 即可得到这两个属性.

  • 在训练时, 图片以0.5的概率被水平翻转, 除此之外, 未使用无其他数据增强方法

3.3.5. back-propagation through RoI pooling layer

RoI pooling layer的前向传播与后向传播, 在本质上与max-pooling layer(无重叠)是一样, 不同的是:

  • max-pooling: kernel_size、stride、pad是固定的, 而pooling后的map大小由输入map、kernel_size、stride、pad决定

  • RoI pooling: pooling后的map大小是固定的, 而kernel_size、stride由输入RoI决定

3.3.5. SGD超参数的设定

3.3.6. scale invariance

实现尺度不变的目标检测: 两种方式

  • “brute learning” learning: 在训练与测试阶段, 均采用固定的 scale (即固定的长边与短边) 进行 resize

  • image pyramids: 在训练阶段, 对已被加入 minibatch 的图片, 在 image pyramids 中为其随机选取一个 scale 进行按比例 resize

注: 项目源码里的 “按比例 resize” 是这样的, 最短边不大于固定 scale, 长边不超过 max_size, 并保持比例

3.4. 加速检测——采用truncated SVD

利用 SVD 分解, 维数为 u × v 的权重矩阵 $W$ 为

其中, $U$ 是维数为 u × u 的正交矩阵, $V$ 是维数为 v × v 的正交矩阵, $\sum$ 是维数为 u × v 的对角矩阵

  • 对角矩阵 $\sum$ 对角线上的元素称为矩阵 $W$ 的奇异值

  • 正交矩阵 $U$ 的列向量称为矩阵 $W$ 的左奇异向量

  • 正交矩阵 $V$ 的列向量称为矩阵 $W$ 的右奇异向量

Truncated SVD, 是指截取部分奇异值作为近似, 假设取 $W$ 的前 t 个奇异值, 则

基于上述 Truncated SVD, 作者把权重矩阵为 $W$ 的 fc layer 拆分为两个 fc layer:

  • 一个 fc layer 的权重矩阵为 $ \sum \nolimits {t×t} \, V{v×t}^T $, bias = 0;

  • 另一 fc layer 的权重矩阵为 $U_{u×t}$, bias为原来的bias

由此可见, Truncated SVD 将 fc layer 的参数量 从 $u × v$ 降至 $t(u+v)$. 当 $t$ 远小于 $min(u, v)$时, 参数量大幅减少.

4. 一些问题

4.1. 多任务loss训练是否有效果?

作者的实验证明, 多任务loss联合训练可以显著提高mAP.

4.2. scale invariance: to brute force or finese?

实验证明, 对于单尺度、多尺度训练得到的模型, 它们的检测表现几乎一样.

考虑到速度与精度, 采用单尺度训练模型.

4.3. 需要更多的训练数据吗

实验证明, 数据多多益善.

4.4. SVMs好于softmax吗

  • 实验证明, softmax 的表现略胜于 SVMs.

  • 虽然提升很小, 但是使用 softmax 可以进行一体化训练.

  • 相比于 多个 “1对其它” SVMs, softmax 引入了类别内的竞争.

注: 在 R-CNN, 每个类别都有一个对应的 二分类 SVM (属于该 class, 不属于该 class), 即若有 $K$ 个 class, 则 有 $K + 1$ 个 SVM 分类器. (1是指background类别)

4.5. 更多proposals就一定有助于提高精度吗

太多反而会有害

注: fc layer: fully-connected layer

参考文献

[1]. Ross Girshick, Fast R-CNN.

[2]. Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun, Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition.

[3]. Jonathan Hui, What do we learn from region based object detectors (Faster R-CNN, R-FCN, FPN)?