深度学习之检测、分类及分割(一)

概括下最近看的博客和论文,整理下基于深度学习的目标检测方面的知识点:

一. RCNN (Regions with CNN) RBG (2014年)

论文作者博客:http://www.rossgirshick.info/

学习参考博客:

https://zhuanlan.zhihu.com/p/113484192

https://blog.csdn.net/briblue/article/details/82012575

https://www.jianshu.com/p/381ffa6e525a

1. 候选区域选择(region proposal), 用到了SelectiveSearch

2. 对于每个区域利用CNN抽取一个固定长度的特征向量(Alexnet, 基于Caffe进行的代码开发)

3. 再对每个区域利用SVM进行目标分类。同时做边界回归。

技巧:采用在ImageNet上已经训练好的模型,然后在PASCAL VOC数据集上进行fine-tune。做迁移学习

Selective search产生的候选区域大小不一,为了与Alexnet兼容,R-CNN采用了非常暴力的手段,无视候选区域的大小和形状,统一变换到227*227的尺寸。变换时可以先对这些区域进行膨胀处理,box周围附加p个像素,这里p=16

存在的问题:

1. 多个候选区域对应的图像需要预先提取,占用较大的磁盘空间

2. crop/warp(归一化)产生的物体截断或拉伸,会导致输入CNN的信息丢失

3. 每一个ProposalRegion都需要进行CNN网络计算,多数是互相重叠,重叠部分会被多次重复提取feature

 

二. Fast RCNN 

论文作者博客:http://www.rossgirshick.info/

学习参考博客:

https://zhuanlan.zhihu.com/p/43624561

https://blog.csdn.net/fengbingchun/article/details/87091740

1. 和SPPnet做比较,Fast-RCNN训练速度达3倍。测试速度达10倍。

2. 网络首先做的就是用一些卷积神经网络以及最大值池化层等图片进行特征提取

3. 利用感兴趣区域池化层从特征图中提取一个特征向量,在全连接层末尾产生两个分支

一个产生softmax来估计K个类别及背景的概率(K+1类别的softmax概率),另外一个层输出四个实数数据,确定边界框

4. ROI MAX Pooling可以将任意的proposal转化成固定的HxW的区域。

5. 预训练网络的初始化

6. Fast-RCNN,整个网络权重参数进行反向传播训练是Fast-RCNN网络独有的能力,SPPnet网络不能更新金子塔前面的卷积网络的参数。

7.使用多任务损失L来对分类和边界框进行联合优化

8. 不用限定网络的输入结构,不管特征图的大小如何,进入到空间金子塔池化层后,变成固定大小的值

 

三. SPP-Net

论文作者博客:http://kaiminghe.com/

学习参考博客:

https://blog.csdn.net/fengbingchun/article/details/87091740

https://blog.csdn.net/weixin_43624538/article/details/87966601


SPP的结构如上图所示,将最后一个卷积层后紧跟SPP层,作为全连接层的输入。至此,网络不仅可对任意长宽比的图像进行处理,而且可对任意尺度的图像进行处理。图像就不需要reshape了。(如果固定网络输入的话,要么选择crop策略,要么选择warp策略,crop就是从一个大图扣出网络输入大小的patch(比如227×227),而warp则是把一个bounding box的内容resize成227×227。这两种方法都存在着丢失或者扭曲原始图像信息的缺陷。这样CNN获取的特征也就受到了限制,从而导致后续分类/预测的泛化能力不够。)

SPP已有一定的速度提升,它在ConvNet的最后一个卷积层才提取proposal,但是依然有不足之处。和R-CNN一样,它的训练要经过多个阶段,特征也要存在磁盘中,另外,SPP中的微调只更新spp层后面的全连接层,对很深的网络这样肯定是不行的。

 

四. Faster-RCNN(https://zhuanlan.zhihu.com/p/31426458)

论文作者博客:http://kaiminghe.com/

参考学习博客:

https://zhuanlan.zhihu.com/p/31426458

https://blog.csdn.net/weixin_43198141/article/details/90178512

https://www.jianshu.com/p/4064de5499d5

虽然Fast-Rcnn基于R-CNN有了很大的改进,但是Fast-Rcnn仍然是基于Selective Search方法进行提取region proposal,而Selective Search方法提取region proposal的计算是无法用GPU进行的,无法借助GPU的高度并行运算能力,所以效率极低。而且选取2000个候选区域,也加重了后面深度学习的处理压力。那Faster-RCNN在吸取了Fast-RCNN的特点的前提下,采用共享的卷积网组成RPN网络(Region Proposal Network),用RPN直接预测出候选区域建议框,数据限定在300个,RPN的预测绝大部分在GPU中完成,而且卷积网和Fast-RCNN部分共享,因此大幅度提升了目标检测的速度。

可以看成:Faster-RCNN = RPN(区域生成网络)+ Fast-RCNN,用RPN网络代替Fast-RCNN中的Selective Search是Faster-RCNN的核心思想。
RPN网络首先经过3x3卷积,再分别生成positive anchors和对应bounding box regression偏移量,然后计算出proposals;而Roi Pooling层则利用proposals从feature maps中提取proposal feature送入后续全连接和softmax网络作classification(即分类proposal到底是什么object)

preview

假设在conv5 feature map中每个点上有k个anchor(默认k=9),而每个anhcor要分positive和negative,所以每个点由256d feature转化为cls=2k scores;而每个anchor都有(x, y, w, h)对应4个偏移量,所以reg=4k coordinates

补充一点,全部anchors拿去训练太多了,训练程序会在合适的anchors中随机选取128个postive anchors+128个negative anchors进行训练(什么是合适的anchors下文5.1有解释)

其实RPN最终就是在原图尺度上,设置了密密麻麻的候选Anchor。然后用cnn去判断哪些Anchor是里面有目标的positive anchor,哪些是没目标的negative anchor。所以,仅仅是个二分类而已!

该1x1卷积的caffe prototxt定义如下:

layer {
  name: "rpn_cls_score"
  type: "Convolution"
  bottom: "rpn/output"
  top: "rpn_cls_score"
  convolution_param {
    num_output: 18   # 2(positive/negative) * 9(anchors)
    kernel_size: 1 pad: 0 stride: 1
  }
}

可以看到其num_output=18,也就是经过该卷积的输出图像为WxHx18大小(注意第二章开头提到的卷积计算方式)。这也就刚好对应了feature maps每一个点都有9个anchors,同时每个anchors又有可能是positive和negative,所有这些信息都保存WxHx(9*2)大小的矩阵。为何这样做?后面接softmax分类获得positive anchors,也就相当于初步提取了检测目标候选区域box(一般认为目标在positive anchors中)。

Faster R-CNN的训练,是在已经训练好的model(如VGG_CNN_M_1024,VGG,ZF)的基础上继续进行训练。实际中训练过程分为6个步骤:

  1. 在已经训练好的model上,训练RPN网络,对应stage1_rpn_train.pt
  2. 利用步骤1中训练好的RPN网络,收集proposals,对应rpn_test.pt
  3. 第一次训练Fast RCNN网络,对应stage1_fast_rcnn_train.pt
  4. 第二训练RPN网络,对应stage2_rpn_train.pt
  5. 再次利用步骤4中训练好的RPN网络,收集proposals,对应rpn_test.pt
  6. 第二次训练Fast RCNN网络,对应stage2_fast_rcnn_train.pt

可以看到训练过程类似于一种“迭代”的过程,不过只循环了2次。至于只循环了2次的原因是应为作者提到:"A similar alternating training can be run for more iterations, but we have observed negligible improvements",即循环更多次没有提升了。接下来本章以上述6个步骤讲解训练过程。

 

五. OverFeat《 OverFeat:Integrated Recognition, Localization and Detection using Convolutional Networks 》

参考学习博客:

https://www.cnblogs.com/liaohuiqiang/p/9348276.html

https://blog.csdn.net/whiteinblue/article/details/43374195

本篇博文主要讲解来自2014年ICLR的经典图片分类、定位物体检测overfeat算法:《OverFeat: Integrated Recognition, Localization and Detection using Convolutional Networks》,至今为止这篇paper,已然被引用了几百次,把图片分类、定位、检测一起搞,可见算法牛逼之处非同一般啊。
 

OverFeat就是一种特征提取算子,就相当于SIFT,HOG等这些算子一样。这篇文献充分利用了卷积神经网络的特征提取功能,它把分类过程中,提取到的特征,同时又用于定位检测等各种任务,只需要改变网络的最后几层,就可以实现不同的任务,而不需要从头开始训练整个网络的参数。

本文的核心操作(FCN + offset max-pooling)

网络最后的输出是一张2*2大小的图片。这个时候,我们就可以发现采用FCN网络,可以输入任意大小的图片。同时需要注意的是网络最后输出的图片大小不在是一个1*1大小的图片,而是一个与输入图片大小息息相关的一张图片了。

                                    
         以往的CNN中,一般我们只用了△=0,得到池化结果后,就送入了下一层。于是文献的方法是,把上面的△=0、△=1、△=2的三种组合方式的池化结果,分别送入网络的下一层。这样的话,我们网络在最后输出的时候,就会出现3种预测结果了。

         如果是2维图片的话,那么(△x,△y)就会有9种取值情况(3*3);如果我们在做图片分类的时候,在网络的某一个池化层加入了这种offset 池化方法,然后把这9种池化结果,分别送入后面的网络层,最后我们的图片分类输出结果就可以得到9个预测结果(每个类别都可以得到9种概率值,然后我们对每个类别的9种概率,取其最大值,做为此类别的预测概率值)。优中选优,避免因为池化而漏掉某些信息,尤其是边缘的信息。

Alexnet在测试阶段的时候,采用了对输入图片的四个角落和中心位置进行裁剪,得到10个大小为网路哟输入大小的图片,分别进行预测,分别得到结果,选出最好结果(平均或最大池化),这最后的结果就是类似对应于上面2*2的预测图选一个最优值。这个2*2的每个像素点,就类似于对应于一个角落裁剪下来的图片预测分类结果。只不过Alexnet把这4个像素点,相加在一起,求取平均值,作为该类别的概率值。

overfeat这篇文献的图片分类算法,在训练阶段采用与Alexnet相同的训练方式,然而在测试阶段可是差别很大,overfeat就是把采用FCN的思想把全连接层看成了卷积层,让我们在网络测试阶段可以输入任意大小的图片。这就是文献最大的创新点(overfeat的方法不是裁剪出10张224*224的图片进行结果预测平均,具体方法请看下面继续详细讲解)。

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,得到最后的结果。

 用于定位任务的时候,就把分类层(上面的layer 6~output)给重新设计,把分类改成回归问题,然后在各种不同尺度上训练预测物体的bounding box。把用分类学习的特征提取层的参数固定下来,然后继续训练后面的回归层的参数,网络包含了4个输出,对应于bounding box的上左上角点和右下角点,然后损失函数采用欧式距离L2损失函数。

 

六. MobileNet V1

学习参考博客:https://blog.csdn.net/qq_31531635/article/details/80508306

这篇论文是谷歌在2017年提出了,专注于移动端或者嵌入式设备中的轻量级CNN网络。该论文最大的创新点是,提出了深度可分离卷积(depthwise separable convolution)。

首先,我们分析一下传统卷积的运算过程,请参考第一个动图或者这篇博客。可以看出,传统卷积分成两步,每个卷积核与每张特征图进行按位相成然后进行相加,此时,计算量为DF∗DF∗DK∗DK∗M∗N,其中DFDF为特征图尺寸,DK为卷积核尺寸,M为输入通道数,N为输出通道数。

然后,重点介绍一下深度可分离卷积。深度可分离卷积将传统卷积的两步进行分离开来,分别是depthwise和pointwise。从下面的图可以看出,首先按照通道进行计算按位相乘的计算,此时通道数不改变;然后依然得到将第一步的结果,使用1*1的卷积核进行传统的卷积运算,此时通道数可以进行改变。使用了深度可分离卷积,其计算量为DK∗DK∗M∗DF∗DF+1∗1∗M∗N∗DF∗DF。

通过深度可分离卷积,计算量将会下降1N+1D2K1N+1DK2,当DK=3DK=3时,深度可分离卷积比传统卷积少8到9倍的计算量。

这种深度可分离卷积虽然很好的减少计算量,但同时也会损失一定的准确率。从下图可以看到,使用传统卷积的准确率比深度可分离卷积的准确率高约1%,但计算量却增大了9倍。

最后给出v1的整个模型结构,该网络有28层。可以看出,该网络基本去除了pool层,使用stride来进行降采样(难道是因为pool层的速度慢?)。

 

  • depthwise后接BN层和RELU6,pointwise后也接BN层和RELU6,如下图所示(图中应该是RELU6)。左图是传统卷积,右图是深度可分离卷积。更多的ReLU6,增加了模型的非线性变化,增强了模型的泛化能力。

  • v1中使用了RELU6作为激活函数,这个激活函数在float16/int8的嵌入式设备中效果很好,能较好地保持网络的鲁棒性。

  • v1还给出了2个超参,宽度乘子αα和分辨率乘子ββ,通过这两个超参,可以进一步缩减模型,文章中也给出了具体的试验结果。此时,我们反过来看,扩大宽度和分辨率,都能提高网络的准确率,但如果单一提升一个的话,准确率很快就会达到饱和,这就是2019年谷歌提出efficientnet的原因之一,动态提高深度、宽度、分辨率来提高网络的准确率。

mobilenet v2发表与2018年,时隔一年,谷歌的又一力作。V2在V1的基础上,引入了Inverted Residuals和Linear Bottlenecks。

为什么要引入这两个模块呢?参考这篇文章,有人发现,在使用V1的时候,发现depthwise部分的卷积核容易费掉,即卷积核大部分为零。作者认为这是ReLU引起的。文章的一个章节来介绍这个理论,但小弟水平有限,还理解不了。

简单来说,就是当低维信息映射到高维,经过ReLU后再映射回低维时,若映射到的维度相对较高,则信息变换回去的损失较小;若映射到的维度相对较低,则信息变换回去后损失很大,如下图所示。因此,认为对低维度做ReLU运算,很容易造成信息的丢失。而在高维度进行ReLU运算的话,信息的丢失则会很少。另外一种解释是,高维信息变换回低维信息时,相当于做了一次特征压缩,会损失一部分信息,而再进过relu后,损失的部分就更加大了。作者为了这个问题,就将ReLU替换成线性激活函数。

Inverted Residuals

这个可以翻译成“倒残差模块”。什么意思呢?我们来对比一下残差模块和倒残差模块的区别。

  • 残差模块:输入首先经过1*1的卷积进行压缩,然后使用3*3的卷积进行特征提取,最后在用1*1的卷积把通道数变换回去。整个过程是“压缩-卷积-扩张”。这样做的目的是减少3*3模块的计算量,提高残差模块的计算效率。
  • 倒残差模块:输入首先经过1*1的卷积进行通道扩张,然后使用3*3的depthwise卷积,最后使用1*1的pointwise卷积将通道数压缩回去。整个过程是“扩张-卷积-压缩”。为什么这么做呢?因为depthwise卷积不能改变通道数,因此特征提取受限于输入的通道数,所以将通道数先提升上去。文中的扩展因子为6。

Linear Bottleneck

这个模块是为了解决一开始提出的那个低维-高维-低维的问题,即将最后一层的ReLU替换成线性激活函数,而其他层的激活函数依然是ReLU6。

 

发表于2019年,该v3版本结合了v1的深度可分离卷积、v2的Inverted Residuals和Linear Bottleneck、SE模块,利用NAS(神经结构搜索)来搜索网络的配置和参数。这种方式已经远远超过了人工调参了,太恐怖了。

v3在v2的版本上有以下的改进:

  • 作者发现,计算资源耗费最多的层是网络的输入和输出层,因此作者对这两部分进行了改进。如下图所示,上面是v2的最后输出几层,下面是v3的最后输出的几层。可以看出,v3版本将平均池化层提前了。在使用1×11×1卷积进行扩张后,就紧接池化层-激活函数,最后使用1×11×1的卷积进行输出。通过这一改变,能减少10ms的延迟,提高了15%的运算速度,且几乎没有任何精度损失。其次,对于v2的输入层,通过3×33×3卷积将输入扩张成32维。作者发现使用ReLU或者switch激活函数,能将通道数缩减到16维,且准确率保持不变。这又能节省3ms的延时。

 

七. vgg16

参考博客:

https://www.cnblogs.com/lfri/p/10493408.html

https://blog.csdn.net/how0723/article/details/83059277

VGG中根据卷积核大小卷积层数目的不同,可分为AA-LRN,B,C,D,E共6个配置(ConvNet Configuration),其中以D,E两种配置较为常用,分别称为VGG16VGG19

下图给出了VGG的六种结构配置:

上图中,每一列对应一种结构配置。例如,图中绿色部分即指明了VGG16所采用的结构。

我们针对VGG16进行具体分析发现,VGG16共包含:

  • 13个卷积层(Convolutional Layer),分别用conv3-XXX表示
  • 3个全连接层(Fully connected Layer),分别用FC-XXXX表示
  • 5个池化层(Pool layer),分别用maxpool表示

其中,卷积层和全连接层具有权重系数,因此也被称为权重层,总数目为13+3=16,这即是

VGG16中16的来源。(池化层不涉及权重,因此不属于权重层,不被计数)。

 

我们注意图1右侧,VGG16的卷积层和池化层可以划分为不同的块(Block),从前到后依次编号为Block1~block5。每一个块内包含若干卷积层一个池化层。例如:Block4包含:

  • 3个卷积层,conv3-512
  • 1个池化层,maxpool

并且同一块内,卷积层的通道(channel)数是相同的,例如:

  • block2中包含2个卷积层,每个卷积层用conv3-128表示,即卷积核为:3x3x3,通道数都是128
  • block3中包含3个卷积层,每个卷积层用conv3-256表示,即卷积核为:3x3x3,通道数都是256

下面给出按照块划分的VGG16的结构图,可以结合图2进行理解:

 

VGG的输入图像是 224x224x3 的图像张量(tensor),随着层数的增加,后一个块内的张量相比于前一个块内的张量:

  • 通道数翻倍,由64依次增加到128,再到256,直至512保持不变,不再翻倍
  • 高和宽变减半,由 224→112→56→28→14→7

 

八. LeNet

参考学习博客:

https://blog.csdn.net/qq_42570457/article/details/81460807

https://www.cnblogs.com/skyfsm/p/8451834.html

LeNet是最早的卷积神经网络之一[1]。1998年,Yan LeCun第一次将LeNet卷积神经网络应用到图像分类上,在手写数字识别任务中取得了巨大成功。LeNet通过连续使用卷积和池化层的组合提取图像特征,其架构如 图1所示,这里展示的是作者论文中的LeNet-5模型:

图1:LeNet模型网络结构示意图

第一轮卷积和池化:卷积提取图像中包含的特征模式(激活函数使用sigmoid),图像尺寸从32减小到28。经过池化层可以降低输出特征图对空间位置的敏感性,图像尺寸减到14。第二轮卷积和池化:卷积操作使图像尺寸减小到10,经过池化后变成5。第三轮卷积:将经过第3次卷积提取到的特征图输入到全连接层。第一个全连接层的输出神经元的个数是64,第二个全连接层的输出神经元个数是分类标签的类别数,对于手写数字识别其大小是10。然后使用Softmax激活函数即可计算出每个类别的预测概率。

è¿éåå¾çæè¿°

九. Alexnet

学习参考博客:

https://blog.csdn.net/luoluonuoyasuolong/article/details/81750190

https://www.cnblogs.com/wangguchangqing/p/10333370.html

AlexNet与LeNet相比,具有更深的网络结构,包含5层卷积和3层全连接,同时使用了如下三种方法改进模型的训练过程:

数据增多:深度学习中常用的一种处理方式,通过对训练随机加一些变化,比如平移、缩放、裁剪、旋转、翻转或者增减亮度等,产生一系列跟原始图片相似但又不完全相同的样本,从而扩大训练数据集。通过这种方式,可以随机改变训练样本,避免模型过度依赖于某些属性,能从一定程度上抑制过拟合。使用Dropout抑制过拟合使用ReLU激活函数少梯度消失现象

第一层:卷积层1,输入为 224×224×3 224 \times 224 \times 3224×224×3的图像,卷积核的数量为96,论文中两片GPU分别计算48个核; 卷积核的大小为 11×11×3 11 \times 11 \times 311×11×3; stride = 4, stride表示的是步长, pad = 0, 表示不扩充边缘;
卷积后的图形大小是怎样的呢?
wide = (224 + 2 * padding - kernel_size) / stride + 1 = 54
height = (224 + 2 * padding - kernel_size) / stride + 1 = 54
dimention = 96
然后进行 (Local Response Normalized), 后面跟着池化pool_size = (3, 3), stride = 2, pad = 0 最终获得第一层卷积的feature map
最终第一层卷积的输出为

第二层:卷积层2, 输入为上一层卷积的feature map, 卷积的个数为256个,论文中的两个GPU分别有128个卷积核。卷积核的大小为:5×5×48 5 \times 5 \times 485×5×48; pad = 2, stride = 1; 然后做 LRN, 最后 max_pooling, pool_size = (3, 3), stride = 2;

第三层:卷积3, 输入为第二层的输出,卷积核个数为384, kernel_size = (3×3×256 3 \times 3 \times 2563×3×256), padding = 1, 第三层没有做LRN和Pool

第四层:卷积4, 输入为第三层的输出,卷积核个数为384, kernel_size = (3×3 3 \times 33×3), padding = 1, 和第三层一样,没有LRN和Pool

第五层:卷积5, 输入为第四层的输出,卷积核个数为256, kernel_size = (3×3 3 \times 33×3), padding = 1。然后直接进行max_pooling, pool_size = (3, 3), stride = 2;

第6,7,8层是全连接层,每一层的神经元的个数为4096,最终输出softmax为1000,因为上面介绍过,ImageNet这个比赛的分类个数为1000。全连接层中使用了RELU和Dropout。
 

十. GoogLeNet

学习参考博客:

https://my.oschina.net/u/876354/blog/1637819

GoogLeNet是谷歌(Google)研究出来的深度网络结构,为什么不叫“GoogleNet”,而叫“GoogLeNet”,据说是为了向“LeNet”致敬,因此取名为“GoogLeNet”

一般来说,提升网络性能最直接的办法就是增加网络深度和宽度,深度指网络层次数量、宽度指神经元数量。但这种方式存在以下问题:
(1)参数太多,如果训练数据集有限,很容易产生过拟合;
(2)网络越大、参数越多,计算复杂度越大,难以应用;
(3)网络越深,容易出现梯度弥散问题(梯度越往后穿越容易消失),难以优化模型。
所以,有人调侃“深度学习”其实是“深度调参”。
解决这些问题的方法当然就是在增加网络深度和宽度的同时减少参数,为了减少参数,自然就想到将全连接变成稀疏连接。但是在实现上,全连接变成稀疏连接后实际计算量并不会有质的提升,因为大部分硬件是针对密集矩阵计算优化的,稀疏矩阵虽然数据量少,但是计算所消耗的时间却很难减少。

那么,有没有一种方法既能保持网络结构的稀疏性,又能利用密集矩阵的高计算性能。大量的文献表明可以将稀疏矩阵聚类为较为密集的子矩阵来提高计算性能,就如人类的大脑是可以看做是神经元的重复堆积,因此,GoogLeNet团队提出了Inception网络结构,就是构造一种“基础神经元”结构,来搭建一个稀疏性、高计算性能的网络结构。

 

 

该结构将CNN中常用的卷积(1x1,3x3,5x5)、池化操作(3x3)堆叠在一起(卷积、池化后的尺寸相同,将通道相加),一方面增加了网络的宽度,另一方面也增加了网络对尺度的适应性。
网络卷积层中的网络能够提取输入的每一个细节信息,同时5x5的滤波器也能够覆盖大部分接受层的的输入。还可以进行一个池化操作,以减少空间大小,降低过度拟合。在这些层之上,在每一个卷积层后都要做一个ReLU操作,以增加网络的非线性特征。
然而这个Inception原始版本,所有的卷积核都在上一层的所有输出上来做,而那个5x5的卷积核所需的计算量就太大了,造成了特征图的厚度很大,为了避免这种情况,在3x3前、5x5前、max pooling后分别加上了1x1的卷积核,以起到了降低特征图厚度的作用,这也就形成了Inception v1的网络结构,如下图所示:

1x1的卷积核有什么用呢?
1x1卷积的主要目的是为了减少维度,还用于修正线性激活(ReLU)。比如,上一层的输出为100x100x128,经过具有256个通道的5x5卷积层之后(stride=1,pad=2),输出数据为100x100x256,其中,卷积层的参数为128x5x5x256= 819200。而假如上一层输出先经过具有32个通道的1x1卷积层,再经过具有256个输出的5x5卷积层,那么输出数据仍为为100x100x256,但卷积参数量已经减少为128x1x1x32 + 32x5x5x256= 204800,大约减少了4倍。

GoogLeNet网络结构明细表解析如下:
0、输入
原始输入图像为224x224x3,且都进行了零均值化的预处理操作(图像每个像素减去均值)。
1、第一层(卷积层)
使用7x7的卷积核(滑动步长2,padding为3),64通道,输出为112x112x64,卷积后进行ReLU操作
经过3x3的max pooling(步长为2),输出为((112 - 3+1)/2)+1=56,即56x56x64,再进行ReLU操作
2、第二层(卷积层)
使用3x3的卷积核(滑动步长为1,padding为1),192通道,输出为56x56x192,卷积后进行ReLU操作
经过3x3的max pooling(步长为2),输出为((56 - 3+1)/2)+1=28,即28x28x192,再进行ReLU操作
3a、第三层(Inception 3a层)
分为四个分支,采用不同尺度的卷积核来进行处理
(1)64个1x1的卷积核,然后RuLU,输出28x28x64
(2)96个1x1的卷积核,作为3x3卷积核之前的降维,变成28x28x96,然后进行ReLU计算,再进行128个3x3的卷积(padding为1),输出28x28x128
(3)16个1x1的卷积核,作为5x5卷积核之前的降维,变成28x28x16,进行ReLU计算后,再进行32个5x5的卷积(padding为2),输出28x28x32
(4)pool层,使用3x3的核(padding为1),输出28x28x192,然后进行32个1x1的卷积,输出28x28x32。
将四个结果进行连接,对这四部分输出结果的第三维并联,即64+128+32+32=256,最终输出28x28x256
3b、第三层(Inception 3b层)
(1)128个1x1的卷积核,然后RuLU,输出28x28x128
(2)128个1x1的卷积核,作为3x3卷积核之前的降维,变成28x28x128,进行ReLU,再进行192个3x3的卷积(padding为1),输出28x28x192
(3)32个1x1的卷积核,作为5x5卷积核之前的降维,变成28x28x32,进行ReLU计算后,再进行96个5x5的卷积(padding为2),输出28x28x96
(4)pool层,使用3x3的核(padding为1),输出28x28x256,然后进行64个1x1的卷积,输出28x28x64。
将四个结果进行连接,对这四部分输出结果的第三维并联,即128+192+96+64=480,最终输出输出为28x28x480

第四层(4a,4b,4c,4d,4e)、第五层(5a,5b)……,与3a、3b类似,在此就不再重复。

GoogLeNet凭借其优秀的表现,得到了很多研究人员的学习和使用,因此GoogLeNet团队又对其进行了进一步地发掘改进,产生了升级版本的GoogLeNet。
GoogLeNet设计的初衷就是要又准又快,而如果只是单纯的堆叠网络虽然可以提高准确率,但是会导致计算效率有明显的下降,所以如何在不增加过多计算量的同时提高网络的表达能力就成为了一个问题。
Inception V2版本的解决方案就是修改Inception的内部计算逻辑,提出了比较特殊的“卷积”计算结构。

降低特征图大小
一般情况下,如果想让图像缩小,可以有如下两种方式:
 
先池化再作Inception卷积,或者先作Inception卷积再作池化。但是方法一(左图)先作pooling(池化)会导致特征表示遇到瓶颈(特征缺失),方法二(右图)是正常的缩小,但计算量很大。为了同时保持特征表示且降低计算量,将网络结构改为下图,使用两个并行化的模块来降低计算量(卷积、池化并行执行,再进行合并)

Inception V3一个最重要的改进是分解(Factorization),将7x7分解成两个一维的卷积(1x7,7x1),3x3也是一样(1x3,3x1),这样的好处,既可以加速计算,又可以将1个卷积拆成2个卷积,使得网络深度进一步增加,增加了网络的非线性(每增加一层都要进行ReLU)。
另外,网络输入从224x224变为了299x299。

Inception V4研究了Inception模块与残差连接的结合。ResNet结构大大地加深了网络深度,还极大地提升了训练速度,同时性能也有提升(ResNet的技术原理介绍见本博客之前的文章:大话深度残差网络ResNet)。
Inception V4主要利用残差连接(Residual Connection)来改进V3结构,得到Inception-ResNet-v1,Inception-ResNet-v2,Inception-v4网络。
ResNet的残差结构如下:
 
将该结构与Inception相结合,变成下图:
 
通过20个类似的模块组合,Inception-ResNet构建如下:

 

Guess you like

Origin blog.csdn.net/jiugeshao/article/details/106520875