检测之旧文新读(二) --SPP-net

动机:

CNN和RCNN输入一张图片需要固定尺寸,这要造成了,不同尺寸,长宽比例的输入图片要进行拉伸或者剪切的形变才能进行输入,这样造成了准确率和精确度的下降,另外,由于输入固定尺寸的主要原因就是全连接层,所以就需要在卷级层和全连接层进行某些操作使得变成固定输入尺寸。如何设计一个feature map输出固定尺寸又保持特征有效的操作,这应该是作者最开始的动机。

为什么会想到SPP(Spatial Pyramid Pooling)

文中提到SPP主要是基于词袋模型Bag-of-words的一种拓展。这个如何理解呢?只能说都有图像进行分块。关于池袋模型直接有wiki,和这个博客:http://blog.sina.com.cn/s/blog_5d2990b70100xpiw.html

整体模型和贡献:

检测之旧文新读(二) --SPP-net_第1张图片
SPP示意图
与先前的卷积流程图对比

提出了spatial pyramid pooling,使得不同的输入可以输出相同的尺度特征。基于此会有一系列的应用和效果的提升。比如使得模型不在受全连接层的影响只能输入固定的尺寸减少由于样本形变造成的误差,又比如检测中的提速,共享卷积层成为可能。这些均体现在下面要总结的实验中。不过在将实验之前,可以先讲一讲SPP的实现。

SPP的实现:

具体实现:利用卷积配合相应的步进来实现:

  1. 对于固定的输入图片:先计算出相应比例的滑动窗口的大小和步进.比如你feature map为axa,想要变成nxn的bins. 一种实现方法就是利用滑动窗口卷积的方式,比如你设计一个a/n 大小的卷积,步进也是a/n大小的步进,然后进行卷积,或者进行pooling,然后flat给后续的全连接操作。卷积采用a/n的上取整,而步进采用a/n的下取整.
    你可能会问为什么卷积采用a/n的上取整,而a/n则采用下取整?
    答:这个你可以进行2*2的排列组合,用a=13,n=3,窗口取上整,步进取下整,那么划过的窗口为12,期间没有特征像素值遗漏,若窗口取下整,步进去上整,那么也是12,那么此时步进为4,窗口才3,中间会有特征像素的遗漏。都取上整,滑动太大为16,都取下整滑动范围太小,才9.所以选择窗口取上整,步近取下整(感叹每个实验细节都是可以细细推敲的)。
  2. 对于多尺度的输入图片来说:也是固定集中尺度:然后对于不同尺度来进行滑动窗口的大小和步近,比如180*180 和224*224,然后先在一个epoch用这个10/n 训练180*180的图片的权值,然后使用13/n在训练一个epoch,权值保持不变,不断迭代训练直到收敛。这种训练方式是优化迭代的常见手法,也可以联想到后面faster RCNN的two stage想关联

实验:

可视化特征与图像空间的位置关系:

实验目的:为了验证feature map上面也存在位置信息。为了替后面的检测效果为什么有效提供证据
实验步骤:
1)找对某个特征(这里是圆形和^型)敏感的conv5层的channel层,如何找?用visual 来自RCNN。
2) 然后找几张含有这个特征图片来证明,比如是否轮胎的位置在feature map的相应位置也为较高的值等。
实验结果分析: 在feature map上面确实存在位置信息
这个实验对未来的帮助: 提出了简化版的图像ROI坐标与特定卷积层ROI坐标的对应关系。具体如下:

图像的ROI坐标映射到特定卷积层ROI坐标的公式:

这个在spp-net 附录里面http://blog.csdn.net/mr_curry/article/details/53914502,这篇博客解释可以参考:
我们来看一下在caffe里面这种映射关系的实现方式:
int roi_start_w = round(bottom_rois[1] * spatial_scale_);
int roi_start_h = round(bottom_rois[2] * spatial_scale_);
int roi_end_w = round(bottom_rois[3] * spatial_scale_);
int roi_end_h = round(bottom_rois[4] * spatial_scale_);
caffe实现倒是简单的将其左上角的坐标和右下角的坐标直接除以s并取整(代码是用round函数是四舍五入取整),s(公式中是spaital_scale)是所有stride的乘积。注意stride包括你卷积的步进(stride)还包含你池化层的步进(stride)。但是这里和原文其实还是有点不同。文中还有关于padding的一些问题?另外,也可以看到这个是比较粗糙的简化版,对于小物体可能就不会那么适合,如何改进?

多层级池化提高准确率(Multi-level Pooling Improves Accuracy)

  1. 实验内容:多层级的解释如下:SPP是将一个feature map 可能按照不同尺度进行网格划分然后pool 然后在级联。比如网格尺度分别为1x1,2x2,4x4 的话那么就是3层。如后面的fast RCNN就ROI pool就是层级为1的SPP.这个实验的内容就是验证这个层级数对最后准确率的影响。
  2. 实验步骤:调节层级数会相应的进行调节参数个数,于是作者先使用层级数较低的模型取得参数规模较小的SPP-net模型和对应拥有更多的参数的原始CNN模型进行效果对比。
    提醒我们:你自己设计的结构后,网络的参数相比原始的模型参数变多的的时候,为了证明你的结构有效,你需要做实验证明你的模型提升效果不仅仅是因为参数的增多。
  3. 实验结果分析:
    检测之旧文新读(二) --SPP-net_第2张图片

    可以看到SPP比没有SPP大约提高0.5-1.6个mAP。可以看出其实效果提升不是很明显,我的理解是:因为文中使用的是Max Pooling:那么在1x1的最大值一定会出现在下面2x2的的最大值中,相应的2x2的最大值一定会出现在6x6的最大值中。所以里面其实存在大量的重复冗余的。可能这也是fast RCNN为什么只用层数为1的ROI pool的原因。所以我感觉multi-level对应max pool我觉得效果即使有提升也提升很有限。 (如果你到这里对于实验你存在如果multi-level对实验有影响,那么我们实际应用中应该使用多少层级的疑问?那么你应该就有下意识的存在对人为参数质疑的习惯了。)

multi-size 和 full image 对classification的效果有提升:

1. 实验内容: multi-size的意思是输入图片resize到不同的图片尺寸进行训练,full image的意思就是保持原始图片的长宽比,可以变化尺寸,然后输入一整张图片进行训练。
2. 实验目的: 很明显,因为spp-net使得原来只能固定尺寸输入的模型变得可以任意输入,为了证明这样任意输入的好处:多尺度输入,不改变图片的原始长宽比的输入对分类效果是有提升的,从而提高自己的研究的价值。
3.实验步骤:
针对multi-size 作者做了两组,一组直接将图片尺寸变化到224和180,另一组实验室在[180,224]上进行随机尺寸变化,然后进行训练。针对full image min(w; h)=256,保持图片的长宽比(同理,多少尺寸才真正合适呢?这里也有人为参数)
4.实验结果分析:

检测之旧文新读(二) --SPP-net_第3张图片

可以看书两种实验结果效果实际上都有提升,但是提升的都不是很明显
5.对于未来的帮助:从实验上结果讲,只能说 multi-size在训练的时候可以运用,虽然后期模型试验验证CNN模型本身有尺度不变性,但是其实现在multi-size的训练对于提高mAP已经成为常见手段了,即使实际上提升的不多。 对于full image而言:spp-net里面说物体剪切和损失会对识别最后造成影响,但是现在基本上就是这么干的。貌似实际上影响不大,如何解释呢?

将spp-net用来做检测:

整体流程还是使用生成候选框的算法,然后使用SPP的共享卷积特征的作用提升计算ROI特征时间,然后在送到SVM里面训练分类器,然后使用loc regression进行位置的回归。
数据集:
正样本:IOU>0.5
负样本:IOU<0.3, 并且排除掉两个负样本之间IOU>0.7的样本。
最后对full image 进行了muiti-Scale的输入训练。

1. 实验目的:因为这个也是spp的一个贡献,当然不是说固定输入尺寸了,就不能做proposal和feature map上面的图像映射了,我觉得主要的原因是因为之前由于输入图片尺寸限定为224x224的关系, 对于一张需要检测的输入图片来说太小了,而且一般都进行了一定的形变,会影响检测精度,而spp接触了输入图片尺寸这一限定,也自然没有了后续的一些对检测的不良影响。另外,最终要的一点就是,可以检测输入一整张图了,可以共享卷积计算来提高整体的检测成为了可能。
2.实验步骤:之前的RCNN是每个proposal 都重新计算一次CNN的特征,然后进行SVM的分类。
现在是只计算一次整张图的feature map,然后计算proposal和feature map上面的位置关系,然后简单的剪切操作。剪切后的大小不一样,无法直接使用后续的fc层,所以就使用提出来的spp来统一大小。但是这里还是最后使用fc layer后面的特征 加上SVM来进行分类(使用SVM和特征提取步骤分离这个是这里的一个“缺点”,后续fast RCNN进行了改进。
3.实验结果分析:

检测之旧文新读(二) --SPP-net_第4张图片
image.png

由于这样做主要是提高了速度,所以作者也是主要在速度方面的结果分析
理论上:居然是用O(像素点个数)来进行表述:来自文章的一句话:分析的话使用:R-CNN is O(n *227^2) with the window number n (~2000). This complexity of our method is O(r *s^2) at a scale s, where r is the aspect ratio实验上:一般如果是我做的话,也是在相同的服务器上面跑,然后看看时间,文中作者其实也是这么干的。

其他:

模型结合的讨论:Boosting的方法,说明简单的使用convoluted是有效的,但是fine-tune的简单boosting是没有效果的。
如何做:对于预训练的模型,先随机初始化两组权值,然后在imageNet上面进行预训练,然后都训练到收敛,两者的mAP相当,然后分别将两组得到的candidate window在同一张测试图上,然后进行非极大值抑制,得到最终结果。效果提升~2%mAP

但是,如果你使用同一个imageNet进行预训练的卷积权值,然后使用分别两个不同初始化fc6,和fc7 并组合,发现并没有效果提升,这个是为什么呢?效果的好处来自于卷积层,和没有来自fine-tune后面的影响。这个可以进行一些解释,但是我觉得后面有时间可以好好总结一下检测boosting (其他ensemble learning)的方法。

参考文献:
  1. He K, Zhang X, Ren S, et al. Spatial pyramid pooling in deep convolutional networks for visual recognition[C]//European Conference on Computer Vision. Springer, Cham, 2014: 346-361.

你可能感兴趣的:(检测之旧文新读(二) --SPP-net)