论文链接:https://arxiv.org/abs/1504.08083
学习Fast R-CNN之前我们先了解一下SPP-Net网络
SPP-net
SPP-net(Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition, He et al. 2014)提出的起因是解决图像分类中要求输入图片固定大小的问题,但是SPP-net中所提出的空间金字塔池化层(Spatial Pyramid Pooling Layer, SPP)可以和R-CNN结合在一起并提升其性能。采用深度学习模型解决图像分类问题时,往往需要图像的大小固定(比如224×224224×224),这并不是CNN层的硬性要求,主要原因在于CNN层提取的特征图最后要送入全连接层(如softmax层),对于变大小图片,CNN层得到的特征图大小也是变化的,但是全连接层需要固定大小的输入,所以必须要将图片通过resize, crop或wrap等方式固定大小(训练和测试时都需要)。但是实际上真实的图片的大小是各种各样的,一旦固定大小可能会造成图像损失,从而影响识别精度。为了解决这个问题,SSP-net在CNN层与全连接层之间插入了空间金字塔池化层来解决这个矛盾。
现在的问题是每个Region Proposal的尺度不一样,直接这样输入全连接层肯定是不行的,因为全连接层输入必须是固定的长度。SPP-NET恰好可以解决这个问题。
由于传统的CNN限制了输入必须固定大小(比如AlexNet是224x224),所以在实际使用中往往需要对原图片进行crop或者warp的操作:
- crop:截取原图片的一个固定大小的patch
- warp:将原图片的ROI缩放到一个固定大小的patch
无论是crop还是warp,都无法保证在不失真的情况下将图片传入到CNN当中:
- crop:物体可能会产生截断,尤其是长宽比大的图片。
- warp:物体被拉伸,失去“原形”,尤其是长宽比大的图片
SPP为的就是解决上述的问题,做到的效果为:不管输入的图片是什么尺度,都能够正确的传入网络。
具体思路为:CNN的卷积层是可以处理任意尺度的输入的,只是在全连接层处有限制尺度——换句话说,如果找到一个方法,在全连接层之前将其输入限制到等长,那么就解决了这个问题。
具体方案如下图所示:
如果原图输入是224x224,对于conv5出来后的输出,是13x13x256的,可以理解成有256个这样的filter,每个filter对应一张13x13的activation map。如果像上图那样将activation map pooling成4x4 2x2 1x1三张子图,做max pooling后,出来的特征就是固定长度的(16+4+1)x256那么多的维度了。如果原图的输入不是224x224,出来的特征依然是(16+4+1)x256;直觉地说,可以理解成将原来固定大小为(3x3)窗口的pool5改成了自适应窗口大小,窗口的大小和activation map成比例,保证了经过pooling后出来的feature的长度是一致的。
使用SPP-NET相比于R-CNN可以大大加快目标检测的速度,但是依然存在着很多问题:
(1) 训练分为多个阶段,步骤繁琐: 微调网络+训练SVM+训练训练边框回归器
(2) SPP-NET在微调网络的时候固定了卷积层,只对全连接层进行微调,而对于一个新的任务,有必要对卷积层也进行微调。(分类的模型提取的特征更注重高层语义,而目标检测任务除了语义信息还需要目标的位置信息)
针对这两个问题,RBG又提出Fast R-CNN, 一个精简而快速的目标检测框架。
Fast R-CNN
论文地址:https://arxiv.org/pdf/1504.08083.pdf
解决的问题:
之所以提出Fast R-CNN,主要是因为R-CNN存在以下几个问题:
1、训练分多步。通过上一篇博文我们知道R-CNN的训练先要fine tuning一个预训练的网络,然后针对每个类别都训练一个SVM分类器,最后还要用regressors对bounding-box进行回归,另外region proposal也要单独用selective search的方式获得,步骤比较繁琐。
2、时间和内存消耗比较大。在训练SVM和回归的时候需要用网络训练的特征作为输入,特征保存在磁盘上再读入的时间消耗还是比较大的。
3、测试的时候也比较慢,每张图片的每个region proposal都要做卷积,重复操作太多。
基于VGG16的Fast RCNN算法在训练速度上比RCNN快了将近9倍,比SPPnet快大概3倍;测试速度比RCNN快了213倍,比SPPnet快了10倍。在VOC2012上的mAP在66%左右。
算法概要:
算法的主网络还是VGG16,按训练过程和测试过程来讲会清晰点。
训练的过程:
输入是224*224,经过5个卷积层和2个降采样层(这两个降采样层分别跟在第一和第二个卷积层后面)后,进入ROIPooling层,该层是输入是conv5层的输出和region proposal,region proposal的个数差不多2000。然后再经过两个都是output是4096的全连接层。最后分别经过output个数是21和84的两个全连接层(这两个全连接层是并列的,不是前后关系),前者是分类的输出,代表每个region proposal属于每个类别(21类)的得分,后者是回归的输出,代表每个region proposal的四个坐标。最后是两个损失层,分类的是softmaxWithLoss,输入是label和分类层输出的得分;回归的是SmoothL1Loss,输入是回归层的输出和target坐标及weight。
测试的过程:
与训练基本相同,最后两个loss层要改成一个softma层,输入是分类的score,输出概率。最后对每个类别采用NMS(non-maximun suppression)。
详解:
ROI pooling:ROI Pooling的作用是对不同大小的region proposal,从最后卷积层输出的feature map提取大小固定的feature map。简单讲可以看做是SPPNet的简化版本,因为全连接层的输入需要尺寸大小一样,所以不能直接将不同大小的region proposal映射到feature map作为输出,需要做尺寸变换。在文章中,VGG16网络使用H=W=7的参数,即将一个h*w的region proposal分割成H*W大小的网格,然后将这个region proposal映射到最后一个卷积层输出的feature map,最后计算每个网格里的最大值作为该网格的输出,所以不管ROI pooling之前的feature map大小是多少,ROI pooling后得到的feature map大小都是H*W。
因此可以看出Fast RCNN主要有3个改进:
1、卷积不再是对每个region proposal进行,而是直接对整张图像,这样减少了很多重复计算。原来RCNN是对每个region proposal分别做卷积,因为一张图像中有2000左右的region proposal,肯定相互之间的重叠率很高,因此产生重复计算。
2、用ROI pooling进行特征的尺寸变换,因为全连接层的输入要求尺寸大小一样,因此不能直接把region proposal作为输入。
3、将regressor放进网络一起训练,每个类别对应一个regressor,同时用softmax代替原来的SVM分类器。
画一画重点:
R-CNN有一些相当大的缺点(把这些缺点都改掉了,就成了Fast R-CNN)。
大缺点:由于每一个候选框都要独自经过CNN,这使得花费的时间非常多。
解决:共享卷积层,现在不是每一个候选框都当做输入进入CNN了,而是输入一张完整的图片,在第五个卷积层再得到每个候选框的特征
原来的方法:许多候选框(比如两千个)-->CNN-->得到每个候选框的特征-->分类+回归
现在的方法:一张完整图片-->CNN-->得到每张候选框的特征-->分类+回归
所以容易看见,Fast RCNN相对于RCNN的提速原因就在于:不过不像RCNN把每个候选区域给深度网络提特征,而是整张图提一次特征,再把候选框映射到conv5上,而SPP只需要计算一次特征,剩下的只需要在conv5层上操作就可以了。
在性能上提升也是相当明显的:
总结:
Fast RCNN将RCNN众多步骤整合在一起,不仅大大提高了检测速度,也提高了检测准确率。其中,对整张图像卷积而不是对每个region proposal卷积,ROI Pooling,分类和回归都放在网络一起训练的multi-task loss是算法的三个核心。另外还有SVD分解等是加速的小贡献,数据集的增加时mAP提高的小贡献。
当然Fast RCNN的主要缺点在于region proposal的提取使用selective search,目标检测时间大多消耗在这上面(提region proposal 2~3s,而提特征分类只需0.32s),这也是后续Faster RCNN的改进方向之一。
参考资料
1 https://blog.csdn.net/u014380165/article/details/72851319
2 https://www.cnblogs.com/skyfsm/p/6806246.html