RCNN--对象检测的又一伟大跨越 2(包括SPPnet、Fast RCNN)(持续更新)

时间:2021-11-09 03:46:53

  继续上次的学习笔记,在RCNN之后是Fast RCNN,但是在Fast RCNN之前,我们先来看一个叫做SPP-net的网络架构。

一,SPP(空间金字塔池化,Spatial Pyramid Pooling)简介:

  有一个事实需要说清楚:CNN的卷积层不需要固定尺寸的图像,全连接层是需要固定大小输入的,因此提出了SPP层放到卷积层的后面。SPPNet将任意大小的图像池化生成固定长度的图像表示,如下图所示:

RCNN--对象检测的又一伟大跨越 2(包括SPPnet、Fast RCNN)(持续更新)

  SPP的优点:1)任意尺寸输入,固定大小输出,2)层多,3)可对任意尺度提取的特征进行池化。

  池化示意图:

RCNN--对象检测的又一伟大跨越 2(包括SPPnet、Fast RCNN)(持续更新)

  SPP层的结构如下,将紧跟最后一个卷积层的池化层使用SPP代替,作为全连接层的输入。当我们有很多层网络的时候,当网络输入的是一张任意大小的图片,这个时候我们可以一直进行卷积、池化,直到网络的倒数几层的时候,也就是我们即将与全连接层连接的时候,就要使用金字塔池化,使得任意大小的特征图都能够转换成固定大小的特征向量,这就是空间金字塔池化的奥义(多尺度特征提取出固定大小的特征向量)(每一种刻度我们称之为:金字塔的一层)

  Note :

BoW -> SPM

(SPP的思想来源于SPM,然后SPM的思想来源自BoW。
关于BoW和SPM,找到了两篇相关的博文,就不在这里展开了。http://blog.csdn.net/v_JULY_v/article/details/6555899
http://blog.csdn.net/jwh_bupt/article/details/9625469)

二,用SPPnet进行对象检测:

  R-CNN重复使用深层卷积网络在~2k个窗口上提取特征,特征提取非常耗时。SPPNet将比较耗时的卷积计算改为对整幅图像只进行一次,之后使用spp将窗口特征图池化为一个固定长度的特征表示。

----------------------------------------------------------------------------------------

这里插一条关于神经网络训练中常用的三个英文单词:epoch、 iteration和batchsize的区别:

(1)batchsize:批大小。在深度学习中,一般采用SGD训练,即每次训练在训练集中取batchsize个样本训练;

(2)iteration:1个iteration等于使用batchsize个样本训练一次;

(3)epoch:1个epoch等于使用训练集中的全部样本训练一次;

举个例子,训练集有1000个样本,batchsize=10,

那么:训练完整个样本集需要:100次iteration,1次epoch。

------------------------------------------------------------------------------------------

这是原文的关于SPP的详解,自己认为非常好,这里先贴出来,明天继续学习:

---------------------------------

SPP网络,我不得不要先说,这个方法的思想在Fast RCNN, Faster RCNN上都起了举足轻重的作用。SPP网络主要是解决深度网络固定输入层尺寸的这个限制,也从各个方面说明了不限制输入尺寸带来的好处。文章在一开始的时候就说明了目前深度网络存在的弊端:如果固定网络输入的话,要么选择crop策略,要么选择warp策略,crop就是从一个大图扣出网络输入大小的patch(比如227×227),而warp则是把一个bounding box的内容resize成227×227 。无论是那种策略,都能很明显看出有影响网络训练的不利因素,比如crop就有可能crop出object的一个部分,而无法准确训练出类别,而warp则会改变object的正常宽高比,使得训练效果变差。接着,分析了出深度网络需要固定输入尺寸的原因是因为有全连接层(FC),不过在那个时候,还没有FCN的思想,那如何去做才能使得网络不受输入尺寸的限制呢?Kaiming He 大神就想出,用不同尺度的pooling 来pooling出固定尺度大小的feature map,这样就可以不受全链接层约束任意更改输入尺度了。下图就是SPP网络的核心思想:
通过对feature map进行相应尺度的pooling,使得能pooling出4×4, 2×2, 1×1的feature map,再将这些feature map concat成列向量与下一层全链接层相连。这样就消除了输入尺度不一致的影响。训练的时候就用常规方法训练,不过由于不受尺度的影响,可以进行多尺度训练,即先resize成几个固定的尺度,然后用SPP网络进行训练,学习。这里讲了这么多,实际上我想讲的是下面的 东西, SPP如何用在检测上面。论文中实际上我觉得最关键的地方是提出了一个如何将原图的某个region映射到conv5的一种机制,虽然,我并不是太认可这种映射机制,等下我也会说出我认为合理的映射方法。论文中是如何映射的,实际上我也是花了好久才明白。
首先,我想先说明函数这个东东,当然我不是通过严谨的定义来说明。什么是y=f(x),我认为只要输入x,有一组固定的操作f,然后产生一个对应的y,这样子就算是函数。根据输入有一个一一对应的输出,这就是函数。这样理解的话,卷积也是函数,pooling也是函数。当然我并不想说明函数是什么,什么是函数,实际上我想强调的是一一对应这样的关系。大家都知道,现在默许的无论是卷积还是pooling(无stride),都会加相应的pad,来使得卷积后的尺寸与卷积前相同,当然这种做法还有个好处就是使得边缘不会只被卷积一次就消失了~这样子的话,实际上原图与卷积后的图就是一一对应的关系。原图的每一个点(包括边缘)都可以卷积得到一个新的点,这就是一一对应了。如下图所示(自己画得太丑):
RCNN--对象检测的又一伟大跨越 2(包括SPPnet、Fast RCNN)(持续更新)RCNN--对象检测的又一伟大跨越 2(包括SPPnet、Fast RCNN)(持续更新)
绿色部分是图片,紫色部分是卷积核。 
RCNN--对象检测的又一伟大跨越 2(包括SPPnet、Fast RCNN)(持续更新) 
如上图可以看出,蓝色的区域是原图区域,而红色的区域是padding区域,紫色的是卷积核。卷积后得到的区域与原区域是一一对应的。而卷积或pooling增加stride的话就相当与原图先进行卷积或池化,再进行sampling,这还是能一一对应的,就这样原图的某个区域就可以通过除以网络的所有stride来映射到conv5后去区域。终于把这里讲出来了,大家如果直接按照函数的一一对应关系去理解,很容易理解为什么原图的区域除以所有的stride就是映射到conv5的区域。这样子就可以在原图上的一些操作放在conv5上进行,这样可以减小任务复杂度。不过,我并不是太认可这种映射机制,这种映射只能是点到点的关系,不过我觉得从原图的某个区域R映射到conv5的区域r,应该r对R敏感,换句话说,应该r感受野应该与R有交集。这样子的话,示意图如下:
RCNN--对象检测的又一伟大跨越 2(包括SPPnet、Fast RCNN)(持续更新) 
其中蓝色的为conv的神经元感受野,红色的是原图的某个感兴趣区域,而黑色框我才认为是要映射到conv5的区域。 
使用SPP进行检测,先用提候选proposals方法(selective search)选出候选框,不过不像RCNN把每个候选区域给深度网络提特征,而是整张图提一次特征,再把候选框映射到conv5上,因为候选框的大小尺度不同,映射到conv5后仍不同,所以需要再通过SPP层提取到相同维度的特征,再进行分类和回归,后面的思路和方法与RCNN一致。实际上这样子做的话就比原先的快很多了,因为之前RCNN也提出了这个原因就是深度网络所需要的感受野是非常大的,这样子的话需要每次将感兴趣区域放大到网络的尺度才能卷积到conv5层。这样计算量就会很大,而SPP只需要计算一次特征,剩下的只需要在conv5层上操作就可以了。当然即使是这么完美的算法,也是有它的瑕疵的,可能Kaiming He大神太投入 SPP的功效了,使得整个流程框架并没有变得更加完美。首先在训练方面,SPP没有发挥出它的优势,依旧用了传统的训练方法,这使得计算量依旧很大,而且分类和bounding box的回归问题也可以联合学习,使得整体框架更加完美。这些Kaiming He都给忽略了,这样也就有了第二篇神作 Fast RCNN。

-----------------------------------------------------------------------------

@@@@@@@@@@@@@@

在微调阶段谈及SPP-net只能更新FC层,这是因为卷积特征是线下计算的,从而无法再微调阶段反向传播误差。
而在fast-RCNN中则是通过image-centric sampling提高了卷积层特征抽取的速度,从而保证了梯度可以通过SPP层(即ROI pooling层)反向传播。

@@@@@@@@@@@@@@

三,Fast RCNN

3.1 首先想说下RCNN的缺点:

1. 训练时要经过多个阶段,首先要提取特征微调ConvNet,再用线性SVM处理proposal,计算得到的ConvNet特征,然后进行用bounding box回归。

2. 训练时间和空间开销大。要从每一张图像上提取大量proposal,还要从每个proposal中提取特征,并存到磁盘中。

3. 测试时间开销大。同样是要从每个测试图像上提取大量proposal,再从每个proposal中提取特征来进行检测过程,可想而知是很慢的。

3.2 然后说下SPPnet的缺点:

1.多阶段的训练
2.特征向量需要被存储在磁盘上
3.SPPnet不能更新SPP之前的卷积层

3.3 Fast RCNN的改进:

1. 比R-CNN更高的检测质量(mAP); 
2. 把多个任务的损失函数写到一起,实现单级的训练过程; 
3. 在训练时可更新所有的层; 
4. 不需要在磁盘中存储特征。

四,Fast RCNN整体框架:

整体框架如下图,如果以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.
(除了1,上面的2-4是joint training的。测试时候,在4之后做一个NMS即可。)

RCNN--对象检测的又一伟大跨越 2(包括SPPnet、Fast RCNN)(持续更新)

这里我把自己看论文认为的处理过程写出来:

1.将原图 & 一系列对象区域 输入整个框架;
2.用一些卷积层 & max pooling层只对原图产生卷积后的feature map
3.从feature map中将对应的ROI区域用 pooling层(这里的SPP金字塔只有一层)提取固定长度的特征向量
4.将固定长度的特征向量经过一系列全连接层
5.每个向量产生两个输出:
   5.1 一个是对类别可能性概率的估计(包括K种类别 和 一个背景)
   5.2 一个是对每一种对象类别产生的4个实数,就是bbox的坐标

??????一个问题??????

为什么是一层SPP金字塔,多层不是更好?

对于这个问题,笔者认为是因为需要读取pretrain model来finetuning的原因,比如VGG就release了一个19层的model,如果是使用多层的SPP layer就不能够直接使用这个model的parameters,而需要重新训练了。

????????????????

五,这里再恶补一个知识点 SGD(Stochastic Gradient Descent-随机梯度下降,SGD)方法:

一种拟合函数关系的一种方法,详细后面再补充。

六,预训练网络的初始化:

1.最后一个max pooling 层被ROI pooling层所取代,设置一个H,W使得和第一个全连接层的匹配
2.最后一个全连接层和softmax层被替换成两个姊妹层。
3.网络需要两个输入:原图 & 一系列的ROI区域

七,训练FRCN网络时,用于检测的调优技巧:

7.1  Multi-task loss:

  RCNN--对象检测的又一伟大跨越 2(包括SPPnet、Fast RCNN)(持续更新)

  第一项是分类损失,第二项是定位损失,L由R个输出取均值而来。

1)对于分类loss,是一个N+1路的softmax输出,其中的N是类别个数,1是背景。为何不用SVM做分类器了?在5.4作者讨论了softmax效果比SVM好,因为它引入了类间竞争。(原文作者觉得这个理由略牵强,他估计还是实验效果验证了softmax的performance好吧 ^_^)
2)对于回归loss,是一个4xN路输出的regressor,也就是说对于每个类别都会训练一个单独的regressor的意思,比较有意思的是,这里regressor的loss不是L2的,而是一个平滑的L1,形式如下:

RCNN--对象检测的又一伟大跨越 2(包括SPPnet、Fast RCNN)(持续更新)

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

7.2  Mini-batch sampling:(小批量采样)

这里没怎么理解。。。

7.3  Back-propagation through RoI pooling layers(RoI pooling层的反向传播):

7.4  SGD超参数(SGD hyperparameters):

八,尺度不变形:

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

九,用FRCN检测(FRCN的测试阶段):

@@@Truncated SVD for faster detection

在分类中,计算全连接层比卷积层快,而在检测中由于一个图中要提取2000个RoI,所以大部分时间都用在计算全连接层了。文中采用奇异值分解的方法来减少计算fc层的时间.

具体来说,作者对全连接层的矩阵做了一个SVD分解,mAP几乎不怎么降(0.3%),但速度提速30%

-----------------------------

RCNN:《Rich feature hierarchies for Accurate Object Detection and Segmentation》

R*CNN:《Contextual Action Recognition with R*CNN》

SPP-Net:《Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition》

Fast-rcnn:《Fast R-CNN》

Faster-rcnn: 《Faster R-CNN: Towards Real-Time Object  Detection with Region Proposal Networks》

YOLO:《You Only Look Once(YOLO):Unified, Real-Time Object Detection》

FCN:《Fully Convolutional Networks for Semantic Segmentation》

-------------------------------