介绍
还是微软研究院里Sun, Jian老师团队里的成员像Ren, Shaoqing/He, Kaiming等跟当时同为微软研究院里的Ross,Girshick一块合作进一步将R-CNN系列的模型升级,最终形成了近乎为当代具有最好检测准确率的模型Faster_R-CNN。本质上它是相对于Fast_R-CNN的进一步升级。通过RPN(Region Proposal Network)的提出解决了Fast_R-CNN对像Selective Search等传统意义上的特征区域提案(Region Proposal)方法的依赖,从而进一步使得模型检测速度与准度都有了较大的提高。
可以简单认为Faster_R-CNN = RPN + Fast_R-CNN。而因为RPN相对于像Selective Search等传统区域提案算法可以与Fast_R-CNN主检测网络共享基础网络特征,因此能够大大地提高区域提案计算效率,所以直接将Fast_R-CNN升级到了Faster_R-CNN。它也是目前为止R-CNN系列图片位置检测网络中最先进、最为流行的一种网络。
Faster_R-CNN的基础架构
如下图示即为Faster_R-CNN的基础网络架构。有了上一篇Fast_R-CNN的基础,我们能很容易看出本质上Faster_R-CNN=Fast_R-CNN+RPN。
Faster_R-CNN基本网络结构
RPN
RPN的提出可谓Faster_R-CNN的最大亮点,因此我们也重点对其进行分析。
从以上Faster_R-CNN基本网络架构图中我们能够看出,此时网络的输入只有图片,而不再有像之前由Selective Search等方法所提供的输入图片的可选区域提案集合。同时,我们看到在前端用于特征提取的CNN主干网络之后有了两个并行的分支。其中一条像Fast_R—CNN一样作为ROI pool的直接输入;另外一条则喂给了本论文中新提出的RPN网络,用于区域提案的自动学习,并将学习出的区域提案再作为ROI pool的另外一个输入从而能够接着进行后续的分类问题与位置回归问题的计算。
下面大致介绍下RPN网络所引入的几个基本概念。
Anchor box
在R-CNN系列目标检测网络中,我们容易知道图片预先所提供的提案对其最终位置检测的准确率有极大的影响。很多CNN目标检测方法都努力提供具有不同scale / size大小的区域提案以最大范围地检测到任意scale / size的目标及其位置。为了达到这一目的,通常有两种方法。一种是使用不同大小的图片作为CNN检测网络的输入(通过Resize获得不同大小的图片,同样一张图片需要resize成不同的size后喂入多次,后续size的输入图片则是对前面已经训练出的模型参数进行finetune);另一种则是在使用CNN进行特征提取时选用不同大小的filter size(比如经典的Network In network中所提出的概念或者典型的Inception系列分类网络)。而在本文中作者提出了使用Anchor box来对输入feature map之中的任一点学习出不同大小/分辨率检测框的方法。以下图中可以看出三种方法的对比与区别。
三种用于不同scale大小目标检测的方法原理
从上图中可以看出第一种方法需要每个图片分别变形(resize)为三种不同的大小来进行模型训练;而第二种方法则要求对于CNN层所生出的feature map之上的任一点用不同大小的filter去进一步处理(相对单纯的CNN结构如VGG系列等而言略显复杂);而第三种使用anchor box的方法则通过对CNN输出的feature map之上的任一点进行单一filter size(kxk)的处理,最终分别生成不同scale / aspect ratio的区域提案及其包含潜在检测目标的概率大小,而它还只需要对单一scale的图片与feature map进行处理,因此优势较大。
在下图中我们能看出Anchor box的具体实现机制及其应用效果。
Anchor_box的具体实现及应用
作者在论文中对CNN特征提取网络最后生成的feature map上的每一点使用了9个相应的anchor box(其分别具有不同的大小与分辨率)。上图中的intermediate layer本质上分别由一层3x3 Conv层与1x1 Conv层所组成。即我们对主干网络最后吐出的feature maps先经过一个256x3x3的CNN层处理生成具有256维的新的中间过渡式feature maps。然后再在其上分别使用1x1的网络进行特征融合,最终再分别通过Reg层及cls层(注意这两个层为RPN网络的loss层,仅在对RPN进行训练时需要)就得到了9个anchor box分别对应的predict box的中心位置/大小及其是否包含有目标的概率大小(objectness)等。
RPN loss函数的计算
与Fast_R-CNN中介绍过的loss函数类似,RPN网络的loss函数也包含分类loss与位置回归loss两个部分。如下所示。
RPN_loss_函数计算定义
其中i表示一个mini-batch中的anchor box的index,Pi为anchor i中包含某目标的概率大小,Pi则为anchor i是否确实包含目标的标识,如果包含某一groud truth box则其为1,否则为0。Ti是anchor i中表示其位置的四个参量(分别为Xi,Yi,Hi,Wi),Ti则为所对应的groud truth box的位置参量组合(也为四个,分别是Xi,Yi,Hi,Wi)。对于每个位置参量,参用经典的回归方式对其进行计算,如下所示。
bounding_box位置参量回归计算
RPN训练
对RPN的训练跟之前Fast_R-CNN的训练类似,同样是将前端CNN特征提取网络使用Imagenet 数据预训练过的权重进行初始化,然后再使用检测数据集(如VOC等)进行finetune。
需要注意的是,每次RPN网络的输出中会有数千个区域提案,其中大多数则为不含任何目标的负样本。有时候因为负样本的数目远远大于正样本的数目,我们需要对负样本进行采样,以使得最终用于分类loss函数计算的正负样本的数目大致相同。这一点亦是所有目标检测网络都会用到的技巧,本质上需于经典机器学习中用于保持数据样本分布平衡的一个典型策略。
Faster_R-CNN网络的训练
对于加入了RPN后而形成的Faster_R-CNN网络结构的训练,作者提供了三种可行的方案。其中第一种方案是他们实验下来效果最好的,论文中所有实验数据全是来自于此种方案。
交叉式训练:即首先训练出RPN网络来;然后使用它生成的图片区域提案再训练Fast_R-CNN目标检测网络;接下来再使用此步骤生成的权重初始化整个Faster_R-CNN网络来finetune RPN的部分;最终再使用上步骤生成的权重初始化整个Faster_R-CNN,然后固定RPN网络部分的权重不变化,finetune Fast_R-CNN部分ROI之后的层,最终就得到了训练好了的Faster_R-CNN模型。
近似联合训练:此种方法用于Faster_R-CNN模型训练时,并不向上个方法那样分阶段进行,而是在SGD的一个fwd/bwd 迭代步骤中同时训练RPN与Fast_R-CNN两个网络部分;相当于它有四个loss(RPN与Fast_R-CNN各两个),然后基于四个loss分别向后做backward。然后在前端CNN网络的最后一层backward时,它会对分别来自于RPN与Fast_R-CNN的参数梯度进行加总以作为它输出的梯度向后进行backward计算。在这整个过程中,我们忽略了由Fast_R-CNN对RPN所输出的区域提案的backward,所以称此方法为近似联合训练。作者在文章中指出此方法能够得到与上述交叉式训练方法近似的精度,同时还能减少约25%-50%的模型训练时间。我们组在基于CPU的caffe框架上曾重现过它这一方法,但最终的test accuracy要少上6个百分点左右。
联合训练:与上述近似联合训练方法不同,它考虑了Fast_R-CNN对RPN所输出区域提案的backward计算,这样更能反映偏微分编程模型本质。但因为自ROI pool之后对区域提案的backward的实现比较复杂,因此作者并未对此过多讨论。
Faster_R-CNN的精度与速度结果
如下图示,容易看出它相对于之前SS + Fast_R-CNN的state of art方法,能够在精度与速度上都有较大提高。显然其最大的贡献在于RPN的提出与使用。
Faster_R-CNN实验部分结果
部分代码
------------Data layer-----------------
我们可以看出Faster_R-CNN的data layer中已经不再有ROI提供了,这里的im_info则会提供一些输入图片信息像图片大小、分辨率啥的
layer { name: 'input-data' type: 'Python' top: 'data' top: 'im_info' top: 'gt_boxes' python_param { module: 'roi_data_layer.layer' layer: 'RoIDataLayer' param_str: "'num_classes': 21" } }
--------------RPN layers--------------------
如下可以看到对于CNN特征提取层的最后一层feature map输出'conv5_3',先对其通过一个512 x 3 x 3的conv 处理,生成中间的512维的feature maps
layer { name: "rpn_conv/3x3" type: "Convolution" bottom: "conv5_3" top: "rpn/output" param { lr_mult: 1.0 } param { lr_mult: 2.0 } convolution_param { num_output: 512 kernel_size: 3 pad: 1 stride: 1 weight_filler { type: "gaussian" std: 0.01 } bias_filler { type: "constant" value: 0 } } }layer { name: "rpn_relu/3x3" type: "ReLU" bottom: "rpn/output" top: "rpn/output"}
此层用来得到每个feature map点上的9个anchor box是否包含有检测目标的概率分布
layer { name: "rpn_cls_score" type: "Convolution" bottom: "rpn/output" top: "rpn_cls_score" param { lr_mult: 1.0 } param { lr_mult: 2.0 } convolution_param { num_output: 18 # 2(bg/fg) * 9(anchors) kernel_size: 1 pad: 0 stride: 1 weight_filler { type: "gaussian" std: 0.01 } bias_filler { type: "constant" value: 0 } } }
此层则是用来得到每个feature map点上的9个predict box的位置/大小
layer { name: "rpn_bbox_pred" type: "Convolution" bottom: "rpn/output" top: "rpn_bbox_pred" param { lr_mult: 1.0 } param { lr_mult: 2.0 } convolution_param { num_output: 36 # 4 * 9(anchors) kernel_size: 1 pad: 0 stride: 1 weight_filler { type: "gaussian" std: 0.01 } bias_filler { type: "constant" value: 0 } } }layer { bottom: "rpn_cls_score" top: "rpn_cls_score_reshape" name: "rpn_cls_score_reshape" type: "Reshape" reshape_param { shape { dim: 0 dim: 2 dim: -1 dim: 0 } } }
中间处理,得到rpn每个区域提案之上的每个predict box与ground box之间的重合关系,用于进一步整理出潜在的positive & negative predict box来用于后面localization loss的计算
layer { name: 'rpn-data' type: 'Python' bottom: 'rpn_cls_score' bottom: 'gt_boxes' bottom: 'im_info' bottom: 'data' top: 'rpn_labels' top: 'rpn_bbox_targets' top: 'rpn_bbox_inside_weights' top: 'rpn_bbox_outside_weights' python_param { module: 'rpn.anchor_target_layer' layer: 'AnchorTargetLayer' param_str: "'feat_stride': 16" } }
计算classification loss
layer { name: "rpn_loss_cls" type: "SoftmaxWithLoss" bottom: "rpn_cls_score_reshape" bottom: "rpn_labels" propagate_down: 1 propagate_down: 0 top: "rpn_cls_loss" loss_weight: 1 loss_param { ignore_label: -1 normalize: true } }
计算localization loss
layer { name: "rpn_loss_bbox" type: "SmoothL1Loss" bottom: "rpn_bbox_pred" bottom: "rpn_bbox_targets" bottom: 'rpn_bbox_inside_weights' bottom: 'rpn_bbox_outside_weights' top: "rpn_loss_bbox" loss_weight: 1 smooth_l1_loss_param { sigma: 3.0 } }
-------------------------------RoI Proposal---------------------------------------
以下几层layers则具体使用RPN输出的值结合data layer输出的raw image生成最终的ROI提案,此提案接下来将由Fast_R-CNN部分使用
layer { name: "rpn_cls_prob" type: "Softmax" bottom: "rpn_cls_score_reshape" top: "rpn_cls_prob"}layer { name: 'rpn_cls_prob_reshape' type: 'Reshape' bottom: 'rpn_cls_prob' top: 'rpn_cls_prob_reshape' reshape_param { shape { dim: 0 dim: 18 dim: -1 dim: 0 } } }layer { name: 'proposal' type: 'Python' bottom: 'rpn_cls_prob_reshape' bottom: 'rpn_bbox_pred' bottom: 'im_info' top: 'rpn_rois' python_param { module: 'rpn.proposal_layer' layer: 'ProposalLayer' param_str: "'feat_stride': 16" } }layer { name: 'roi-data' type: 'Python' bottom: 'rpn_rois' bottom: 'gt_boxes' top: 'rois' top: 'labels' top: 'bbox_targets' top: 'bbox_inside_weights' top: 'bbox_outside_weights' python_param { module: 'rpn.proposal_target_layer' layer: 'ProposalTargetLayer' param_str: "'num_classes': 21" } }
作者:manofmountain
链接:https://www.jianshu.com/p/ede35536d62c