本文大部分转自晓雷在知乎上的文章。
RCNN通过卷积神经网络提取图像特征,第一次将目标检测引入了深度学习领域;SPPNet通过空间金字塔池化,避免了对于同一幅图片多次提取特征的时间花费。
但是无论是RCNN还是SPPNet,其训练都是多阶段的。首先通过ImageNet预训练网络模型,然后通过检测数据集微调模型提取每个区域候选的特征,之后通过SVM分类每个区域候选的种类,最后通过区域回归,精细化每个区域的具体位置。为了避免多阶段训练,同时在单阶段训练中提升识别准确率,Fast RCNN提出了多任务目标函数,将SVM分类以及区域回归的部分纳入了卷积神经网络中。
网络结构
类似于RCNN,Fast RCNN首先通过Selective Search产生一系列的区域候选,然后通过CNN提取每个区域候选的特征,之后训练分类网络以及区域回归网络。对比SPPNet,我们可以看出Fast RCNN的区别所在:
首先是将SPP换成了ROI Poling。ROI Poling可以看作是空间金字塔池化的简化版本,它通过将区域候选对应的卷积层特征还分为H*W个块,然后在每个块上进行最大池化就好了。每个块的划分也简单粗暴,直接使用卷积特征尺寸除块的数目就可以了。SPP是pooling成多个固定尺度,RoI只pooling到单个固定的尺度 (论文通过实验得到的结论是多尺度学习能提高一点点mAP,不过计算量成倍的增加,故单尺度训练的效果更好)。而对于H*W的设定也是参照网络Pooling层的,例如对于VGG-19,网络全连接层输入是7*7*512,因此对应于我们的H,W就分别设置为7,7就可以了。
另外一点不同在于网络的输出端,无论是SPPNet还是RCNN,CNN网络都是仅用于特征提取,因此输出端只有网络类别的概率。而Fast RCNN的网络输出是包含区域回归的。即joint training (SVM分类,bbox回归 联合起来在CNN阶段训练)把最后一层的Softmax换成两个,一个是对区域的分类Softmax(包括背景),另一个是对bounding box的微调。这个网络有两个输入,一个是整张图片,另一个是候选proposals算法产生的可能proposals的坐标。(对于SVM和Softmax,论文在SVM和Softmax的对比实验中说明,SVM的优势并不明显,故直接用Softmax将整个网络整合训练更好。对于联合训练: 同时利用了分类的监督信息和回归的监督信息,使得网络训练的更加鲁棒,效果更好。这两种信息是可以有效联合的。)
注意点:
论文在回归问题上并没有用很常见的2范数作为回归,而是使用所谓的鲁棒L1范数作为损失函数。
论文将比较大的全链接层用SVD分解了一下使得检测的时候更加迅速。虽然是别人的工作,但是引过来恰到好处(矩阵相关的知识是不是可以在检测中发挥更大的作用呢?)
ROI Pooling
与SPP的目的相同:如何把不同尺寸的ROI映射为固定大小的特征。ROI就是特殊的SPP,只不过它没有考虑多个空间尺度,只用单个尺度(下图只是大致示意图)。
ROI Pooling的具体实现可以看做是针对ROI区域的普通整个图像feature map的Pooling,只不过因为不是固定尺寸的输入,因此每次的pooling网格大小得手动计算,比如某个ROI区域坐标为(x1,y1,x2,y2),那么输入size为(y2-y1)·(x2-x1),如果pooling的输出size为pooledheight·pooledweight,那么每个网格的size为 ((y2-y1)/pooledheight)·((x2-x1)/pooledweight)。
Bounding-box Regression
有了ROI Pooling层其实就可以完成最简单粗暴的深度对象检测了,也就是先用selective search等proposal提取算法得到一批box坐标,然后输入网络对每个box包含一个对象进行预测,此时,神经网络依然仅仅是一个图片分类的工具而已,只不过不是整图分类,而是ROI区域的分类,显然大家不会就此满足,那么,能不能把输入的box坐标也放到深度神经网络里然后进行一些优化呢?rbg大神于是又说了"yes"。在Fast-RCNN中,有两个输出层:第一个是针对每个ROI区域的分类概率预测p = {p0 , p1 , ... , pK},第二个则是针对每个ROI区域坐标的偏移优化tk = (tkx , tky , tkw , tkh),0 <=k <=K 是多类检测的类别序号。这里我们着重介绍第二部分,即坐标偏移优化。
假设对于类别 k*,在图片中标注了一个groundtruth坐标:t* = (t*x , t*y , t*w , t*h),而预测值为t = (tx , ty , tw , th),二者理论上越接近越好,这里定义损失函数:
这里,smooth L1(x)中的x即为ti - ti*即对应坐标的差距。该函数在 (−1,1) 之间为二次函数,而其他区域为线性函数,作者表示这种形式可以增强模型对异常数据的鲁棒性,整个函数在matplotlib中画出来是这样的
对应的代码在smooth_L1_loss_layer.cu中。
现在的Fast RCNN模型已经接近完美了,识别检测全部放到了卷积神经网络的框架里面,速度也是相当的快。美中不足的是,区域建议网络还是Selective Search,网络其他部分都能在GPU中运行,而这部分需要在CPU中运行,有点拖后腿啊。接下来的Faster RCNN已经弥补了这个问题,下一篇中再讲述一下Faster RCNN~