Faster R-CNN
论文:Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks
发表时间:2016
发表作者:(Microsoft)Shaoqing Ren, Kaiming He, Ross Girshick, and Jian Sun
发表刊物/会议:NIPS
论文链接:论文链接
论文代码:Matlab版本点击此处,Python版本点击此处
2015 年微软研究院的任少庆、何恺明以及 Ross B Girshick 等人又提出了 Faster R-CNN 算法。从R-CNN到Fast R-CNN,再到本文的Faster R-CNN,目标检测的四个基本步骤(候选区域生成,特征提取,分类,位置精修)终于被统一到一个深度网络框架之内。所有计算没有重复,完全在GPU中完成,大大提高了运行速度。
Faster R-CNN可以简单地看做“区域生成网络(RPN)+Fast RCNN“的系统,用区域生成网络代替Fast R-CNN中的Selective Search方法,网络结构如下图。本篇论文着重解决了这个系统中的三个问题:
- 如何设计区域生成网络
- 如何训练区域生成网络
- 如何让区域生成网络和Fast R-CNN网络共享特征提取网络
步骤如下:
- 首先向CNN网络【ZF或VGG-16】输入任意大小图片M×NM×N;
- 经过CNN网络前向传播至最后共享的卷积层,一方面得到供RPN网络输入的特征图,另一方面继续前向传播至特有卷积层,产生更高维特征图;
- 供RPN网络输入的特征图经过RPN网络得到区域建议和区域得分,并对区域得分采用非极大值抑制【阈值为0.7】,输出其Top-N【文中为300】得分的区域建议给RoI池化层;
- 第2步得到的高维特征图和第3步输出的区域建议同时输入RoI池化层,提取对应区域建议的特征;
- 第4步得到的区域建议特征通过全连接层后,输出该区域的分类得分以及回归后的bounding-box。
RPN
设计辅助生成样本的 RPN(Region Proposal Networks)网络,将算法结构分为两个部分,先由 RPN 网络判断候选框是否为目标,再经分类定位的多任务损失判断目标类型,整个网络流程都能共享卷积神经网络提取的的特征信息,节约计算成本,且解决 Fast R-CNN 算法生成正负样本候选框速度慢的问题,同时避免候选框提取过多导致算法准确率下降。
RPN网络基本设想是:在提取好的特征图上,对所有可能的候选框进行判别。由于后续还有位置精修步骤,所以候选框实际比较稀疏。
1、特征提取
RPN还是需要使用一个CNN网络对原始图片提取特征。为了方便读者理解,不妨设这个前置的CNN提取的特征为$51×39×256$,即高为51,宽为39,通道数为256.对这个卷积特征再进行一次卷积计算,保持宽、高、通道数不变,再次得到一个$51×39×256$的特征。
为了方便叙述,先来定义一个“位置”的概念:对于一个$51×39×256$的卷积特征,称它一共有$51×39$个"位置"。让新的卷积特征的每一个"位置"都"负责”原图中对应位置的9种尺寸框的检测,检测的目标是判断框中是否存在一个物体,因此共用$51×39×9$个“框”。在Faster R-CNN原论文中,将这些框都统一称为 "anchor"。
2、候选区域(anchor)
特征可以看做一个尺度$51×39$的256通道图像,对于该图像的每一个位置,考虑9个可能的候选窗口:三种面积分别是$128×128$,$256×256$,$512×512$,每种面积又分成3种长宽比,分别是$2:1$,$1:2$,$1:1$ 。这些候选窗口称为anchors。做着就是通过这些anchors引入了检测中常用到的多尺度方法(检测各种大小的目标),下图示出$51×39$个anchor中心,以及9种anchor示例。
对于这$51×39$个位置和$51×39×9$个anchor,下图展示了接下来每个位置的计算步骤:
- 设$k$为单个位置对应的anchor的个数,此时$k=9$,通过增加一个$3×3$滑动窗口操作以及两个卷积层完成区域建议功能;
- 第一个卷积层将特征图每个滑窗位置编码成一个特征向量,第二个卷积层对应每个滑窗位置输出$k$个区域得分,表示该位置的anchor为物体的概率,这部分总输出长度为$2×k$(一个anchor对应两个输出:是物体的概率+不是物体的概率)和k个回归后的区域建议(框回归),一个anchor对应4个框回归参数,因此框回归部分的总输出的长度为$4×k$,并对得分区域进行非极大值抑制后输出得分Top-N(文中为300)区域,告诉检测网络应该注意哪些区域,本质上实现了Selective Search、EdgeBoxes等方法的功能。
3、框回归
如图绿色表示的是飞机的实际框标签(ground truth),红色的表示的其中一个候选区域(foreground anchor),即被分类器识别为飞机的区域,但是由于红色区域定位不准确,这张图相当于没有正确检测出飞机,所以我们希望采用一种方法对红色的框进行微调,使得候选区域和实际框更加接近:
对于目标框一般使用四维向量来表示$(x,y,w,h)$,分别表示目标框的中心点坐标、宽、高,我们使用$A$表示原始的foreground anchor,使用$G$表示目标的ground truth,我们的目标是寻找一种关系,使得输入原始的Anchor $A$经过映射到一个和真实框$G$更接近的回归窗口$G′$,即:
-给定$A=(A_x,A_y,A_w,A_h)$,\(G=(G_x,G_y,G_w,G_h)\);
寻找一种变换$F$,使得$F(A_x,A_y,A_w,A_h)=(G_x',G_y',G_w',G_h')\(,其中\)(G_x,G_y,G_w,G_h)≈(G_x',G_y',G_w',G_h')$;
那么如何去计算$F$呢?这里我们可以通过平移和缩放实现$F(A)=G′$:
- 平移:
G_x'=A_x + A_w\cdot d_x(A) \\
G_y'=A_y + A_h\cdot d_y(A)
\]
- 缩放:
G_w'=A_w\cdot exp(d_w(A)) \\
G_h'=A_h\cdot exp(d_h(A))
\]
上面公式中,我们需要学习四个参数,分别是$d_x(A),d_y(A),d_w(A),d_h(A)\(,其中\)(A_w\cdot d_x(A),A_w\cdot d_y(A))$ 表示两个框中心距离的偏移量。当输入的anchor A与G相差较小时,可以认为这种变换是一种线性变换, 那么就可以用线性回归来建模对目标框进行微调(注意,只有当anchors A和G比较接近时,才能使用线性回归模型,否则就是复杂的非线性问题了)。
接下来就是如何通过线性回归获得$d_x(A),d_y(A),d_w(A),d_h(A)$。线性回归就是给定输入的特征向量$X$,学习一组参数$W$,使得线性回归的输出$WX$和真实值$Y$的差很小。对于该问题,输入$X$是特征图,我们使用$ϕ$表示,同时训练时还需要$A$到$G$变换的真实参数值:\((t_x,t_y,t_w,t_h)\);输出是$d_x(A),d_y(A),d_w(A),d_h(A)$,那么目标函数可以表示为:
d_*(A)=w_*^T\cdot \phi(A)
\]
其中$ϕ(A)$是对应anchor的特征图组成的特征向量,$w$是需要学习的参数,$d(A)$是得到预测值,(*表示$x,y,w,h$,也就是每一个变换对应一个上述目标函数),为了让预测值$d_x(A),d_y(A),d_w(A),d_h(A)$和真实值差距$t_x,t_y,t_w,t_h$最小,代价函数如下:
loss=\sum\limits_{i=1}^{N}(t_*^i - \hat{w}_*^T\cdot \phi(A^i))^2
\]
函数优化目标为:
w_*=\mathop{\arg\min}_{\hat{w}_*} \sum\limits_{i=1}^{N}(t_*^i - \hat{w}_*^T\cdot \phi(A^i))^2+\lambda \|{\hat{w*}}\|2
\]
需要说明,只有在G和A比较接近时,才可近似认为上述线性变换成立,下面对于原文中,A与G之间的平移参数$(t_x,t_y)\(和尺度因子\)(t_w,t_h)$为:
t_x=(G_x-A_x)/A_w \\
t_y=(G_y-A_y)/A_h \\
t_w=log(G_w/A_w) \\
t_h=log(G_h/A_h)
\]
对于训练bouding box regression网络回归分支,输入是特征图$ϕ$,监督信号是A到G的变换参数
\((t_x,t_y,t_w,t_h)\),即训练的目标是:输入$ϕ$的情况下使网络输出与监督信号尽可能接近。那么bouding box regression工作时,再输入$ϕ$时,回归网络分支的输出就是每个anchor的平移参数和变换尺度$(t_x,t_y,t_w,t_h)$,显然即可用来修正anchor位置了。
4、候选框修正
得到每一个候选区域anchor A的修正参数$(d_x(A),d_y(A),d_w(A),d_h(A))$之后,我们就可以计算出精确的anchor,然后按照物体的区域得分从大到小对得到的anchor排序,然后提出一些宽或者高很小的anchor(获取其它过滤条件),再经过非极大值抑制抑制,取前Top-N的anchors,然后作为proposals(候选框)输出,送入到RoI Pooling层。
此外,全部anchors拿去训练太多了,训练程序会在合适的anchors中随机选取128个postive anchors+128个negative anchors进行训练。
具体规则如下:
- 对每个标定的ground true box区域,与其重叠比例最大的anchor记为 正样本 (保证每个ground true 至少对应一个正样本anchor);
- 对1)剩余的anchor,如果其与某个标定区域重叠比例大于0.7,记为正样本(每个ground true box可能会对应多个正样本anchor。但每个正样本anchor 只可能对应一个grand true box);如果其与任意一个标定的重叠比例都小于0.3,记为负样本。
- 对上面两步剩余的anchor,弃去不用;
- 跨越图像边界的anchor弃去不用。
训练RPN时,与VGG共有的层参数可以直接拷贝经ImageNet训练得到的模型中的参数,剩下没有的层参数用标准差=0.01的高斯分布初始化。
一句话总结:其实RPN最终就是在原图尺度上,设置了密密麻麻的候选Anchor。然后用cnn去判断哪些Anchor是里面有目标的foreground anchor,哪些是没目标的backgroud。所以,仅仅是个二分类而已!
缺点:由于RPN网络可在固定尺寸的卷积特征图中生成多尺寸的候选框,导致出现可变目标尺寸和固定感受野不一致的现象。最大的问题就是对小物体检测效果很差。
RoI Pooling层
RoI Pooling层负责收集所有的候选框,并计算每一个候选框的特征图,然后送入后续网络,从Faster RCNN的结构图我们可以看到RoI Pooling层有两个输入:
- 原始的特征图;
- RPN网络输出的候选框;
RoI Pooling层把每一个候选框的特征图水平和垂直分为pooled_w(文章中为7)和pooled_h(7)份,对每一份进行最大池化处理,这样处理后,即使大小不一样的候选区,输出大小都一样,实现了固定长度的输出。
然后我们把Top-N个固定输出($7×7=49$)连接起来,组成特征向量,大小为$Top−N×49$,这里可以把Top-N看做样本数,49看做每一个样本的特征维数,送入全连接层。
存在的问题:
由于预选ROI的位置通常是有模型回归得到的,一般来说是浮点数,而赤化后的特征图要求尺度固定,因此ROI Pooling这个操作存在两次数据量化的过程。1)将候选框边界量化为整数点坐标值;2)将量化后的边界区域平均分割成kxk个单元,对每个单元的边界进行量化。事实上,经过上面的两次量化操作,此时的ROI已经和最开始的ROI之间存在一定的偏差,这个偏差会影响检测的精确度。
下面我们用直观的例子具体分析一下区域不匹配问题。输入一张800x800的图片,图片中有一个665x665的BB中框这一只狗。图片经过特征提取网络之后,整个图片的特征图变为800/32 * 800/32,即25x25,但是665/32=20.87,带有小数,ROI Pooling直接将它量化为20。在这里引入了一次偏差。由于最终的特征映射的大小为7x7,即需要将20x20的区域映射成7x7,矩形区域的边长为2.86,又一次将其量化为2。这里再次引入了一次量化误差。经过这两次的量化,候选ROI已经出现了严重的偏差。更重要的是,在特征图上差0.1个像素,对应到原图上就是3.2个像素。
分类和框回归
通过RoI Pooling层我们已经得到所有候选区组成的特征向量,然后送入全连接层和softmax计算每个候选框具体属于哪个类别,输出类别的得分;同时再次利用框回归获得每个候选区相对实际位置的偏移量预测值,用于对候选框进行修正,得到更精确的目标检测框。
Faster R-CNN使用RPN生成候选框后,剩下的网络结构和Fast R-CNN中的结构一模一样。在训练过程中,需要训练两个网络,一个是RPN网络,一个是在得到框之后使用的分类网络。通常的做法是交替训练,即在一个batch内,先训练RPN网络一次,再训练分类网络一次。
损失函数计算
对于每个锚点,首先在后面接上一个二分类softmax,有2个score 输出用来表示这是一个前景还是一个背景的概率 (\(p_i\)),然后再接上一个bounding box的regressor 输出代表这个锚点的4个坐标位置(\(t_i\)),因此RPN的总体$Loss$函数可以定义为 :
其中Lcls表示分类loss,这里使用两类别(前景还是背景)的log loss;Lreg表示回归loss,这里使用的是Smooth-L1;
i表示第i个锚点,当锚点是正背景样本时 \(p_i^* =1\) ,是负样本则为0 。 \(t_i^*\) 表示 一个与正样本锚点相关的ground true box坐标 (每个正样本锚点 只可能对应一个ground true box: 一个正样本锚点 与某个grand true BB对应,那么该锚点与ground true box 的IOU要么是所有anchor中最大,要么大于0.7)
训练策略
- 用ImageNet模型初始化,独立训练一个RPN网络;
- 仍然用ImageNet模型初始化,但是使用上一步RPN网络产生的proposal作为输入,训练一个Fast-RCNN网络,至此,两个网络每一层的参数完全不共享;
- 使用第二步的Fast-RCNN网络参数初始化一个新的RPN网络,但是把RPN、Fast-RCNN共享的那些卷积层的learning rate设置为0,也就是不更新,仅仅更新RPN特有的那些网络层,重新训练,此时,两个网络已经共享了所有公共的卷积层;
- 仍然固定共享的那些网络层,把Fast-RCNN特有的网络层也加入进来,形成一个unified network,继续训练,fine tune Fast-RCNN特有的网络层,此时,该网络已经实现我们设想的目标,即网络内部预测proposal并实现检测的功能。
即进行交替训练,迭代2次的原因是作者发现多次的迭代并没有显著的改善性能。
Faster R-CNN总体流程总结如下:
- 首先对输入的图片进行裁剪操作,并将裁剪后的图片送入预训练好的分类网络中获取该图像对应的特征图;
- 然后在特征图上的每一个锚点上取9个候选的ROI(3个不同尺度,3个不同长宽比),并根据相应的比例将其映射到原始图像中(因为特征提取网络一般有conv和pool组成,但是只有pool会改变特征图的大小,因此最终的特征图大小和pool的个数相关);
- 接着将这些候选的ROI输入到RPN网络中,RPN网络对这些ROI进行分类(即确定这些ROI是前景还是背景)同时对其进行初步回归(即计算这些前景ROI与真实目标之间的BB的偏差值,包括Δx、Δy、Δw、Δh),然后做NMS(非极大值抑制,即根据分类的得分对这些ROI进行排序,然后选择其中的前N个ROI);
- 接着对这些不同大小的ROI进行ROI Pooling操作(即将其映射为特定大小的feature_map,文中是7x7),输出固定大小的feature_map;
- 最后将其输入简单的检测网络中,然后利用1x1的卷积进行分类(区分不同的类别,N+1类,多余的一类是背景,用于删除不准确的ROI),同时进行BB回归(精确的调整预测的ROI和GT的ROI之间的偏差值),从而输出一个BB集合。
作为一个目标检测领域的baseline算法,Faster-rcnn值得去仔细理解里面的细节。
参考:
Faster R-CNN