Course 4-Convolutional Neural Networks--Week 2

来源:互联网 发布:什么是淘宝直通车? 编辑:程序博客网 时间:2024/06/07 14:55

本周将会展示几个有效的ConvNet案例,如LeNet-5、Alex Net、VGG16、ResNet、Inception,以及这些网络所涉及的一些技巧,如short cut(skip connection)、1*1卷积。最后介绍了如何使用这些网络,比如,直接在github上找不同框架下实现的网络,还可以在别人pre-training的基础上fine tune网络,fine tune的参数多少取决于拥有数据的多少。

2.1 Why look at case studies?

为什么要学习这些案例呢?上周我们学习了组成ConvNet的几个基本模块,如卷积层、池化层、全连接层。近几年大量计算机视觉方面的研究都是有关于如何将这几个模块组合在一起形成有效的ConvNets的。我们获得intuition的最好方法之一就是学习这些有效的ConvNets。就像学习写代码就从大量阅读别人的代码开始一样,我们可以通过学习别人有效的ConvNets来获得如何构建ConvNets的intuition。在一个计算机视觉任务中工作的好的神经网络,在其他计算机视觉任务中也工作的比较好。
接下来将会展示几个经典的网络,如下图所示。LeNet-5是上世纪80年代提出来的。AlexNet和VGG是非常有效的神经网络,它们中的一些ideas已经形成了现代计算机视觉的基石。这些ideas很可能在你自己的网络中也很有用。然后,将会展示ResNet或者称之为Residual Network,你可能听说过,神经网络已经变得越来越深了,ResNet是一个拥有152层的神经网络,并具有一些有趣的tricks关于如何有效的实现。最后,还会进行inception神经网络的案例学习。在学习完这些神经网络后,我们就会有关于构建ConvNet更好的intuition。即使最后我们不从事计算机视觉领域,通过这些案例获得的ideas也可以对自己的神经网络工作有帮助。
这里写图片描述

2.2 Classic networks

本小节中,我们将学习一些经典的神经网络结构,从LeNet-5开始,然后是AlexNet,再下来是VGG Net。
首先是LeNet-5的结构。如下图所示。输入是一幅32*32*1的图像,LeNet-5的目标是能识别手写数字。LeNet-5是在灰度图像上进行训练的,这就是为什么输入是一个单通道的图像。第一步,我们使用6个5*5的filters,进行stride为1、no padding的卷积,这一步的输出size为28*28*6。然后进行average pooling,在写这篇文章时,人们使用average pooling比较多,若是现在再实现时,我们应该使用max pooling,这一步的输出size为14*14*6。后面的连接以此类推。这样的网络,随着网络的加深,nHnW会逐渐减小,而nC会逐渐变大。另外一个特点是,一个或多个卷积层后接一个池化层,再一个或多个卷积层后接一个池化层,然后接几个全连接层,最后是输出层。这种层次的排列类型是非常常见的。
这里写图片描述
第二个神经网络的例子是AlexNet。如下图所示。输入是一幅227*227*3的图像,首先使用96个11*11的filters,进行stride为4、no padding的卷积,这一步的输出size为55*55*96。然后进行 f =3、s = 2 的max pooling,这一步的输出size为27*27*96。接下来使用256个5*5的filters,进行等长卷积(padding type is ‘same’),这一步的输出size为27*27*256。接着再进行 f = 3、s = 2的max pooling,得到13*13*256大小的输出。再后面的卷积、池化、全连接操作以此类推,不再详述。
AlexNet(about 60 million parameters)和LeNet-5(about 60k parameters)有很多的相似之处,但它更大。同时,它使用了relu激活函数,这也使得它的性能优于LeNet-5。
这里写图片描述
最后,介绍第三个神经网络,称为VGG或VGG-16网络。如下图所示。有关VGG-16一个标志性的事情是,与其使用大量参数,不如使用一个简化的网络,在这个网络中的卷积层超参数均为大小为3*3的filter,stride = 1,padding =SAME,同时,所有的池化层超参数均为大小为2*2,stride = 2。因此,VGG做了一件很好的事情就是简化网络。并且在每次卷积时,都将#channels double,这是另外一个简化网络的方法。该网络主要的缺点就是,网络很大,有很多参数要训练(约138 million)。VGG-16还有一点吸引人的地方就是,通过池化操作每次将height和width减半,又通过卷积操作将#channels翻倍
这里写图片描述

2.3 Residual Networks

非常非常深的神经网络通常很难训练,因为存在梯度消失和梯度爆炸的问题。本小节将会介绍skip connections,它允许将激活输出从一层到另外一个更深的层。通过使用skip connections,我们将会构建ResNets,它使我们能够训练非常深(more than 100 layers)的网络。
下面介绍ResNets。ResNets是由称为residual block的部分组成的,我们先来介绍residual block。如下图所示。图中给出了神经网络的两层。对于输入a[l],我们通过下式得到z[l+1],然后再经过一个relu非线性单元,得到a[l+l]。同样的处理方法,我们可以得到z[l+2]a[l+2]。换句话说,信息从a[l]流向a[l+2],需要经过上述这些步骤,我们将其称为这些层次的主路径(main path)。在residual net中,我们将做一些改变。我们再多加一条路径,将a[l]z[l+2]一起作为l+2层激活函数的输入。如图中紫色线所示,并将其称为short cut。这样,a[l]除了经过main path外,还要经过short cut,于是,a[l+2]=g(z[l+1]+a[l]),附加的这部分a[l]就形成了residual block。对于上面的神经网络的两层,我们就要加一条路径,如蓝色的线所示,必须加在方框上,因为方框包含了两步操作,线性变换和非线性变化,而a[l]添加在线性变换之后和非线性变换之前。有时,除了称之为“short cut”还可以称其为“skip connection”,它指出a[l]跳过了一层或两层,进而将信息传递给网络中更深的层。
这里写图片描述
现在,我们来看看ResNets。如下图所示。原始的黑色网络称为“plain networks”,加上蓝色线画出的“short cut”后,就形成了ResNets。正如上张图片所介绍的,图中蓝色笔画出的每两层就是一个residual block,多个residual block堆叠在一起就形成了residual network。下图中的residual network是由5个residual block堆叠起来的。
如果使用标准优化算法(梯度下降、momentum、Adam等等)来训练plain network,经验发现,当神经网络的层数加深时,训练误差会先下降在上升,如图中蓝色线所示,理论上它应该像绿色线所示,越来越小的。理论上,层数越多应该越有用,但现实却是,当网络太深的时候,效果反而不好。但是,对于ResNets,尽管网络越来越深,我们还是使得误差不断下降,即便训练一个层数超过100的神经网络。这对于解决梯度消失和梯度爆炸问题很有帮助,同时也允许我们构建更深的神经网络。
这里写图片描述

2.4 Why ResNets work?

为什么ResNets可以工作的这么好呢?我们来通过一个例子进行说明,并了解如何在不太影响网络性能的情况下或至少在训练误差不不增大的情况下,使其越来越深。由于在训练集上表现好,是在training-dev、开发集、测试集上表现好的前提,因此,在训练集上表现好,是网络性能好的第一步。
上一小节,我们知道,当神经网络越来越深的时候,网络的训练误差会有所增大,这就是为什么有时我们并不希望网络太深。但当我们训练ResNets时,情况就不是这样了。如下图所示。我们将输入X喂入一个很大的神经网络,输入为a[l]。随后,我们又修改了这个网络,在后面增加了两层,使其更深,输出变为a[l+2],我们将其变为residual block。这个网络的所有激活函数都使用relu,即所有的激活输出都大于等于0,于是a[l+2]就可由图片中的表达式计算出来。注意一下,如果我们使用L2正则化,绿色箭头所指的权重W[l+2]将会shrink,如果对b使用权重衰减,它的值同样会shrink。如果W[l+2]=0b=0,那么表达式中的前一项就没有了,于是a[l+2]=g(a[l])=a[l](激活函数为relu)。这表明,identity function is easy for residual block to learn,residual block容易学到恒等函数。这意味着,增加神经网络的residual block并不会对网络的能力造成伤害,网络至少能做的和添加residual block之前一样好。这就是为什么在网络的任何地方添加residual block都不会对性能有所损伤。但我们的目的并不是只对网络没有伤害,而是希望网络可以做的更好。大多数时候,residual block都会帮助我们获得更好的结果。
另一个有关于 residual network的细节是:因为a[l+2]=g(z[l+2]+a[l]),所以z[l+2]a[l]具有相同的shape,因此,我们在ResNets中见到的大多数情况都是使用有padding的“SAME”类型的卷积。为了防止输入和输出的shape不同,我们要做的就是在a[l]前乘一个系数矩阵Ws,如下图中红笔所写的。假设a[l]的长度为128,a[l+2]的长度为256,那么Ws的shape就是256*128。
这里写图片描述
最后,我们看下ResNets在图像上的应用。如图所示,和大多数网络一样,我们有若干卷积层,然后跟一个池化层,当遇到池化层后,我们就要对shape对一个调整,使用前面提到的系数矩阵Ws。接下来又是若干卷积层和一个池化层形成的pattern,重复几次后,最后输出接一个全连接+softmax。
这里写图片描述

2.5 Network in Network and 1*1 convolutions

为了设计复杂的结构,一个非常有用的想法就是使用1*1的卷积。你可能好奇,1*1的卷积是用来做什么的?如下图所示,有一个1*1的filter,值为2,对图中的每个像素做卷积就像对每个元素乘以2。因此,用1*1的filter做卷积看起来并不是那么有用,我们只是乘以了某个数。但是,这是在输入为6*6*1时的情况。如果我们有6*6*32的输入,而不是1通道的输入,这时候,一个1*1*32的filter所做的工作就有意义多了。特别的,1*1的filter所做的工作就是查看这36个位置中的每一个,并将对应位置上的数值相乘再相加,最后经过relu激活函数。1*1的卷积有时候也称为network in network。
这里写图片描述
下面给出1*1的卷积的用武之地。如下图所示。如果我们想shrink height和width,我们可以使用pooling。但如果#channels太大,我们该怎么办呢?以图中为例,这时候我们使用32个1*1*192的filters就可以使#channels从192 shrink 到32
这里写图片描述
接下来在inception网络中,我们将会看到1*1卷积层的身影。

2.6 Inception network motivation

在ConvNet中设计layer时,我们可能要挑选the size of filters,以及是否需要池化层。inception network的思想就是全做,这使网络更复杂但也更有效。
以下图为例,输入的大小是28*28*192,inception network的想法就是,与其选择filter size,以及是否需要卷积层或池化层,不如将这些全都做了。如图中所示,为了保持shape的一致,我们使用padding,并将各种结果堆叠起来。这样一个从28*28*192的volume到28*28*256的volume的部分称为inception module。其思想就是与其思考选择参数,不如将这些参数都尝试一遍,并把它们的结果堆叠起来。这样的思想背后就是计算代价问题。
这里写图片描述
现在,我们只关注上图中5*5的卷积操作,如下图所示。对于输出的每个像素,我们要做5*5*192次乘法,而输出总共有28*28*32个像素,因此,总共要做约120 million 次的乘法!马上,我们就会看到如何用1*1的卷积来减少计算代价,越能降低到十分之一。
这里写图片描述
下面是上图中从28*28*192的volume到28*28*256的volume的另外一种构造。首先用16个1*1*192的filters进行卷积,得到28*28*16的volume,再用32个5*5*16的filters进行卷积,得到和上图一样的输出28*28*32。我们所做的就是使用我们有的左边的这样一个大的volume,将其shrink为一个小的多的28*28*16的中间volume,有时候这叫做bottleneck layer(因为它是网络中最小的一步部分)。我们在增加size之前先收缩了表示。现在我们来考虑下计算代价的问题,如图所示,第一层约需要2.4 million 次乘法,第二层约需要10 million 次乘法,总共约需要12.4 million 次乘法,相比于上图中的120 million,下降到约十分之一。其中涉及到的加法运算和乘法运算差不多,因此,这里只计算了乘法运算的次数。
这里写图片描述
最后,总结一下,如果在构建神经网络的一层时,我们不知道如何觉得filter的size,以及不确定是否要卷积层和池化层的时候,inception 模块就全部都做,并将结果拼接起来。我们可能会有疑问,只是简单的收缩表示会对我们的神经网络表现有影响吗?事实表明,实现bottleneck layer 能显著收缩表示,但并不会对性能有损伤,同时还能省下很多计算量。因此,这就是inception网络的主要思想。下一节将展示出完整的inception网络长什么样子。

2.7 Inception network

上一节已经学习了inception网络的所有基本模块,本小节将介绍如何将这些blocks放在一起,形成我们自己的inception network。
如下图所示,inception module以前一层的激活函数输出作为输入,shape如图中所示。再分别使用size为1、3、5的conv和maxpooling后,不需要再使用池化层,而是直接将这些结果拼接起来,得到一个28*28*256的输出。这是一种inception module。inception network 所做的就是,或多或少的将这些inception module组装在一起。
这里写图片描述
如下图所示,是inception network的网络图。这里面有很多重复的blocks。可能这个网络图看起来很复杂,但如果仔细看其中的一个block,就会发现它与上图中的basical inception module是一样一样的。
inception网络的还有一个细节就是,它有sign branches,如下图所示。sign branches所做的就是获取一些hidden layer的输出,并尝试利用这些hidden layer的输出做一些prediction,有正则化的作用,可以防止过拟合?
这里写图片描述
只要理解了inception module,就不难理解inception network,因为inception network是很多inception module的组装。

2.8 Using open-sourse inplementations

至此,已经学习了一些有效的神经网络和卷积网络结构。接下来将分享一些如何使用它们的实践建议。首先来看下,如何使用开源实现。很多神经网路都是很难复制的,因为涉及很多调节超参数的细节,这些会使性能有差异。因此,只通过阅读文章来实现神经网络是有难度的。幸运的是,很多深度学习的研究者都会将他们的工作开源。当我们在工作时,我们应该首先在网上找找开源实现,并在此基础上做一些修改,会使我们的工作进度更快。

2.9 Transfer learning

对于同类问题,如图像分类,我们先去网上下载开源的神经网络实现代码,并且不光要下载代码,还要下载参数weights。
如下图最上面的网络所示,当我们的数据集很小的时候,对于我们自己的分类问题,我们先移走开源实现原本的softmax层,然后创建我们自己的softmax层。Ng建议我们将最后一层之外的其它层参数都当成固定值,只训练最后一层的参数。通过使用别人预训练的权重,我们会得到一个不错的结果,即便数据集比较小。幸运的是,很多深度学习框架都支持这种操作,在类似TrainableParameter的参数设置False或者在其他框架中将freeze设置为True,可以设置一些层的参数不再被训练。
另外一个trick就是,由于之前层都是固定的,那么对一个样本,多次计算的结果也是一样的,我们只要将所有样本在这些固定层的结果计算出来,并存储在硬盘上,这样在训练的时候,我们就只需要对一个较浅的网络进行训练,从而提高我们的效率。以上是我们的数据集很小的时候,我们要做的事情。
如果我们有一个更大的数据集,该怎么办呢?如下图中间的网络所示。一条经验法则就是,如果我们有一个较大的标记数据集,那我们就freeze较少的layers,然后训练剩下的layers。有很多方法可以这样做,比如,直接在后面几层现有的权重上进行训练,或者不要后面几层,自己重新设置。
其中一个模式就是,当我们拥有的数据量越大,我们需要freeze的层数就越小,需要从顶开始训练的layers就越多。
如果我们拥有很多数据,如下图第三个网络所示,我们可以在现有框架和权重的基础上,对整个网络进行训练。
这里写图片描述

2.10 Data augmentation

大多数计算机视觉任务可以使用更多数据。常见的方法如下图所示。
这里写图片描述

这里写图片描述

这里写图片描述
数据扩增也会有超参数。

2.11 The state of computer vision

本节将会分享一些深度学习在计算机视觉领域方面的观点。
这里写图片描述

这里写图片描述

这里写图片描述

原创粉丝点击