经典网络解读系列(三):faster rcnn

大部分博客内容来自:https://zhuanlan.zhihu.com/p/31426458   讲的非常详细,强烈推荐

faster rcnn是fast rcnn的改进版本,主要贡献是改进了候选区域的选取方式,由原本的ss(select search)转换为RPN网络,这样所有的计算都在GPU上进行,和Fast R-CNN的卷积网络一起复用,大大缩短了计算时间。同时mAP又上了一个台阶。

fast rcnn可参考博客:http://blog.csdn.net/zlrai5895/article/details/80729048

网络结构:



1、首先是共享的CNN部分,用于提取image的feature maps。

2、Region Proposal Networks。RPN网络用于生成region proposals。Region Proposal Networks首先生成大量的anchors,然后判断它们属于物体还是属于背景,并对位置进行微调(只有部分合适的anchors会参与微调)。

3、Roi Pooling。接收conv给出的feature maps和Region Proposal Networks给出的proposals相关信息,在feature map上截取proposals,并将其变成大小统一的尺寸。

4、Classification。利用proposal feature maps计算proposal的类别,同时再次bounding box regression获得检测框最终的精确位置。


与fast rcnn相比,区别在于Region Proposal Networks。我们先对其进行解释。


Region Proposal Networks

对于conv层提取出来的feature map ,每个点配k个anchor,一般k=9。所谓的anchor就是预备的proposals。由左上角坐标和右下角坐标决定。9个矩形共有3种形状,长宽比为大约为 width:height = [1:1, 1:2, 2:1] 三种,如图6。实际上通过anchors就引入了检测中常用到的多尺度方法。





假设在feature map中每个点上有k个anchor(默认k=9),而每个anhcor要分foreground和background,所以每个点由256d feature转化为cls=2k scores;而每个anchor都有[x, y, w, h]对应4个偏移量,所以reg=4k coordinates。

补充一点,全部anchors拿去训练太多了,训练程序会在合适的anchors中随机选取128个postive anchors+128个negative anchors进行训练。

具体实现:

一副MxN大小的图像送入Faster RCNN网络后,经过共享卷积层的池化层后,到RPN网络变为(M/16)x(N/16),不妨设 W=M/16 , H=N/16 。在进入reshape与softmax之前,先做了3*3卷积,得到W×H×256的feature


一个分支用于判断anchor是前景还是背景:





W×H×256的feature----做1*1卷积核卷积,得到W×H×18feature map

这也就刚好对应了feature maps每一个点都有9个anchors,同时每个anchors又有可能是foreground和background,所有这些信息都保存 W\times H\times (9\cdot2) 大小的矩阵。每个点对应的anchor的特征向量是2*9。


另一个分支用于微调:

具体数学计算可参考上一篇rcnn的博客



W×H×256的feature----做1*1卷积核卷积,得到W×H×36feature map。可以看到其 num\_output=36 ,即经过该卷积输出图像为 W\times H\times 36 这里相当于feature maps每个点都有9个anchors,每个anchors又都有4个用于回归的[d_{x}(A),d_{y}(A),d_{w}(A),d_{h}(A)]变换量。


proposal层:

RPN的最后一层是proposal层,两个分支在这里汇合。

Proposal Layer有3个输入:fg/bg anchors分类器结果rpn_cls_prob_reshape,对应的bbox reg的[d_{x}(A),d_{y}(A),d_{w}(A),d_{h}(A)]变换量rpn_bbox_pred,以及im_info;另外还有参数feat_stride=16,这和图4是对应的。

首先解释im_info。对于一副任意大小PxQ图像,传入Faster RCNN前首先reshape到固定 M\times N,im_info=[M, N, scale_factor]则保存了此次缩放的所有信息。然后经过Conv Layers,经过4次pooling变为 W\times H=(M/16)\times(N/16) 大小,其中feature_stride=16则保存了该信息,用于计算anchor偏移量。


proposal具体操作:

  1. 1、生成anchors,利用[d_{x}(A),d_{y}(A),d_{w}(A),d_{h}(A)]对所有的anchors做bbox regression回归(这里的anchors生成和训练时完全一致)
  2. 2、按照输入的foreground softmax scores由大到小排序anchors,提取前pre_nms_topN(e.g. 6000)个anchors,即提取修正位置后的foreground anchors。
  3. 3、限定超出图像边界的foreground anchors为图像边界(防止后续roi pooling时proposal超出图像边界)
  4. 4、剔除非常小(width<threshold or height<threshold)的foreground anchors
  5. 5、进行nonmaximum suppression
  6. 6、再次按照nms后的foreground softmax scores由大到小排序fg anchors,提取前post_nms_topN(e.g. 300)结果作为proposal输出。

之后输出 proposal=[x1, y1, x2, y2] ,注意,由于在第三步中将anchors映射回原图判断是否超出边界,所以这里输出的proposal是对应 M\times N 输入图像尺度的,这点在后续网络中有用。



ROI层:

先来看一个问题:对于传统的CNN(如AlexNet,VGG),当网络训练好后输入的图像尺寸必须是固定值,同时网络输出也是固定大小的vector or matrix。如果输入图像大小不定,这个问题就变得比较麻烦。有2种解决办法:

  1. 从图像中crop一部分传入网络
  2. 将图像warp成需要的大小后传入网络
图13 crop与warp破坏图像原有结构信息

两种办法的示意图如图13,可以看到无论采取那种办法都不好,要么crop后破坏了图像的完整结构,要么warp破坏了图像原始形状信息。
回忆RPN网络生成的proposals的方法:对foreground anchors进行bounding box regression,那么这样获得的proposals也是大小形状各不相同,即也存在上述问题。所以Faster R-CNN中提出了RoI Pooling解决这个问题。不过RoI Pooling确实是从Spatial Pyramid Pooling发展而来,但是限于篇幅这里略去不讲,有兴趣的读者可以自行查阅相关论文。


ROI层的原理参考上一篇fast rcnn 博客,这里只讲具体操作。

在之前有明确提到: proposal=[x1, y1, x2, y2] 是对应MxN尺度的,所以首先使用spatial_scale参数将其映射回 (M/16)\times(N/16) 大小的feature maps尺度;之后将每个proposal水平和竖直分为pooled_w和pooled_h份,对每一份都进行max pooling处理。这样处理后,即使大小不同的proposal,输出结果都是 7\times7 大小,实现了fixed-length output(固定长度输出)。


后续fast rcnn部分:

从PoI Pooling获取到7x7=49大小的proposal feature maps后,送入后续网络,可以看到做了如下2件事:

  1. 通过全连接和softmax对proposals进行分类,这实际上已经是识别的范畴了
  2. 再次对proposals进行bounding box regression,获取更高精度的rect box

训练

  1. 在已经训练好的model上,训练RPN网络,对应stage1_rpn_train.pt
  2. 利用步骤1中训练好的RPN网络,收集proposals,对应rpn_test.pt
  3. 第一次训练Fast RCNN网络,对应stage1_fast_rcnn_train.pt
  4. 第二训练RPN网络,对应stage2_rpn_train.pt
  5. 再次利用步骤4中训练好的RPN网络,收集proposals,对应rpn_test.pt
  6. 第二次训练Fast RCNN网络,对应stage2_fast_rcnn_train.pt

可以看到训练过程类似于一种“迭代”的过程,不过只循环了2次。至于只循环了2次的原因是应为作者提到:"A similar alternating training can be run for more iterations, but we have observed negligible improvements",即循环更多次没有提升了。



 训练RPN网络:

在该步骤中,首先读取RBG提供的预训练好的model(本文使用VGG),开始迭代训练。来看看stage1_rpn_train.pt网络结构,如图18。

图18 stage1_rpn_train.pt(考虑图片大小,Conv Layers中所有的层都画在一起了,如红圈所示,后续图都如此处理)

与检测网络类似的是,依然使用Conv Layers提取feature maps。整个网络使用的Loss如下:

上述公式中, i 表示anchors index, p_{i} 表示foreground softmax probability,p_{i}^{*}代表对应的GT predict概率(即当第i个anchor与GT间 IoU>0.7 ,认为是该anchor是foreground,p_{i}^{*}=1;反之 IoU<0.3 时,认为是该anchor是background,p_{i}^{*}=0;至于那些 0.3<IoU<0.7 的anchor则不参与训练);t代表predict bounding box,t^{*}代表对应foreground anchor对应的GT box。可以看到,整个Loss分为2部分:

  1. cls loss,即rpn_cls_loss层计算的softmax loss,用于分类anchors为forground与background的网络训练
  2. reg loss,即rpn_loss_bbox层计算的soomth L1 loss,用于bounding box regression网络训练。注意在该loss中乘了 p_{i}^{*} ,相当于只关心foreground anchors的回归(其实在回归中也完全没必要去关心background)。

由于在实际过程中,N_{cls}N_{reg}差距过大,用参数λ平衡二者(如N_{cls}=256N_{reg}=2400时设置 λ=10 ),使总的网络Loss计算过程中能够均匀考虑2种Loss。这里比较重要是Lreg使用的soomth L1 loss,计算公式如下:

通过训练好的RPN网络收集proposals

在该步骤中,利用之前的RPN网络,获取proposal rois,同时获取foreground softmax probability,如图19,然后将获取的信息保存在python pickle文件中。该网络本质上和检测中的RPN网络一样,没有什么区别。

图19 rpn_test.pt

 训练Faster RCNN网络

读取之前保存的pickle文件,获取proposals与foreground probability。从data层输入网络。然后:

  1. 将提取的proposals作为rois传入网络,如图19蓝框
  2. 计算bbox_inside_weights+bbox_outside_weights,作用与RPN一样,传入soomth_L1_loss layer,如图20绿框

这样就可以训练最后的识别softmax与最终的bounding box regression了,如图19。

图20 stage1_fast_rcnn_train.pt

之后的stage2训练都是大同小异,不再赘述了。Faster R-CNN还有一种end-to-end的训练方式,可以一次完成train,有兴趣请自己看作者GitHub吧。


猜你喜欢

转载自blog.csdn.net/zlrai5895/article/details/80734365
今日推荐