Fast R-CNN
Fast R-CNN 是 Ross Girshick 于 2014 年提出的算法。 针对 R-CNN 速度慢的问题,提出了 Roi Pooling 算法,使卷积运算可以在不同的提议框之间进行共享,大幅提高了推理时算法的速度。 Fast R-CNN 还借助多任务学习(multi-task learning)的模式实现了模型的端到端训练,大幅提升了模型训练的速度。 受益于这两个创新点,Fast R-CNN 在训练速度和测试速度上提高了 10-100 倍。
R-CNN 的速度问题
从检测精度的提升来看,RCNN 是非常成功的。但 RCNN 在速度方面有着明显的劣势。 即便使用 GPU 加速,推理一张图片也需要几十秒的时间。
RCNN 中存在大量重复的计算。 在推理过程中,selective search 可以产生 2000 个左右的提议框。 这些提议框无论大小,都需要统一拉伸到 227x227 再送入卷积网络。 这些 proposal 之间必然有大量重叠,但由于图像拉伸操作的存在,卷积运算不能在不同提议框之间共享。 即便在一张图像上进行推理,我们也需要上千次完整的 AlexNet 卷积网络的前传计算。
RCNN 的训练也非常复杂。在 RCNN 算法中,训练一个检测模型需要四个步骤:
在 ImageNet 数据集上预训练一个图像分类网络
使用裁剪下来的图像区域,对 ImageNet 预训练的网络进行微调训练
用训练好的网络提取所有图像区域的特征
用提取好的特征训练 SVM 分类器,和边界框回归模型
上述步骤前后依赖,耗时较长,而且需要大量的存储空间存储中间结果。
卷积共享
Fast RCNN 改进的出发点就是减少重叠区域的卷积计算。在 RCNN 算法中,为了提取不同区域的图像特征, 我们需要将 selective search 产生的提议框全部剪裁下来,再拉伸到同样的大小。由于拉伸尺度不同,重叠的区域在拉伸后就变成不同的图像了。 即便有所重叠,重叠部分也需要分别进行卷积计算。
为了减少重叠区域重复的卷积计算,Fast RCNN 采用了另一种方法,直接用卷积核扫过整个图像,产生整张图像上特征图,再从特征图上裁剪下不同的提议框,作为这些提议框的特征。考虑大小为的图像及图像上位置和大小分别为 的提议框。一个空间采样率为 的卷积网络可以将图像变为 大小的特征图。我们可以按比例提议框映射到特征图上的框 ,再将这个框内的特征图裁剪下来作为提议框的特征。
需要注意的是,先拉伸再计算特征,先计算特征再裁剪,两种方法得到的结果是不同的。但两种方法得到的都是语义级别的特征,可以作为后续分类和边界框回归模型的输入。此外,这种映射关系只是人为定义一种几何关系,与神经网络的感受野在并没有本质上的联系,但针对大多数主流的主干网络(如 ResNet、VGG 等),提议框的感受野的中心是 。
在 RCNN 中,如果有 N 个提议框,我们需要进行 N 次完整的前传计算,以得到每个提议框的特征。 在 Fast RCNN 中,无论有多少提议框,我们都只需要对原图进行一次前传计算,即可得到全部提议框的特征。
RoI Pooling
接下来我们需要考虑另一个问题。不同的提议框大小不同,因而裁剪下来的特征图尺度大小也互不相同。但后续的全连接层要求输入特征具有固定的维度。因此我们就需要将不同大小的提议框特征图处理到一个固定的大小。为了达到这个目的,Faster RCNN 提出了 RoI Pooling 层,通过池化操作将提议框特征图映射到固定的大小。
RoI Pooling 在操作上与普通的池化有所区别。普通的池化层设置固定大小的池子,例如 2x2 大小,再将每个池子内的神经元响应通过平均或者最大化聚合成一个值,输出特征图的大小随输入变化。RoI Pooling 则是设置一个固定的输出尺寸,再根据这个尺寸和确定池子的大小,使得池化的输出恰好为期待的大小。
在下面的示例图中,整幅图像的特征图大小为 8x8,黑框表示提议框在特征图上的映射,目标大小为 2x2。RoI Pooling 将黑框划分成 2x2 个区域,再在每个区域内取最大值,使得池化后的大小为 2x2 。
严格来讲,考虑在特征图上左上右下坐标分别为 的框,如果我们希望将特征图池化到 的大小,那么池化结果的第 行,第 列(, )的单元来自特征图上
范围内的所有响应值。
RoI Pooling 层输出的大小通常设置为所搭配的主干网络在 224x224 图像上输出的特征图的大小,例如对于 VGG 或 ResNet,RoI Pooling 输出大小设置为 7x7,对于 AlexNet 或 ZFNet,输出大小设置为 6x6。这种设置可以更好地利用与训练模型。如果我们把一个 VGG 分类网络最后的池化层直接换成 ROI Pooling,那么这个网络就可以在任意大小的图像及任意大小的框上,产生固定 7x7 大小的特征图,而 7x7 的特征图又恰好可以适配预训练模型中的全连接层输出分类结果。
RoI Pooling 与普通池化层一样,是可以传递梯度的,这就使得端到端训练整个检测模型成为可能。
端到端与多任务学习
Fast RCNN 将 RCNN 中的神经网络、SVM 分类器和边界框回归模型集合到了一起,形成了一个单一的神经网络模型。该模型可以根据单张图像和其上的一系列提议框,直接计算出每个提议框中物体的类别及边界框的修正值。由于输入的图像和输出的检测结果之间只有一个神经网络模型,因而我们说 Fast RCNN 是一个端到端(end-to-end)的模型。又由于一个模型可以同时学习分类和边界框回归两个任务,因而我们说它是一个多任务学习(multi-task learning)的模型。
Fast RCNN 模型的整体结构如下图所示:
在推理阶段,Fast RCNN 以单张图片和 selective search (或其他外部算法)产生的一系列提议框为输入,经由如下步骤预测图中出现的物体:
将图片输入主干网络,产生特征图(即上图中的 conv feature map)。这个过程只需要进行一次。
将全部提议框,按照主干网络的缩放比例映射到特征图上。
对于每一个映射框,通过 RoI Pooling 产生固定尺度(例如 7x7)的提议框特征图。
将每个提议框特征图输入两个共享的全连接层,得到一个特征向量,即上图中的 roi feature vector。
将每个特征向量输入分类和回归模型,得到物体的类别,以及边界框的修正值。
删除分类为背景的提议框,利用其它后处理算法如 NMS 除去重叠的检测框,得到最终检测结果。
由于 Fast RCNN 中所有计算都是可微分的,因而我们可以抛弃 RCNN 中分步骤的训练方法,直接对其进行端到端的训练。训练的整体流程与图像分类网络类似,输入图像、前传计算分类和边界框偏移量,与真值比较计算损失函数并回传,更新网络参数,重复迭代至收敛。但由于检测模型在一张图上有若干个提议框,所以前传的过程比图像分类复杂一些。Fast RCNN 的训练的大体流程如下:
输入一个 batch 的图像以及对应的提议框,使用主干网络前传计算得到一批特征图。
将每张图像上的提议框与真值框进行匹配,将所有的提议框分为正样本、负样本、丢弃样本三类。大体而言,正样本即为与某些真值框重合度较大的提议框,负样本为与所有真值框重合都比较小的提议框,一些不适合用于训练的提议框则丢弃。在 Fast RCNN 的原始论文中,与某个真值框 IoU 大于 0.5 的提议框会被归为正样本,与所有真值框的 IoU 的最大值介于 0.1-0.5 的归为负样本,其余丢弃。需要注意的是,匹配算法并不是单一的,可以根据需要设计或调整。注意,这里的正样本和负样本都是提议框。
对于正样本提议框,用与之 IoU 最大的真值框的类别、以及对应的边界框偏移量,作为这个样本预测的真值。对于负样本,类别标记为背景,不需要边界框偏移量。不难发现,提议框的真值是训练过程中动态生成的。
按照一定的比例(如 1:3)随机选取一部分正样本和负样本,通过 RoI Pooling 得到这些提议框的特征图,并组成 batch,继续前传计算,得到对应的物体类别和边界框偏移量的预测值,与真值比较,计算损失函数,并回传。
对于正样本提议框,我们希望神经网络可以预测出其中物体的类别,以及边界框偏移量。对于负样本,我们只希望神经网络可以将其预测为背景,边界框偏移量对于背景是没有意义的。因而,损失函数可以表达为如下形式:
其中, 为分类损失函数,通常使用交叉熵。 为边界框回归的损失函数,通常使用 smooth L1 损失函数,且仅对于正样本计算这部分损失函数。
通过这种方式,我们实现了端到端的训练,也节省了中间结果需要的存储空间。
模型在 mmdetection 中的实现
数据
首先,Fast RCNN 对数据的加载流程进行了改写。我们可以看到,在定义 data
字段时,我们需要把外部算法已经生成好的提议框从预先生成的 pickle 文件中读取进来。在数据流水线中,需要增加一个 LoadProposals
操作,将图像对应的至多 2000 个提议框增加到数据的字典中。
模型
这个模型使用 ResNet 作为主干网络,并使用 FPN 输出了多尺度的特征图。我们会在后面的小节中讲解 FPN,这里可以先忽略之。不使用 FPN 的情况下,我们可以使用 ResNet 的第三个 block 的输出作为特征图,即指定 out_indices=(2, )
主干网络输出的特征图会输入 StandardRoIHead
模块,该模块会使用 SingleRoIExtractor
子模块,根据数据中提供的提议框和主干网络输出的特征图,通过 RoI Align 算法产生 proposal 框的特征图,这里 RoI Align 算法是 RoI Pooling 算法的升级版。我们可以就把它当作 RoI Pooling 来理解。这里 roi_feat_size=7
表明 RoI Pooling 的目标大小为 7x7 。
接下来的 Shared2FCBBoxHead
以 RoI Pooling 输出的 7x7 大小的特征图为输入,经过两个全连接层,产生一个特征向量,再分别通过各自的全连接层产生类别和边界框的预测。在训练过程中,分别使用CrossEntropyLoss
和 L1Loss
作为分类和边界框回归的损失函数,二者的权重通过loss_weight
指定。
RoI 采样
与所有真值框 IoU 都小于
neg_iou_thr=0.5
的提议框为负样本与某个真值框 IoU 不低于
pos_iou_thr=0.5
的提议框为正样本
匹配完成后,使用 RandomSampler
从这些正负样本中采样,总共采样 num=512
个提议框,其中 pos_fraction=0.25
比例为正样本。同时,add_gt_as_proposals=True
把真值框也作为提议框加入导正样本中,提高正样本的基数。
Last updated
Was this helpful?