Ross Girshick
Microsoft Research
[email protected]
paper:Fast R-CNN
论文翻译:点击这里
Fast R-CNN在SPPNet的基础再跟进,进一步提升速度和准确率,提出了RoI层代替SPP层,实现了整个物体检测模型大部分网络的end-to-end,下面就来好好学习一下。
老套路,现回顾一下: R-CNN ,SPP-net
R-CNN和SPP-net在训练时pipeline是隔离的:提取proposal,CNN提取特征,SVM分类,bbox regression。
检测目标速度慢.
在测试阶段,特征来自于每张测试图片的每个候选区域.
同样是要从每个测试图像上提取大量proposal,再从每个proposal中提取特征来进行检测过程,可想而知是很慢的
每个候选区域都需要经过CNN的前向传播计算出特征向量。速度很慢.
训练分为多个阶段(multi-stage pipeline)
训练花费大量的空间和时间(in space and time)
候选区域经过CNN得到的特征向量要存在到disk内,然后在训练SVM和bbox回归再取出来,这需要大量的磁盘空间,并且很耗费时间。
R-CNN速度慢是因为每个候选区域都需要塞入CNN里面做一次前向传播,而SPPNet实现了计算共享。
在SPPNet中,把全图塞进CNN得到一个完整的feature map,在将每个候选区域映射到feature map上,获得每个候选区域的特征向量。然后用SPP(Spatial pyramid pooling)对在没个候选区域的特征向量再提取得到了固定长度的特征向量,再实现SVM分类,bbox回归等.
SPPNet也有很明显的缺点:
针对上述的问题,Fast R-CNN的想法是将整个模型分成两步:
Fast R-CNN将整张整张图片归一化之后直接送入深度网络,邻接时才加入候选框信息,只有末尾的少数几层才处理每个候选框;相比之下,R-CNN框架中,一张图像内候选框之间大量重叠,需要重复地提取特征,耗时间。
Fast R-CNN把类别判断和位置精修统一到一个深度网络中,不需要额外存储;相比之下,RCNN中独立的分类器和回归器需要大量特征作为训练样本,耗空间。
新的模型效果很好,因为多个训练阶段合并了,训练后面阶段的同时可以更新前面阶段的参数,模型收敛的更好了。同时因为多个阶段合并,候选区域的特征不需要在写入磁盘,一直在显存中,训练的速度大大的提升。
Fast R-CNN模型先把一张图片的候选区域整出来,整个模型的输入是全图片和一组候选区域.和SPPNet一样,首先全图片塞进一个CNN得到一个全图的feature map.
然后,把图片的候选区域映射到feature map得到对应的patch(这和SPPNet的处理类似).然后把这个patch塞给ROI层(Region of interest)得到固定大小的的特征向量(feature vector).
每个特征向量会送到FC层,最后分为两个分支层:一个层是处理softmax概率,输出类别有K个类别和”背景”类;另一个层作bbox回归,输出回归的选框数据.联合一起训练整个网络。
相比于SPPNet,Fast R-CNN简化了SPP层(RoI层是一个简化的SPP层),按论文的说法,Fast R-CNN是joint training。
这里我们主要关注两个问题:
RoI层的作用和SPPNet中的SPP层作用类似:承上启下。
说白了就是如何把不同尺寸的侯选区域提取特征变换成为固定大小的特征向量。
做图片分类时,一般都是先将图片crop和resize到固定尺寸,然后输入网络,提取特征,最后进行分类。
对于检测来说,这个方法不太适合,因为原始图像如果缩小到224这种分辨率,那么感兴趣对象可能都会变的太小无法辨认。
而Fast R-CNN的数据输入并不对图片大小进行限制,实现这一点的关键所在,就是ROI Pooling层,它可以在任意大小的图片feature map上针对输入的每一个ROI区域提取出固定维度的特征表示,保证后续对每个区域的后续分类能够正常进行。
作用
RoI层是特殊的SPP层,RoI层是使用单个尺度的SPP层(为什么不用多个尺度的原因是多个尺度准确率提升不高,但是计算量成倍的翻)
ROI Pooling的具体实现可以看做是针对ROI区域的普通整个图像feature map的Pooling,只不过因为不是固定尺寸的输入,因此每次的pooling网格大小得手动计算,比如某个ROI区域坐标为,那么输入size为 ,如果pooling的输出size为 ,那么每个网格的size为 。
引用shenxiaolu1984.
RoI层将候选区域分为H×WH×W块。对每个小块做max-pooling.将候选区的局部特征映射转变为大小统一的数据,送入下一层。
RoI Pooling层将每个候选区域均匀分成M×N块,对每块进行max pooling,这样一来将feature map上大小不一的候选区域转变为了大小统一的特征向量,然后送入下一层。RoI Pooling层的训练(backward)
考虑到普通的的max pooling层,设xixi为输入层的节点,yiyi为输出层的节点.
其中判决函数δ(i,j)δ(i,j)表示ii节点是否被jj节点选为最大值输出。不被选中有两种可能:xixi不在yjyj范围内,或者xixi不是最大值
对于RoI的max pooling,一个输入节点可能和多个输出节点相连。设xixi为输入层的节点,yrjyrj为第rr个候选区域的第jj个输出节点。
判决函数δ(i,r,j)δ(i,r,j)表示ii节点是否被候选区域rr的第jj个节点选为最大值输出。代价对于xi
xi的梯度等于所有相关的后一层梯度之和.
另外,实际实现时采用的是Max Pooling,具体每个网格中哪个点的值最大,在Forward过程中就已经记录,存储在了argmax_data变量里。
前面我们讲了RoI层的反向传播,这就让整个模型能从FC层传播到卷积层了,剩下的就是把SVM分类器和bbox回归整到一起就大功告成了。
Fast R-CNN在FC层后有两个分支,一个是SVM分类器,一个是bbox回归。
这里直接给结论,论文把这两个分支的损失弄到一起:
Lcls(p,u)Lcls(p,u)是一个分支softmax层输出概率分布:p=(p0,...,pk)p=(p0,...,pk),这是一个K个分类,加上1个背景的softmax层。
λ[u≥1]Lloc(tu,v)λ[u≥1]Lloc(tu,v)另一个分支bbox回归的位移: tk=(tkx,tky,tkw,tkh)tk=(txk,tyk,twk,thk),k表示类别,这里对于bbox回归的loss,是一个K个输出的regressor.每个类别都会训练出一个回归器,且这里的回归器用的损失函数为:
使用L1L1正则损失的原因是对outliers(离群点)的敏感度低,模型更具有鲁棒性。
R**oI层加上多任务损失函数,把除了proposal以外的整个模型整到一起了,大家可以一起训练了,没有特征存/取硬盘的操作,整个训练和测试过程又全线提速了!**
作者这样设置的目的是想让loss对于离群点更加鲁棒,控制梯度的量级使得训练时不容易跑飞。
最后在5.1的讨论中,作者说明了Multitask loss是有助于网络的performance的。
Mini-batch sampling
在微调时,每个SGD的mini-batch是随机找两个图片,R为128,因此每个图上取样64个RoI。从object proposal中选25%的RoI,就是和ground-truth交叠至少为0.5的。剩下的作为背景。
在调优训练时,每一个mini-batch中首先加入N张完整图片,而后加入从N张图片中选取的R个候选框。这R个候选框可以复用N张图片前5个阶段的网络特征。
实际选择N=2, R=128-> 每一个mini-batch中首先加入2张完整图片,而后加入从2张图片中选取的128个候选框。这128个候选框可以复用2张图片前5个阶段的网络特征。
这里针对fine-tuning阶段指出了SPPNet存在的问题。
SPPNet在使用BP算法训练效率低的原因:
SPPNet只能微调SPP层后面的全连接层,再采用SGD方法训练的过程中,而SPPNet的会在多张图片上选取候选区域,这里在反向传播的过程中会大量耗费内存和时间。
在Fast R-CNN的做法:
Fast R-CNN采用SGD训练,每次采样在N个图片的基础上选取R个候选区域,实验选取的N=2,R=128.这样样本数据来自与2张图片,这比R-CNN和SPPNet选取的样本在训练速度上快了很多倍。
这里存在一个问题,训练样本大多数取自同一张图片,样本之前关联性很大,这可能会造成训练不收敛,但是在论文的实验过程中,没有出现这种情况,所以就采用这个方法了。
在网络微调,每个SGD mini-batch是由N=2,R=128,首先加入N张完整图片,而后加入从N张图片中选取的R个候选框。从object proposal中选25%的RoI,就是和ground-truth的IoU至少为0.5的。剩下的75%取IoU至少为在0.1到0.5的样本作为背景。
N张完整图片以50%概率水平翻转。 R个候选框的构成方式如下:
类别 | 比例 | 方式 |
---|---|---|
正例 | 25% | 与Ground-Truth的IoU大于0.5 |
反例 | 75% | 与Ground-Truth的IoU在0.1到0.5之间 |
在检测过程中,因为要处理的RoIs较多,几乎过半的时间都耗费在FC层的计算上了,这里是用SVD分解加速FC层的计算。
我们对一组尺寸u×vu×v的权重矩阵WW可分解为:使用t个特征值.
将原来的前向传播分为两步,降低了计算复杂度:
计算复杂度从u×vu×v变为u×t+v×tu×t+v×t。
在实现时,相当于把一个全连接层拆分成两个,中间以一个低维数据相连。
在分类中,计算全连接层比卷积层快,而在检测中由于一个图中要提取2000个RoI,所以大部分时间都用在计算全连接层了。文中采用奇异值分解的方法来减少计算fc层的时间.
具体来说,作者对全连接层的矩阵做了一个SVD分解,mAP几乎不怎么降(0.3%),但速度提速30%
Scale invariance
SPPnet用了两种实现尺度不变的方法:
1. brute force (single scale),直接将image设置为某种scale,直接输入网络训练,期望网络自己适应这个scale。
2. image pyramids (multi scale),生成一个图像金字塔,在multi-scale训练时,对于要用的RoI,在金字塔上找到一个最接近227x227的尺寸,然后用这个尺寸训练网络。
虽然看起来2比较好,但是非常耗时,而且性能提高也不对,大约只有%1,所以这篇论文在实现中还是用了1。
对应文中4.5,作者的观察有2点
全连接层提速
分类和位置调整都是通过全连接层(fc)实现的,设前一级数据为后一级为,全连接层参数为,尺寸。一次前向传播(forward)即为:
将进行SVD分解,并用前t个特征值近似:
原来的前向传播分解成两步:
Data augment
在训练期间,作者做过的唯一一个数据增量的方式是水平翻转。
作者也试过将VOC12的数据也作为拓展数据加入到finetune的数据中,结果VOC07的mAP从66.9到了70.0,说明对于网络来说,数据越多就是越好的。
实验与结论
实验过程不再详述,只记录结论
- 网络末端同步训练的分类和位置调整,提升准确度
- 使用多尺度的图像金字塔,性能几乎没有提高
- 倍增训练数据,能够有2%-3%的准确度提升
- 网络直接输出各类概率(softmax),比SVM分类器性能略好
- 更多候选窗不能提升性能
Results for VOC2007
method | mAP S M L | train time(h) S M L | test rate (s/im) S M L |
---|---|---|---|
SPPnet BB | — — 63.1 | — — 25 | — — 2.3 |
R-CNN BB | 58.5 60.2 66.0 | 22 28 84 | 9.8 12.1 47.0 |
FRCN | 57.1 59.2 66.9 | 1.2 2.0 9.5 | 0.10 0.15 0.32 |
Fast R-CNN 两大主要贡献点 :
参考文献:
1.https://blog.csdn.net/u011974639/article/details/78053203#r-cnn
2.https://blog.csdn.net/u011534057/article/details/51241831
3.https://blog.csdn.net/xiaqunfeng123/article/details/78716060
4.https://zhuanlan.zhihu.com/p/24780395