论文名称:《 OverFeat:Integrated Recognition, Localization and Detection using Convolutional Networks 》
论文下载:https://arxiv.org/abs/1312.6229
论文代码:https://cilvr.nyu.edu/doku.php?id=software:overfeat:start
1、文章亮点:
OverFeat就是一种特征提取算子,就相当于SIFT,HOG等这些算子一样。这篇文献充分利用了卷积神经网络的特征提取功能,它把分类过程中,提取到的特征,同时又用于定位检测等各种任务,只需要改变网络的最后几层,就可以实现不同的任务,而不需要从头开始训练整个网络的参数。文章利用卷积网络为分类、定位、检测提供了一个统一的框架,展示了在ConvNet中高效地实现多尺度(multiscale)滑动窗口方法,介绍了一种新的深度学习方法,通过学习预测对象边界来进行定位。Bounding box最后被累积计算而非抑制,以提高检测的置信度。论文指出不同的任务可以用相同的网络来同时学习。
归纳如下:
(1)用一个共享的CNN(ConvNet)来同时处理图像分类,定位,检测三个任务,可以提升三个任务的表现。
(2)用CNN有效地实现了一个多尺度的,滑动窗口的方法,来处理任务。
(3)提出了一种方法,通过累积预测来求bounding boxes(而不是传统的非极大值抑制)。
2、文章思路:
虽然ImageNet的数据包含一个大致充满图像的中心目标,但是目标在不同图像中的大小和位置有着显著差异(位于图像边角位置的小目标依旧存在)。解决这个问题有以下几个思路:
(1)使用多个固定大小的滑动窗口移动,对每个扫过的窗口图像做CNN预测。该方法的缺点在于窗口没有包含整个目标,甚至中心也没有,只是包含了一部分(比如狗狗的头)。这种方法虽然适合做分类,但是定位和检测效果很差。
(2)训练一个卷积网络,不仅产生分类的分布,还产生预测框bouding box(预测目标的大小和位置)。
(3)累积每个位置和尺寸对应类别的置信度。
AlexNet展示了CNN可在图像分类和定位任务上取得了优秀的表现,但是并没有公开描述他们的定位方法。此篇OverFeat论文是第一次清晰地解释CNN如何用于定位和检测。
3、任务分析:
论文探索了图像处理的三大任务,按难度上升的顺序排列如下:
(1)分类(classification):给定一张图片,为每张图片打一个标签,说出图片是什么类别,然而因为一张图片中往往有多个类别,因此我们允许你预测出来的概率最大的5个,只要这五个概率最大的包含了我们人工标定标签(人工标定每张图片只有一个标签,只要你用5个你预测的最大概率的类别,把label类别囊括在内即可)。
(2)定位(localization):定位通常与分类一起。图像中通常包含一个主要对象,除了需要给出5个类别判断囊括这个对象对象的类别,还需要返回图像中这个主要对象的bbox (bounding box),且bbox与GT的IoU必须达到50%。每个bbox必须标注为正确的label,即bbox和label不能分离。
(3)检测(detection):与分类和定位不同,每张图像都可以由任意数量的object (也可以没有object),评价标准是mAP。一张图像有很多个目标物体,需要全部找出来(分类并定位)。分类和定位共享数据集(使用同一个数据集),而检测使用另外的数据集,里面包含更多的小目标(这样的训练集有利于提升模型的性能)。
1、FCN(Fully Convolutional Network)——大名鼎鼎的全卷积网络:
对于一个各层参数结构都设计好的CNN网络模型来说,输入的图片大小是固定的,比如Alexnet设计完毕后,网络输入图片大小就是227*227。作者希望让一个已经设计完毕的网络,也可以输入任意大小的图片,通过FCN实现。
FCN 精髓(全卷积,即全都用卷积层,包括FC层也用卷积层来实现):
(1)用 卷积层 实现 全连接层 的效果,把FC层操作看成是对一整张图片的卷积层运算。
(2)把 全连接层 看做是 1*1卷积层,即采用1*1大小的卷积核,进行卷积层运算。
具体如何让一个已经设计好的CNN模型,可以输入任意大小的图片:
上面图中绿色部分表示:卷积核大小。假设我们设计了一个CNN模型,输入图片大小是14*14,通过第一层卷积后我们得到10*10大小的图片,然后接着通过池化得到了5*5大小的图片。
接着要从:5*5大小的图片 变成 1*1大小的图片(这就是FC层做的事情):
(1)传统的CNN:如果从以前的角度进行理解的话,那么这个过程就是全连接层,我们会把这个5*5大小的图片,直接reshape展平成为一个一维的向量,进行计算(写cnn代码的时候,这个时候经常会在这里加一个flatten函数,就是为了展平成一维向量)。
(2)创新的FCN:FCN并不是把5*5的图片展平成一维向量,再进行计算,而是直接采用5*5的卷积核,对一整张图片进行卷积运算,卷积得到这个1*1的图片(当然有很多层,这其实是个列向量)。
其实这两个的表面效果是相同的,只是角度不同,FCN把这个过程当成了对一整张特征图进行卷积,同样,后面的全连接层也是把它当做是以1*1大小的卷积核进行卷积运算。但是,卷积层引入的非线性比直接展平特征图保留了更多的有效信息!
用上面的网络,输入一张任意大小的图片,比如16*16大小的图片,具体请看下面的示意图:
网络最后的输出是一张2*2大小的图片。这个时候,我们就可以发现采用FCN网络,可以输入任意大小的图片。同时需要注意的是网络最后输出的图片大小不在是一个1*1大小的图片,而是一个与输入图片大小息息相关的一张图片了。
总结一下:对14*14的图像进行卷积操作,在得到5*5的feature map后的这一步,如果使用直接使用全连接层,就会把它直接压平再全连接(直接reshape),这样就破坏了原feature map的图像位置关系,直接转为一列特征。但是如果使用的是卷积,最后也会得到1*1*C的feature map,C是channel数,也是类别的大小,但是卷积运算使得得到的列向量中包含了原feature map的图像位置关系。如果输入是一张16*16的图像,经过层层卷积后就会得到2*2*C的feature map,这个时候可以对这个2*2的4个值做一个取最大或平均,就会变成一个值了,即最后得到的也是列向量。以此类推,来了更大的图像,最后得到的feature map就是3*3*C,4*4*C,5*5*C的大小,输出的大小和输入的大小相关,但总是可以对这个输出进行max池化(取最大)来得到符合FC层输出形式的各类别的置信值。可以用此方法对16*16的图像产生了“2*2”个输出,以此类推我们可以在测试时使用更大的图像(使用多scale),产生“更多”的输出进行(取最大)预测(后面跟上max池化)。这个做法相对于传统的滑动窗口(用14*14大小,步长为2的滑动窗口在16*16的图像上执行滑动4次,每次进行一次全连接操作并且进行分类)的优点是,保证了效率(一次全卷积)同时可以用各种不同尺度图像作为输入(通过卷积把三维张量变成列向量,比直接FC的reshape更灵活),消除了很多冗余计算,提高了模型的鲁棒性又保证了效率。
2、offset max-pooling———宁可错杀三千不可放过一个的全面的池化策略:
offset ,采用一维作为示例,来讲解原理:
如上图所示,我们在x轴上有20个神经元,如果我们选择池化size=3的非重叠池化,那么根据我们之前所学的方法应该是:对上面的20个,从1位置开始进行分组,每3个连续的神经元为一组,然后计算每组的最大值(最大池化),19、20号神经元将被丢弃,如下图所示:
我们也可以在20号神经元后面,人为的添加一个数值为0的神经元编号21,与19、20成为一组,这样可以分成7组:[1,2,3],[4,5,6]……,[16,17,18],[19,20,21],最后计算每组的最大值就是经典的max-pooling。可是如果我们只分6组的话,我们除了以1作为初始位置进行连续组合之外,也可以从位置2或者3开始进行组合。也就是说我们其实有3种池化组合方法:
A、△=0分组:[1,2,3],[4,5,6]……,[16,17,18];
B、△=1分组:[2,3,4],[5,6,7]……,[17,18,19];
C、△=2分组:[3,4,5],[6,7,8]……,[18,19,20];
示意图如下:
以往的CNN中,一般我们只用了△=0,得到池化结果后,就送入了下一层。于是文献的方法是,把上面的△=0、△=1、△=2的三种组合方式的池化结果,分别送入网络的下一层。这样的话,我们网络在最后输出的时候,就会出现3种预测结果了。
如果是2维图片的话,那么(△x,△y)就会有9种取值情况(3*3);如果我们在做图片分类的时候,在网络的某一个池化层加入了这种offset 池化方法,然后把这9种池化结果,分别送入后面的网络层,最后我们的图片分类输出结果就可以得到9个预测结果(每个类别都可以得到9种概率值,然后我们对每个类别的9种概率,取其最大值,做为此类别的预测概率值)。优中选优,避免因为池化而漏掉某些信息,尤其是边缘的信息。
1、Alexnet的训练、测试:
(1)训练阶段:每张训练图片256*256,然后我们随机裁剪出224*224大小的图片,作为CNN的输入进行训练。
(2)测试阶段:输入256*256大小的图片,我们从图片的5个指定的方位(上下左右+中间)进行裁剪出5张224*224大小的图片,然后水平镜像一下再裁剪5张,这样总共有10张;然后我们把这10张裁剪图片分别送入已经训练好的CNN中,分别预测结果,最后用这10个结果的平均作为最后的输出。
Alexnet在测试阶段的时候,采用了对输入图片的四个角落和中心位置进行裁剪,得到10个大小为网路哟输入大小的图片,分别进行预测,分别得到结果,选出最好结果(平均或最大池化),这最后的结果就是类似对应于上面2*2的预测图选一个最优值。这个2*2的每个像素点,就类似于对应于一个角落裁剪下来的图片预测分类结果。只不过Alexnet把这4个像素点,相加在一起,求取平均值,作为该类别的概率值。
overfeat这篇文献的图片分类算法,在训练阶段采用与Alexnet相同的训练方式,然而在测试阶段可是差别很大,overfeat就是把采用FCN的思想把全连接层看成了卷积层,让我们在网络测试阶段可以输入任意大小的图片。这就是文献最大的创新点(overfeat的方法不是裁剪出10张224*224的图片进行结果预测平均,具体方法请看下面继续详细讲解)。
背景:AlexNet是2012年ILSVRC比赛的冠军,它的出现直接打破了沉寂多年的图片识别领域(在1998年出现LeNet-5网络一直占据图片识别的领头地位),给该领域带来了新的契机,并一步步发展至今,甚至打败了人类的识别精确度,可惜的是2017年的ILSVRC举办方宣布从2018年起将取消该比赛,因为目前的神经网络精确度已经达到很高的程度。但深度学习的步伐不会停止,人们将在其他方面进行深入的研究。AlexNet是神经网络之父Hinton的学生Alex Krizhevsky开发完成,它总共有8层,其中有5个卷积层,3个全链层,附上最经典的AlexNet网络架构图,如下。Alex在他的论文中写到,他在处理图片的时候使用了两个GPU进行计算,因此,从图中看出,在卷积过程中他做了分组的处理。
2、OverFeat 网络结构:
(1)把网络的第一层到第五层看做是特征提取层,然后不同的任务共享这个特征提取层。基本用了同一个网络架构模型(特征提取层相同,分类回归层根据不同任务稍作修改、训练)、同时共享基础特征。论文的网络分为两个版本,一个快速版,一个精确版。下图是精确版的网络结构图:
1)训练集:ImageNet (120W, C=1000);(训练的图像不是原始图像,而是 fixed crop。把图像缩放为最小边长为256 pixels,然后随机截取5个大小分别为221x221的crop,水平翻转后变为10个。然后进行训练)
2)网络输入:从上面的表格,我们知道网络输入图片大小为221*221;
3)网络结构:基本上和AlexNet一样,也使用了ReLU激活,最大池化。不同之处在于:
① 作者没有使用局部响应归一化层(LRN);
② 没有采用重叠池化;
③ 在第一层卷积层,stride设置,文章选择了2,这个与AlexNet不同 ( AlexNet选择的stride是4,在网络中,如果stride选择比较大得话,虽然可以减少网络层数,提高速度,但是却会降低精度 )。
需要注意的是,把f7这一层全连接层,设置成卷积核大小为5*5的卷积层,即把整个网络看成FCN模型,没有了全连接层的概念,全部采用卷积层实现功能(尤其是FC层)。我们在测试阶段要输入各种大小的图片,FCN思想的采用会在这一步极大地帮助到网络。OverFeat网络和alexNet最大的不同之处在于它在测试测试阶段使用了不同的方法来预测。OverFeat网络的测试阶段,用到了多尺度、滑动窗口的方法(实验最多输入了6个不同尺度的图像)。这也是论文最大的创新点。
(2)本文在测试时,采用的是 图像金字塔(图片上下采样放缩)+ sliding window 的方法。
即对图像做不同尺度的缩放,对不同尺度的image进行卷积,得到不同尺寸的feature map,然后用固定大小(i.e.5x5)的sliding window以等距步长在feature map上滑动,对每个sliding window进行分类。
最终分类是通过这样的步骤:
1)在每个尺度下,取每个类的最大值,这样构成C维向量,C个值对应了C个类别在这个尺度下的图片中的目标置信值;
2)对不同尺度的C维向量取均值,得到了同一图片在不同尺度下的对每个类别的置信值;
3)取平均化后的C维向量的Top1或Top5作为预测的类,对每张图片取置信值第一或者前五高的类别作为输出的预测类别;
3、网络训练:
(1)训练输入:对于每张原图片为256*256,然后进行随机裁剪为221*221的大小作为CNN输入,进行训练。
(2)参数设置:
1)min-batchs选择128
2)权重初始化选择高斯分布的随机初始化:
3)采用随机梯度下降法:动量项参数大小选择0.6,L2权重衰减系数大小选择10-5次方。
4)学习率一开始选择0.05,然后根据迭代次数的增加,每隔几十次的迭代后,就把学习率的大小减小一半。
5)DropOut,这个只有在最后的两个全连接层,才采用dropout,dropout比率选择0.5,也就是网络的第6、7层。
训练阶段同AlexNet。
网络结构在训练完后,参数的个数、结构是固定的,测试阶段并没有改变网络的结构,也无法改变网络参数。
1、Alexnet(分类算法)测试时的方法是:输入一张图片256*256,然后进行multi-view裁剪,也就是从图片的四个角进行裁剪,还有就是一图片的中心进行裁剪,这样可以裁剪到5张224*224的图片。然后把原图片水平翻转一下,再用同样的方式进行裁剪,又可以裁剪到5张图片。把这10张图片作为输入,分别进行预测分类,在后在softmax的最后一层,求取个各类的总概率,求取平均值。
2、Alexnet (分类算法)这种预测方法存在两个问题:首先这样的裁剪方式,把图片的很多区域都给忽略了,说不定这样裁剪刚好把图片物体的一部分给裁剪掉了;另外一方面,裁剪窗口重叠存在很多因图片重叠而产生的冗余的计算,像上面我们要分别把10张图片送入网络,可见测试阶段的计算量还是蛮大的。
3、Overfeat算法(用于分类):训练完上面所说的网络之后,在测试阶段,文章不再是用一张221*221大小的图片了作为网络的输入,而是用了6张大小都不相同的图片,也就是所谓的多尺度输入预测,如下表格所示:
测试阶段网络输入图片大小分别是245*245,281*317……461*569。
然后当网络前向传导到layer 5的时候,就使出了FCN和offset pooling一记组合拳。以输入一张图片为例(6张图片的计算方法都相同),讲解layer 5后面的过程:
(1)layer-5 pre-pool【输入是17*17,输出是(5*5)*(3*3)】:
通过大小为(3,3)的池化进行池化,然后△x=0、1、2,△y=0、1、2,这样我们可以得到对于每一张特征图,我们都可以得到9幅池化结果图。以上面表格中的sacle1为例,layer-5 pre-pool大小是17*17,经过池化后,大小就是5*5,然后有3*3张结果图(不同offset得到的结果)。
(2)layer-5 post-pool【输入是(5*5)*(3*3),输出是(1*1)*(3*3)*C】:
在训练的时候,全连接层输入的大小是4096*(5*5),然后经过FC层,得到4096*(1*1)。但是现在输入的是各种不同大小的图片,因此从第5层后采用FCN的招式(用卷积层代替FC层),让网络继续前向传导。我们从layer-5 post-pool到第六层的时候,如果把全连接看成是卷积,那么其实这个时候卷积核的大小为5*5,因为训练的时候,layer-5 post-pool得到的结果是5*5。因此在预测分类的时候,假设layer-5 post-pool 得到的是7*9(上面表格中的scale 3),经过5*5的卷积核进行卷积后,那么它将得到(7-5+1)*(9-5+1)=3*5的输出。然后我们就只需要在后面把它们拉成一维向量摆放就ok了,这样在一个尺度上,我们可以得到一个C*N个预测值向量,每一列就表示图片属于某一类别的概率值,共C列,然后我们求取每一列(类别)的N个待选概率中的最大值作为本尺度的这个类别的概率值。
从上面过程,我们可以看到整个网络分成两部分:layer 1~5这五层我们把它称之为特征提取层;layer 6~output我们把它们称之为分类层。具体流程示意图如下:
以一维为例,offset池化就是移动一定的位置再池化,(b)中Δ=0,1,2 就可以表示可以做三种池化,得到三个结果,因为图像是二维的,所以最后会得到3*3也就是9种池化结果,最后对于每个类别就有9个结果,可以对这些结果集成预测(下图的例子中只考虑一维的所以图中最后会得到三个结果,红蓝绿三种颜色表示三种池化后得到的结果)图中(c)表示进行3*3池化后得到6*6的图(6个格子)。(d)表示经过5*5的全卷积得到2*2的图(2个格子)。e表示把位置信息(长度为2)和offset方式(3种)交错后得到的最后的输出图。
在实际的二维图像处理中,上述这个操作会对重复6*2也就是12次,其中6代表6个scale,如下图所示的6个不同的scale,而2表示水平翻转后会得到两个图。在这12次里面的每一次,对位置信息取最大,以Scale2为例,最后大小为6x9xC,就在这6x9个值中取最大。那么就会得到12个长度为C的向量,12个向量加起来取平均,得到一个长度为C的向量,然后求Top1或Top5,得到最后的结果。
4、Overfeat算法(用于定位):
用于定位任务的时候,就把分类层(上面的layer 6~output)给重新设计,把分类改成回归问题,然后在各种不同尺度上训练预测物体的bounding box。把用分类学习的特征提取层的参数固定下来,然后继续训练后面的回归层的参数,网络包含了4个输出,对应于bounding box的上左上角点和右下角点,然后损失函数采用欧式距离L2损失函数。
至于检测,就是分类+定位。重新设计网络的最后部分,训练分类的同时也进行回归,类似YOLOv1。
总之,这篇上古时期的文章理解起来确实不容易,费了好大劲,脑累!