参见 https://blog.csdn.net/u011974639/article/details/78053203
R-CNN的训练可分成下白四步:
(1)在数据集上训练CNN 。R-CNN论文中使用的CNN网络是AlexNet,数据集为ImageNet 。
(2)在目标检测的数据集上,对训练好的CNN做微调。
(3)用Selective Search搜索候选区域,统一使用微调后的CNN对这些区域提取特征,并将提取到的特征存储起来。
(4)使用存储起来的特征,训练SVM分类器。
一、有监督的预训练
一般的CNN模型层数多,模型的容量大,在标定数据少的情况下,这样的数据量是不够从新训练一个CNN模型的。故我们采用已训练好的AlexNet/VGG16模型的卷积层参数,使用这样已训练好的网络参数,可以较好的提取图片的特征。。
即用CNN网络AlexNet,数据集ImageNet进行网络参数训练。此时输出为1000个类别的网络参数。
Alexnet特征提取部分包含了5个卷积层、2个全连接层,在Alexnet中p5层神经元个数为9216、 fc6、fc7的神经元个数都是4096,通过这个网络训练完毕后,最后提取特征每个输入候选框图片都能得到一个4096维的特征向量。
二、fine-tuning
AlexNet是针对ImageNet训练出来的模型,AlexNet的卷积部分可以作为一个好的特征提取器,后面的全连接层可以理解为一个好的分类器。这里把AlexNet的softmax层替换为一个N+1神经元的输出层(N为存在物体的种类,即正样本;1为背景,即负样本)。然后做微调训练。
采用 selective search 搜索出来的候选框 (PASCAL VOC 数据库中的图片) 继续对上面预训练的CNN模型进行fine-tuning训练。假设要检测的物体类别有N类,那么我们就需要把上面预训练阶段的CNN模型的最后一层(分类到1000的层)给替换掉,替换成N+1个输出的神经元(加1,表示还有一个背景) (20 + 1bg = 21),然后这一层直接采用参数随机初始化的方法,其它网络层的参数不变;接着就可以开始继续SGD训练了。开始的时候,SGD学习率选择0.001【0.01/10为了在学习新东西时不至于忘记之前的记忆】。每次训练时,mini-batch size大小选择128,其中32个是正样本、96个是负样本【由于正样本太少】。
原本ImageNet的输出类别有1000个,这里把1000个替换为21个(N=20,1为背景).
在训练CNN的时候会在网络的后面加上一个分类层,在训练完毕后,我们会移除最后的分类层,直接提取到前面的FC层,AlexNet的FC层为4096维。
对于一张图片,使用训练好的CNN基础上,将所有的图片的所有侯选区域塞到CNN里面,把得到的pool5 feature存到硬盘里面(这里一存,后面训练一取,非常耗费时间)
CNN在侯选区域上提取出了特征向量,例如2000个侯选区域,那么提取出来的就是2000*4096这样的特征向量(AlexNet的第一个FC层维度为4096,故pool5的输出为4096)。
备注:
1、一张照片我们得到了2000个候选框。然而人工标注的数据一张图片中就只标注了正确的bounding box,我们搜索出来的2000个矩形框也不可能会出现一个与人工标注完全匹配的候选框。因此在CNN阶段我们需要用IoU为2000个bounding box打标签。如果用selective search挑选出来的候选框与物体的人工标注矩形框(PASCAL VOC的图片都有人工标注)的重叠区域IoU大于0.5,那么我们就把这个候选框标注成物体类别(正样本),否则我们就把它当做背景类别(负样本)。
这是一个二分类问题,假设我们要检测车辆。只有当bounding box把整量车都包含在内,才叫正样本;如果bounding box 没有包含到车辆,那么我们就可以把它当做负样本。但问题是当我们的检测窗口只有部分包含物体,那该怎么定义正负样本呢?作者测试了IoU阈值各种方案数值0,0.1,0.2,0.3,0.4,0.5。最后通过训练发现,如果选择IoU阈值为0.3效果最好(选择为0精度下降了4个百分点,选择0.5精度下降了5个百分点),即当重叠度小于0.3的时候,我们就把它标注为负样本
2、如果不针对特定任务进行fine-tuning,而是把CNN当做特征提取器,卷积层所学到的特征其实就是基础的共享特征提取层,就类似于SIFT算法一样,可以用于提取各种图片的特征,而f6、f7所学习到的特征是用于针对特定任务的特征。打个比方:对于人脸性别识别来说,一个CNN模型前面的卷积层所学习到的特征就类似于学习人脸共性特征,然后全连接层所学习的特征就是针对性别分类的特征了。
3、 CNN训练的时候,本来就是对bounding box的物体进行识别分类训练,在训练的时候最后一层softmax就是分类层。那么为什么作者闲着没事干要先用CNN做特征提取(提取fc7层数据),然后再把提取的特征用于训练svm分类器?
这个是因为svm训练和cnn训练过程的正负样本定义方式各有不同,导致最后采用CNN softmax输出比采用svm精度还低。事情是这样的,cnn在训练的时候,对训练数据做了比较宽松的标注,比如一个bounding box可能只包含物体的一部分,那么我也把它标注为正样本,用于训练cnn;采用这个方法的主要原因在于因为CNN容易过拟合,所以需要大量的训练数据,所以在CNN训练阶段我们是对Bounding box的位置限制条件限制的比较松(IOU只要大于0.5都被标注为正样本了);然而svm训练的时候,因为svm适用于少样本训练,所以对于训练样本数据的IOU要求比较严格,我们只有当bounding box把整个物体都包含进去了,我们才把它标注为物体类别,然后训练svm
三、在候选区域的特征向量上训练分类器(目标分类)
因为最终目标分类是通过SVM进行分类的,而不是通过网络框架中的softmax分类的。
前面的CNN在侯选区域上提取出了特征向量,例如2000个侯选区域,那么提取出来的就是2000*4096这样的特征向量(AlexNet的第一个FC层维度为4096,故pool5的输出为4096)。用这些特征向量训练同时训练N个二分类的SVM,SVM的权重矩阵为4096xN(N为分类种类)。
训练SVM时使用的样本
样本 描述
正样本 候选区域与ground-truth(图片物体标注区域)的IoU>0.7
负样本 候选区域与ground-truth(图片物体标注区域)的IoU<0.3
这个0.7的阈值是做实验得出来的经验值
使用了SVM来进行分类,对于每一类都会训练一个SVM分类器,所以共有N(21)个分类器
如何训练和使用SVM分类器?
如下图所示,在训练过程中,SVM的输入包括两部分:
(1) CNN feature:这个便是CNN网络为每个region proposal提取的feature,共2000*4096。
(2) Ground truth labels: 在训练时,会为每个region proposal附上一个label,在SVM分类过程中,当IoU<0.3时,为负样本,然后正样本便是ground truth box(个人理解应该是和ground truth box重合度最高的region proposal)。但是,对于label的形式没有详细说明,但是根据我个人理解,正负样本的label应该是以下的形式:
然后SVM分类器也会输出一个预测的labels,然后用labels和ground truth labels计算loss,然后训练SVM。
在经过SVM分类后,会输出一堆的候选框得分(是一个2000x20的得分矩阵),这时候我们需要用的非极大值抑制得到想要的候选框了.大概步骤如下:
对矩阵按列从大到小排序
每列的最大值向下做非极大值抑制,遍历完所有列
依据阈值,得到候选区域的类型
注意到这里,我们得到的是一组预测好类别的候选区域了。
四、修正bbox,对bbox做回归微调(回归器训练)
目标检测问题的衡量标准是重叠面积。许多看似准确的检测结果,往往因为候选框不够准确,重叠面积很小。故需要一个位置精修步骤。 回归器:对每一类目标,使用一个线性脊回归器进行精修。正则项λ=10000。 输入为深度网络pool5层的4096维特征,输出为xy方向的缩放和平移。 训练样本:判定为本类的候选框中和真值重叠面积大于0.6的候选框。
我们使用一个简单的bounding-box回归用于提高定位的表现。这个bbox回归应用在SVM分类器给每个候选区域打分后,bbox回归认为候选区域和ground-truth之间是线性关系(因为在最后从SVM内确定出来的区域比较接近ground-truth,这里近似认为可以线性关系)
回归器是线性的,输入为Alexnet pool5的输出。
bbox回归认为候选区域和ground-truth之间是线性关系(因为在最后从SVM内确定出来的区域比较接近ground-truth,这里近似认为可以线性关系)
训练回归器的输入为N对值,,分别为候选区域的框坐标和真实的框坐标,下面在不必要时省略i。这里选用的Proposal必须和Ground Truth的IoU>0.6才算是正样本.
从候选框P到预测框G的基本思路如下:
因为我们在分类之后得到候选框P ,其中(p_x,p_y)为候选框的中心点,(p_w,p_h)为候选框的宽高,下面介绍中所有框的定位都用这种定义,即x和y表示中心点坐标,w和h表示框的宽高。知道候选框的表示,那么只要估计出出候选框与真实框的平移量和尺度缩放比例,就可以得到我们的估计框了
五、测试阶段
测试时其实分两个步骤
1.分类
在测试的时候,先对带检测图像提取出约2000个候选区域,将每个区域都进行缩放,然后将缩放后的图片输入CNN进行特征提取,对CNN输出的特征用SVM进行打分(每类都有一个SVM,21类就有21个SVM分类器),对打好分的区域使用NMS即非极大抑制(每类都单独使用)。
到这里分类就完成了,但是得到的位置只是候选区在图像中的位置,而候选区的位置并不一定就是ground truth,即检测目标的真实位置。
2.定位(回归)
将CNN对候选区域提取出的特征输入训练好的线形回归器中,得到更为精确的位置定位,具体情况在训练方法中详细介绍了。但要明确的是,这些回归器是按照类来训练的,即每类分类完后进行回归。
使用selective search的方法在测试图片上提取2000个region propasals ,将每个region proposals归一化到227x227,然后再CNN中正向传播,将最后一层得到的特征提取出来。然后对于每一个类别,使用为这一类训练的SVM分类器对提取的特征向量进行打分,得到测试图片中对于所有region proposals的对于这一类的分数,再使用贪心的非极大值抑制(NMS)去除相交的多余的框。再对这些框进行canny边缘检测,就可以得到bounding-box(then B-BoxRegression)。
(非极大值抑制(NMS)先计算出每一个bounding box的面积,然后根据score进行排序,把score最大的bounding box作为选定的框,计算其余bounding box与当前最大score与box的IoU,去除IoU大于设定的阈值的bounding box。然后重复上面的过程,直至候选bounding box为空,然后再将score小于一定阈值的选定框删除得到这一类的结果(然后继续进行下一个分类)。作者提到花费在region propasals和提取特征的时间是13s/张-GPU和53s/张-CPU,可以看出时间还是很长的,不能够达到及时性。因此才有SPP-Net及面向实时检测的Fast R-CNN和Faster R-CNN的提出。
六、存在的问题:
1、最大的缺点是对一张图片的处理速度慢,这是由于一张图片中由selective search算法得出的约2k个建议框都需要经过变形处理后由CNN前向网络计算一次特征,这其中涵盖了对一张图片中多个重复区域的重复计算,很累赘;
2、知乎上有人说R-CNN网络需要两次CNN前向计算,第一次得到建议框特征给SVM分类识别,第二次对非极大值抑制后的建议框再次进行CNN前向计算获得Pool5特征,以便对建议框进行回归得到更精确的bounding-box,这里文中并没有说是怎么做的,博主认为也可能在计算2k个建议框的CNN特征时,在硬盘上保留了2k个建议框的Pool5特征,虽然这样做只需要一次CNN前向网络运算,但是耗费大量磁盘空间;
3、训练时间长,虽然文中没有明确指出具体训练时间,但由于采用RoI-centric sampling【从所有图片的所有建议框中均匀取样】进行训练,那么每次都需要计算不同图片中不同建议框CNN特征,无法共享同一张图的CNN特征,训练速度很慢;
4、整个测试过程很复杂,要先提取建议框,之后提取每个建议框CNN特征,再用SVM分类,做非极大值抑制,最后做bounding-box回归才能得到图片中物体的种类以及位置信息;同样训练过程也很复杂,ILSVRC 2012上预训练CNN,PASCAL VOC 2007上微调CNN,做20类SVM分类器的训练和20类bounding-box回归器的训练;这些不连续过程必然涉及到特征存储、浪费磁盘空间等问题。