程序员

深度学习案例研究

2019-03-06  本文已影响8人  带刺的小花_ea97
第一课:为什么要进行案例研究?

上周我们学习了一些基本结构模块,例如卷积层,池化层和全连接层。事实证明,过去几年的计算机视觉研究已经着手于如何将这些基础结构模块组合起来以形成高效的神经网络,让你自己受到启发的最好方法就是去研究案例。

一个更好的方法学会如何构建卷积网络的机制就是去看别人的高效的卷积网络的例子。事实证明,一个神经网络结构如果在一个计算机视觉问题中表现良好,通常也会在其他问题中表现良好。

一些计算机领域的研究论文,我希望你也会觉得它们有用。

总览几个经典的神经网络(有些观点已经成为了现代计算机视觉的基石):

开锤!

第二课:经典神经网络

在这节课,你会学到一些经典的神经网络结构,如LeNet 5,AlexNet和VGGNet,让我们看一下:

LeNet 5在灰度图上进行训练,所以图层通道数目为1。
识别数字7,32 * 32 * 1的原始图像,5 * 5过滤器,步长为1,得到28 * 28 * 6的输出。
然后进行池化,在发表这篇文章时,人们更常用均值池化,虽然现在一般选择最大池化,f = 2,s = 2的滤波器进行均值池化,进行降维,得到14 * 14 * 6的体积结果。
接着进行另一层卷积。16个滤波器尺寸为5 * 5,得到10 * 10 * 16的结果。

这篇文章完成于1998年,那时人们不怎么用填充,或总用有效卷积进行计算,这就是为什么每次使用卷积时,结果的尺寸都会缩小。

接着进行进一步池化,得到5 * 5 * 16的结果。
然后接下来一层是进行全连接层,其本身120个神经元每个都连接这400个节点,因此叫做全连接层。
接着是另一个全连接层,得到84维特征。
最后一步是将这84维特征生成一个最终结果来预测y帽,y帽包括10个预测值。

作为该网络结构的现代版,我们用softmax层来生成10个分类结果,尽管LeNet 5原先是用别的分类器做输出层,而那个分类器现在已经不用了。

这是一个小型的神经网络,大概有60000个参数,而如今你经常可以见到包含千万到亿量级参数的神经网络,这些字面上比LeNet 5大千倍的神经网络。

但是当你深入研究网络,值得注意的一个模式是从左到右,高度和宽度往往会下降,通道数是增加的,另一个神经网络至今仍然使用的模式是你会用一层或多层卷积,随后是池化层,然后再是一层或多层卷积层,然后是池化层,随后是几层全连接层,然后输出,这种层次排列很常见。

最后对于想读这篇文献的人,添加一些脚注:
人们用sigmoid函数和tanh非线性函数而不用ReLu非线性函数,且还有一些有趣的方式,即以现代标准来看这个网络联级的方式很有趣,例如你会发现如果有一个nh * nw * nc的网络结构,然后用f * f * nc维的滤波器,其中每个滤波器都处理了每一维通道,但那时计算机比较慢,所以为了节省计算量和参数数量,原始LeNet 5有种比较疯狂的计算方法,其中不同的滤波器会处理输入块的不同通道,而现在先进的应用则不会用这种复杂的方法。另外一个变化就是LeNet 5在池化后有非典型处理,应该是在池化后使用sigmoid非线性函数,可以重点看这篇文章的二三两章。

第二个经典卷积神经网络算法是AlexNet:
227 * 227 * 3原始图像,用96个11 * 11,步长为4的过滤器,得到55 * 55 * 96的输出,之后用3 * 3步长为2的滤波器进行最大池化,体积降到27 * 27 * 96,然后用5 * 5进行卷积,相同填充,得到27 * 27 * 256,再次最大池化,得到13 * 13 * 256,然后相同的卷积,相同填充,得到13 * 13 * 384然,然后再次3 * 3相同卷积,最后最大池化,得到6 * 6 * 256的输出。

6 * 6 * 256 = 9216。因此我们把它展开为9216个节点,然后有几层全连接层,然后用softmax输出结果,即目标可能是1000类中的哪一类。

这个网络结构实际上很像LeNet,但更大。LeNet 5有60000个参数,AlexNet大概有6千万个参数,而且AlexNet采用非常相似的构造板块,拥有更多的隐藏神经元,在更多的数据上训练,AlexNet在ImageNet数据库上进行训练,大数据库使它有更好的性能。使AlexNet比LeNet更好的一个因素是:

ReLu函数的使用。

脚注:当时GPU还比较慢,因此该文章有在两块GPU上训练的复杂方法,基本思想是网络中很多层被分割到两块不同的GPU上,两块GPU可以互相通讯,而且原始的AlexNet结构还有另一种层,叫做局部响应归一层(LRN),这种层实际上用的很少。但局部响应归一层的基本思想是:当你看一个块体,你看一个位置高和宽,然后看跨越通道的位置,跨越了256个通道然后归一化,这个局部响应操作是针对处理该13 * 13图像的每一个位置但是不想要太多高激活率的神经元。

鉴于AlexNet有很多复杂的结构和超参数,在哪放置这些超参数,是AlexNet算法必须考虑的问题。

第三个VGG/VGG-16算法:

VGG-16非常值得注意的一点是:
与大量超参数不同,VGG-16结构更简单,更能关注卷积层,即3 * 3,s=1,same填充的卷积滤波器,所有最大池化都采用2 * 2,s=2。

VGG-16有一个优点:
真正简化了神经网络结构。

原始图像224 * 224 * 3,卷积池化卷积池化...最后得到7 * 7 * 512的结果输入全连接层,通过两层4096个神经元的全连接层,然后是softmax函数输出1000类结果。

VGG-16中的16表示该网络有16层带权重的层,这是个相当大的网络,该网络总共有1亿3千八百万个参数,即使以现在的标准衡量也是很大了。但VGG-16结构的简洁性非常吸引人,看得出这个结构相当统一,有几组卷积,然后是池化层,以降低高和宽,另一方面,如果你看卷积层的滤波器数量,你有64个滤波器,然后两倍到128到256到512,这种在每步粗略的双倍增加,或在每组卷积层双倍增加的方式,是设计这个网络时用的另一个简单原则。

所以我认为这种相对统一性对研究者来说很有趣,而该结构的主要缺点是:以训练参数的数量来看是个非常大的网络。

VGG-19是比VGG-16更大的版本,但是VGG-19和VGG-16性能差不多,很多人用VGG-16。我最喜欢的是这种高和宽随着网络深入而减少的模式,尺寸每次会因为池化层按因子2减少,与此同时,通道数量增加。每次用一组卷积层时,通道数会按照因子2增加。

这种按照比率减少或增加是非常有条理性的。

以上就是三种经典神经网络结构。

更先进更强大的神经网络?

第三课:ResNets(残差网络)

太深的神经网络训练起来很难,因为有梯度消失和爆炸这类问题。

本节讲述跳跃连接,它能让你从一层中得到激活,并突然把它传递给下一层,甚至更深的神经网络层,利用它,你就可以训练网络层很深很深的残差网络(ResNets),有时能超过100层。

残差网络是使用了残差结构的网络。这里有两层神经网络,a[l]代表第l层中的激活函数,然后到了第a[l+1],两层之后是a[l+2],在这个计算步骤中,你先有一个a[l],之后你做的第一件事就是将这个线性运算应用到它上面,即用a[l]计算z[l+1],通过乘以一个加权矩阵,并加上一个偏置向量,之后你通过非线性ReLu函数来得到a[l+1],然后在下一层,再次应用这个线性步骤,最后再运行ReLu函数,得到a[l+2]。
换言之,从a[l]到a[l+2]的信息,它需要经过这些步骤,我们把这个步骤称为这组层的主路径。

在残差网络中,我们要做一点改变。
我们把a[l],把它往前提,然后复制,提到神经网络非常靠后的位置,最后应用一些非线性处理,比如线性整流函数ReLu,我将这个称为快捷路径。

所以无需遵循主路径,a[l]中的信息现在可以遵循快捷路径进入到更深层的神经网络中,这意味着最后一个等式:

消失了,我们有了:

使这成为了一个残差块。实际上快捷路径是加在ReLu非线性函数之前的,所以在第二个神经网络层中每个节点都应用一个线性方程和ReLu函数。

有时这个术语不叫快捷路径,叫做跳跃连接,是指a[l]跳过一层或者跳过几乎两层把信息传递到更深的神经网络中去。

作者发现使用残差块,让你可以训练更深层的神经网络,而你建立一个ResNets的方法就是通过大量的这些残差块,然后把它们堆叠起来,形成一个深层网络。

看一下plain网络:
要把一个plain网络变成ResNets,你需要做的就是添加所有这些跳跃连接(或称为快捷路径连接),所以每两层结束于额外的改变,将这个10层的神经网络结构变为5个残差块堆积在一起,这就是一个残差网络。

事实证明:
如果你使用标准的优化算法,如梯度下降法或者高级优化算法来训练plain网络,没有额外的快捷路径或者跳跃连接。从经验上来说,随着你层数的增加,训练误差会在下降一段时间后,又回升上去。从理论上说,当你使神经网络更深,它在训练数据上的性能应该会更好,但是在实践中或者现实中,没有ResNets,一个plain网络如果很深意味着你的优化算法训练起来很困难。

所以在现实中,如果你选择的网络太深,则训练误差会更糟糕。但是有了ResNets的情况是,即使层数越来越深,你仍然可以让误差继续下降,即使我们训练超过100层的网络。

使用ResNets确实对解决梯度消失和爆炸问题非常有帮助。这使得我们可以训练深得多的神经元网络而不会看到性能倒退的现象,尽管在某一层可能会达到平原现象,但是ResNets对训练很深的算法确实有帮助。

为什么ResNets有效?

第四课:为什么ResNets有效?

看一个例子:

你可以通过使用ResNets来训练非常深的神经网络,让它们越来越深而又没有真正的损害让它们在训练集上好好工作的能力,在训练集上表现出色通常是你出色地控制你在训练集上的深度的前提条件,所以使用ResNets是对付你训练集的第一步。

对于一个普通的神经网络,我们在后面添加几层,使神经网络的层数更深一点。

通过以上公式推导可以得出:
残差块比较容易学习恒等函数,由于跳跃连接也可以得到a[l+2] = a[l]。这意味着将这两层加入到你的神经网络与上面没有这两层的神经网络相比,并不会影响神经网络的能力,因为对它来说学习恒等函数非常容易,只需要复制a[l]到a[l+2],即便它中间有额外的两层,所以这就是为什么要添加这额外的两层,这个残差块到大型神经网络,中间或者尾部并不会影响神经网络的表现。

当然我们目标并不是维持现有的表现,而是获得更好的表现,你可以想象成我们额外添加的两层,应该学习到有意义的东西,可能要比学习恒等函数更好。

有极多层的神经网络里比较深层的网络在没有残差块跳跃连接的情况下,容易出错的地方是:当你的神经网络越深层,它就很难选择参数来学习,即便是恒等参数也很难,这就是为什么有很多层数却会使你的结果更糟而不是更好。

我认为残差块网络有效的主要原因是:
这些额外层学习恒等函数非常简单,你几乎总能保证它不会影响总体的表现,甚至有些时候幸运的话,可以提升网络的表现。至少不会影响效果,然后梯度下降在这里开始可以改善最终的结果。

残差网络另一个值得讨论的细节是:
我们假定a[l+2]和a[l]是同一维度的,所以你将看到在ResNet中许多相同卷积的应用,输出层的维度相同,所以我们可以做一个快捷连接,因为相同的卷积会保留维度,也使你运算这个快捷连接更加方便,因为运算的是两个相同维度的矢量的和。
如果不是相同维度怎么办?
你需要做的是增加一个额外的矩阵,称它为ws。那么这个ws可以更改a[l]的维度和z[l]相同。
ws矩阵也可以做一些其他的事:比如它可以是一个包含已学习到参数的矩阵,也可以是一个固定的矩阵,其中包含很多0项。

最后我们来看一下ResNet在图像上的应用:

你输入一张图像,然后经过一系列卷积层,直到最终你输出一个softmax分类,要把这个变为ResNet,你需要添加那些额外的跳跃连接。

细节:这里有很多3 * 3卷积,其中大部分都是相同的3 * 3卷积,这也是为什么你需要做相同维度矢量的相加。所以与其说是相互充分连接的层,还不如说这些是卷积层,但由于它们是相同的卷积层,这里的维度相同,因此z[l+2]+a[l]的算数得以成立。

和你之前见过的ResNet相同的是:
你有一堆卷积层,然后偶尔有池化层或者类似于池化的层,你可以利用我们提到的方法调整维度,你可以用矩阵ws人,然后在这些网络中比较常见的是,你有个池,最后连接一个softmax作出预测。

接下来,1 * 1过滤,1 * 1卷积的神经网络,如何使用它?

第五课:网中网,网络中的1x1卷积

在设计卷积网络的架构时,一种很有用的方法是用1 * 1的卷积,1 * 1的卷积能做什么?

如果你有一个6 * 6 * 1的图像,那么经过1 * 1卷积就是进行像素乘法,但是当你的图像有两个维度的时候,和一个1 * 1的过滤器做卷积很有意义:

比如6 * 6 * 32,这个1 * 1的卷积会逐一扫过这里的36个不同的位置,然后进行对应元素之间的乘法,将左边的32个数和过滤器中的32个数相乘(做内积),然后将一个非线性映射ReLu(线性整流函数)作用于它。

事实上,你可以这样理解:这个 * 1 * 32过滤器中的32个数,它类似于你有一个神经元,接收一个32个数的输入向量,将这一条位于相同位置,即相同高度和宽度,但位于32个不同通道的数和32个权重相乘,然后将线性整流函数(ReLu函数)作用于它,再把对应的结果输出到这里。

更通常地,有多个过滤器,那么这类似于,你有不止一个单元,而有多个单元,接收用一面中的所有数作为输入,然后将它们生成一个6 * 6滤波器数的输出量。。。

所以对1 * 1卷积的一种理解就是:
它本质上是一个完全连接的神经网络,逐一作用于这36个不同的位置上,这个完全连接的神经网络所做的是:
它接收32个数的输入,然后输出过滤器数个输出值,即nc[l+1],然后对这36个位置中的每一个都进行相同的操作,最终得到输出为6 * 6 * 过滤器数。

这对你的输入量所进行的是一个非常不平凡的计算,这个想法被称为1 * 1卷积。但有时也被称为网中网。

举一个1 * 1卷积有应用价值的例子:

28 * 28 * 192,通道数太多,想要缩小通道数到28 * 28 * 32,你可以使用32个1 * 1的过滤器,从技术上说,每一个过滤器都会是1 * 1 * 19大小的,因为过滤器的通道数需要和输入量的通道数保持一致。
由于你使用了32个过滤器,所以这个过程的输出将会是28 * 28 * 32大小的立方体。
这是一种让你缩小nc的方式。
而池化层我只可以用它来缩小nh和nw,即这个立方体的高度和宽度。

之后我们会分析为什么1 * 1卷积会缩小通道数,从而达到在某些网络中减少计算量的目的。当然,如果你想保持192个通道数,这也是可行的。
采用192个1 * 1的过滤器,这时1 * 1卷积的效果是增加非线性,它通过添加一层输入28 * 28 * 192再输出28 * 28 * 192的操作,使得你的网络可以学习到更复杂的函数形式。

综上就是1 * 1卷积,可以做一些不平凡的操作,以及在神经网络中增加非线性,以及允许你减少或不改变增加输入的通道数。接下来你会看到这种思想在构建inception network中是十分有用的。

第六课:Inception Network

为卷积网络设计某一层时,你可能需要选择一个1 * 3的滤波器或者3 * 3或则5 * 5等,或者你需要一个池化层,Inception Network是:为什么不全用呢?

这使得网络结构更加复杂,但它的效果也会越好,比如:

Inception Network是指:与其在卷积神经网络中选择一个你想使用的卷积核尺寸,乃至选择你是否需要一个卷积层还是一个池化层,让我们全部都做了吧。

你要做的是,对于不同的过滤器,将第二个量并列的堆叠在第一个量旁边,并且保证维度是匹配的,所以要使用same填充,保证输出与输入的维度相同。
为了保证维度的匹配,事实上你需要为最大池化操作使用填充,所以这是一种不一般的池化。
对于像这样的一个Inception Network,你可以输入一些量并且获得一个输出,如果你把所有过滤器得到的维度加起来,得到256。

即你将有一个Inception Network,输入28 * 28 * 192,输出为28 * 28 * 256。
这就是Inception Network的核心。

这个网络基础的一个特点就是:你不用去只挑选一个卷积核的大小或者是池化,你可以都做,然后把所有的结果结合起来,让神经网络去学习它想要的参数以及他想要用到的卷积核大小。

但是这里会出现一个Inception Network的问题:
计算成本问题。

对于5 * 5过滤器进行分析:看一下获得28 * 28 * 32的输出的计算成本是多少?

你有32个卷积核,因为你有32个通道,然后每一个卷积核大小应该是5x5x192,那么输出张量的大小将是:28x28x32,所以你需要计算28x28x32,每一个都需要做那么多乘法,对应你做乘法的总数为:5x5x192x28x28x32 = 1.2亿。
但是通过1 * 1卷积可以将这个运算降低到其1/10。

另一种计算方法:

你用1 * 1的卷积运算将通道的个数从192减小到16,然后我们用这个相对较小的量去做5x5卷积并最终得到结果,两者的输入和输出维度相同,但是这种计算方法,我们先把这较大的输入减小为一个较小的中间值,也就是只有16个通道而不是192个通道,我们把中间层称为瓶颈层。这个方法的计算成本是:
第一个卷积层的计算成本:28x28x16x192 = 240万

28x28x32x5x5x16 = 1000万

1240万次乘法

第二种方法中,你想加的次数和相乘的次数差不多。

总结一下:如果你在建立一个卷积网络层,并且你不想去决定到底使用1x1, 3x3,5x5的卷积核或者是否使用池化,那么就用这个Inception Network,它会做所有的工作,并将结果都连接起来,通过别计较计算成本,可以看到1 * 1卷积计算可以生成一个瓶颈层,并且显著降低计算成本。

如此剧烈的缩小特征表示的大小会不会影响神经网络的性能?
只要你合理的去实现这个瓶颈层,你既可以缩小输入张量的维度,又不会影响到整体的性能,还能给你节省计算成本。

完整的Inception Network是什么样的?

第七课:Inception Network

你已经学到了所有构建Inception Network的基本模块,让我们把这些模块连接起来从而建立自己的Inception Network。

Inception Network模块的输入值一般是激活值或者来自上层的输出。

这里:
当我们为了保持输出的维度,而对池化使用填充操作的时候,这里的输出和输入相同都是28x28x192,它的通道的个数以及深度和我们给的输入是一样的,这个看上去好像有很多通道,因此我们要做的是加上一个1x1的卷积层,来增强通道的个数。
这样的话,我们避免了在最后的输出中把所有的通道加到池化层。

最后,所有的模块都用来做渠道连接,得到28x28x256的输出

这就是一个Inception模块Inception Network所做的事,差不多把这些模块放到一起。

图中的每一个模块就是一个Inception模块,还有另一个池化层来改变高和宽的维度。

最后一个细节就是:加入了你读的论文。
加入旁支的作用就是:它把隐藏层作为输入,来做预测,在中间就得到softmax输出。它的作用就是保证所计算的特征值,即使它们在最头部的单元里,或者在中间层里,它们对于预测结果不算太差。
这就是Inception Network的正则化,用来防止这个网络过度学习。

GoogleNet

最后。。。名字的来源:

总结:
如果你理解了Inception模块的话,你就能理解Inception Network,Inception Network就是重复的多次使用Inception模块的网络结构,自从Inception模块开发以来,有些新的Inception Network在不同的论文中被提出,但是所有的新版本都是建立在这个基础上的。

你已经学习了一定数量的神经网络,使用的技巧?
如何构建自己的计算机视觉系统?

上一篇下一篇

猜你喜欢

热点阅读