【笔记】Fast_R-CNN_ICCV_2015_paper

来源:互联网 发布:阿里云服务器重启 编辑:程序博客网 时间:2024/06/07 01:55

论文地址:http://arxiv.org/abs/1504.08083

代码:https://github.com/rbgirshick/fast-rcnn

概要


Fast RCNN是RCNN和SPPnet的改进版。Fast RCNN在训练的时候比RCNN快9倍,比SPPnet快3倍;测试的时候比RCNN快213倍,比SPPnet快10倍。最后在PASCAL VOC 2012上达到66%的mAP.

缺点

为何有了R-CNN和SPP-Net之后还要提出Fast RCNN(简称FRCN)?因为前者有三个缺点

  • 训练是多阶段的:训练的时候,pipeline是隔离的,先提proposal,然后CNN提取特征,之后用SVM分类器,最后再做bbox regression。FRCN实现了end-to-end的joint training(提proposal阶段除外)。
  • 训练非常耗费时间和空间(存储):RCNN中ROI-centric的运算开销大,要从每一张图像上提取大量proposal,还要从每个proposal中提取特征,并存到磁盘中。所以FRCN用了image-centric的训练方式来通过卷积的share特性来降低运算开销;RCNN提取特征给SVM训练时候需要中间要大量的磁盘空间存放特征,FRCN去掉了SVM这一步,所有的特征都暂存在显存中,就不需要额外的磁盘空间了。
  • 物体检测非常慢:测试时间开销大,依然是因为ROI-centric的原因,这点SPP-Net已经改进,然后FRCN进一步通过single scale testing和SVD分解全连接来提速。

整体框架

如果以AlexNet(5个卷积和3个全连接)为例,大致的训练过程可以理解为:

  1. selective search在一张图片中得到约2k个object proposal(这里称为RoI)
  2. 缩放图片的scale得到图片金字塔,FP得到conv5的特征金字塔。
  3. 对于每个scale的每个ROI,求取映射关系,在conv5中crop出对应的patch。并用一个单层的SPP layer(这里称为Rol pooling layer)来统一到一样的尺度(对于AlexNet是6x6)。
  4. 继续经过两个全连接得到特征,这特征有分别share到两个新的全连接,连接上两个优化目标。第一个优化目标是分类,使用softmax,第二个优化目标是bbox regression,使用了一个smooth的L1-loss.

Fast RCNN的优点

1.      比RCNN,SPPnet有更高的准确率(mAP)。

2.      训练是单阶段的,使用多任务的loss。

3.      训练可以更新所有的网络层(SPPnet只能更新fc层)。

4.      特征缓存的时候不需要硬盘存储。




第一步,将这个完整的图片经过若干卷积层与max pooling层,得到一个feature map。

第二步,用selective search算法从这完整的图片中提取出object proposals,即RoI。

第三步,根据映射关系,可以得到每个object proposal对应的feature map。

第四步,将第三步得到的feature map经过RoI pooling layer得到固定大小的feature map(变小了)。

第五步,经过2层全连接层(fc),得到固定大小的RoI特征向量。

第六步,特征向量经由各自的FC层,得到两个输出向量:第一个是分类,使用softmax,第二个是每一类的bounding box回归。

 

简要流程图如下:


说明:在训练的时候,分类与回归是一起训练的,总的loss是分类的loss加上回归的loss。计算公式如下:

FRCN大致就是一个joint training版本的SPP-Net

  1. SPP-Net在实现上无法同时tuning在SPP layer两边的卷积层和全连接层。
  2. SPP-Net后面的需要将第二层FC的特征放到硬盘上训练SVM,之后再额外训练bounding box regressor。

Rol pooling layer

这是SPP pooling层的一个简化版,只有一级“金字塔”,输入N个特征映射和一组R个RoI(R>>N)N个特征映射来自于最后一个卷积层,每个特征映射都是H x W x C的大小。每个RoI是一个元组(n, r, c, h, w)n是特征映射的索引,n∈{0, ... ,N-1}(r, c)是RoI左上角的坐标,(h, w)是高与宽。输出是max-pool过的特征映射,H' x W' x C的大小,H'≤HW'≤W。对于roI,bin-size ~ h/H' x w/W',这样就有H'W'个输出bin,bin的大小是自适应的,取决于RoI的大小。

Rol pooling layer的作用主要有两个,一个是将image中的rol定位到feature map中对应patch,另一个是用一个单层的SPP layer将这个feature map patch下采样为大小固定的feature再传入全连接层。

  1. 对于某个rol,怎么求取对应的feature map patch?代码中寻找。
  2. 为何只是一层的SPP layer?多层的SPP layer不会更好吗?因为需要读取pretrain model来finetuning,比如VGG就release了一个19层的model,如果是使用多层的SPP layer就不能够直接使用这个model的parameters,而需要重新训练了。

pre-trained networks

用了3个预训练的ImageNet网络(CaffeNet/VGG_CNN_M_1024/VGG16)。预训练的网络初始化Fast RCNN要经过三次变形: 
1. 最后一个max pooling层替换为RoI pooling层,设置H’和W’与第一个全连接层兼容。 
2. 最后一个全连接层和softmax(原本是1000个类)替换为softmax的对K+1个类别的分类层,和bounding box 回归层。 
3. 输入修改为两种数据:一组N个图形,R个RoI,batch size和ROI数、图像分辨率都是可变的。

fine-tuning

前面说过SPPnet有一个缺点是只能微调spp层后面的全连接层,所以SPPnet就可以采用随机梯度下降(SGD)来训练。 
RoI-centric sampling:从所有图片的所有RoI中均匀取样,这样每个SGD的mini-batch中包含了不同图像中的样本。(SPPnet采用) 
FRCN想要解决微调的限制,就要反向传播到spp层之前的层,反向传播需要计算每一个RoI感受野的卷积层,通常会覆盖整个图像,如果一个一个用RoI-centric sampling的话就又慢又耗内存。 
image-centric sampling: mini-batch采用层次取样,先对图像取样,再对RoI取样,同一图像的RoI共享计算和内存。 
另外,FRCN在一次微调中联合优化softmax分类器和bbox回归,看似一步,实际包含了多任务损失(multi-task loss)、小批量取样(mini-batch sampling)、RoI pooling层的反向传播(backpropagation through RoI pooling layers)、SGD超参数(SGD hyperparameters)。

Multi-task loss

Fast R-CNN有两个loss:
1.分类loss,是一个N+1路的softmax输出,其中的N是类别个数,1是背景。为何不用SVM做分类器了?在5.4作者讨论了softmax效果比SVM好,因为它引入了类间竞争。
2.回归loss,是一个4xN路输出的regressor,也就是说对于每个类别都会训练一个单独的regressor的意思,比较有意思的是,这里regressor的loss不是L2的,而是一个平滑的L1,形式如下:


作者这样设置的目的是想让loss对于离群点更加鲁棒,控制梯度的量级使得训练时不容易跑飞。最后在5.1的讨论中,作者说明了Multitask loss是有助于网络的performance的。

两个输出层:
一个对每个RoI输出离散概率分布:这里写图片描述 
一个输出bounding box回归的位移:这里写图片描述 

k表示类别的索引,前两个参数是指相对于object proposal尺度不变的平移,后两个参数是指对数空间中相对于object proposal的高与宽。把这两个输出的损失写到一起:

这里写图片描述

k*是真实类别,式中第一项是分类损失,第二项是定位损失,L由R个输出取均值而来,不再具体展开。

mini-batch sampling

在微调时,每个SGD的mini-batch是随机找两个图片,R为128,因此每个图上取样64个RoI。从object proposal中选25%的RoI,就是和ground-truth交叠至少为0.5的。剩下的作为背景。

backpropagation through RoI pooling layers

RoI pooling层计算损失函数对每个输入变量x的偏导数,如下:

这里写图片描述

y是pooling后的输出单元,x是pooling前的输入单元,如果y由x pooling而来,则将损失L对y的偏导计入累加值,最后累加完R个RoI中的所有输出单元。下面是我理解的x、y、r的关系: 
这里写图片描述

SGD hyperparameters

是一些参数的设置。

Scale invariance

SPPnet用了两种实现尺度不变的方法: 
1. brute force (single scale),直接将image设置为某种scale,直接输入网络训练,期望网络自己适应这个scale。 
2. image pyramids (multi scale),生成一个图像金字塔,在multi-scale训练时,对于要用的RoI,在金字塔上找到一个最接近227x227的尺寸,然后用这个尺寸训练网络。 
虽然看起来2比较好,但是非常耗时,而且性能提高也不对,大约只有%1,所以这篇论文在实现中还是用了1。

这里讨论object的scale问题,就是网络对于object的scale应该是要不敏感的。这里还是引用了SPP的方法,有两种。

  1. brute force (single scale),也就是简单认为object不需要预先resize到类似的scale再传入网络,直接将image定死为某种scale,直接输入网络来训练就好了,然后期望网络自己能够学习到scale-invariance的表达。
  2. image pyramids (multi scale),也就是要生成一个金字塔,然后对于object,在金字塔上找到一个大小比较接近227x227的投影版本,然后用这个版本去训练网络。

可以看出,2应该比1更加好,作者也在5.2讨论了,2的表现确实比1好,但是好的不算太多,大概是1个mAP左右,但是时间要慢不少,所以作者实际采用的是第一个策略,也就是single scale。
这里,FRCN测试之所以比SPP快,很大原因是因为这里,因为SPP用了2,而FRCN用了1。

Truncated SVD on fc layers for faster detection

对应文中3.1,这段笔者没细看。大致意思是说全连接层耗时很多,如果能够简化全连接层的计算,那么能够提升速度。具体来说,作者对全连接层的矩阵做了一个SVD分解,mAP几乎不怎么降(0.3%),但速度提速30%,在分类中,计算全连接层比卷积层快,而在检测中由于一个图中要提取2000个RoI,所以大部分时间都用在计算全连接层了。文中采用奇异值分解的方法来减少计算fc层的时间,学过矩阵论的都懂,不展开了。

Which layers to finetune?

对应文中4.5,作者的观察有2点

  1. 对于较深的网络,比如VGG,卷积层和全连接层是否一起tuning有很大的差别(66.9 vs 61.4)
  2. 有没有必要tuning所有的卷积层?答案是没有。如果留着浅层的卷积层不tuning,可以减少训练时间,而且mAP基本没有差别。

Data augment

在训练期间,作者做过的唯一一个数据增量的方式是水平翻转。
作者也试过将VOC12的数据也作为拓展数据加入到finetune的数据中,结果VOC07的mAP从66.9到了70.0,说明对于网络来说,数据越多就是越好的。

Are more proposals always better?

对应文章的5.5,答案是NO。
作者将proposal的方法粗略地分成了sparse(比如selective search)和dense(sliding windows)。

如Figure 3所示,不管是哪种方法,盲目增加proposal个数反而会损害到mAP的。

results

for VOC2007

methodmAP S M Ltrain time(h) S M Ltest rate (s/im) S M LSPPnet BB— — 63.1— — 25— — 2.3R-CNN BB58.5 60.2 66.022 28 849.8 12.1 47.0FRCN57.1 59.2 66.91.2 2.0 9.50.10 0.15 0.32


参考:

http://blog.csdn.net/liumaolincycle/article/details/50203333

http://blog.csdn.net/shenxiaolu1984/article/details/51036677