4-2 Coursera吴恩达《卷积神经网络》 第二周课程笔记-深度卷积模型:实例探究

72 篇文章 28 订阅

上周的学习4-1 Coursera吴恩达《卷积神经网络》 第一周课程笔记-卷积神经网络基础主要讲解了构建卷积神经网络的一些基本构建:卷积,padding,步长的概念,卷积层,池化层和全连接层这些组件。以及学习了卷积神经网络的所有基本构造模块,还有如何在高效图片识别系统中整合这些模块。这周继续介绍几个经典的神经网络模型(VGG、AlexNet和LeNet-5,以及ResNets和Inception系列)和实例研究。

目录

《2.1 为什么要进行实例探究?》Why look at case studies

《2.2 经典网络》Classic Networks

《2.3 残差网络(ResNets)》Residual Networks (ResNets)

《2.4 残差网络为什么有用?》Why ResNets work?

《2.5 网络中的网络以及 1×1 卷积》Network in Network and 1×1 convolutions

《2.6 谷歌 Inception 网络简介》Inception network motivation

《2.7 Inception网络》Inception network

《2.8 使用开源的实现方案》Using open-source implementations

《2.9 迁移学习》Tranfer Learning

《2.10 数据增强》Data augmentation

《2.11 计算机视觉现状》The state of computer vision

Summary

《2.1 为什么要进行实例探究?》Why look at case studies

事实上,过去几年计算机视觉研究中的大量研究都集中在如何把这些基本构件(卷积层,池化层和全连接层)组合起来,形成有效的卷积神经网络。最直观的方式之一就是去看一些实例,就像很多人通过看别人的代码来学习编程一样,通过研究别人构建有效组件的案例是个不错的办法。实际上在计算机视觉任务中表现良好的神经网络框架往往也适用于其它任务,如果有人已经训练或者计算出擅长识别猫、狗、人的神经网络或者神经网络框架,而你的计算机视觉识别任务是构建一个自动驾驶汽车,你完全可以借鉴别人的神经网络框架来解决自己的问题。

最后,学完本周的几节课,可以读一些计算机视觉方面的研究论文了,Andrew希望这也是你学习本课程的收获。当然,读论文并不是必须的,但是Andrew希望当你发现你可以读懂一些计算机视觉方面的研究论文或研讨会内容时会有一种满足感。言归正传,我们进入主题(So with that, let’s get started)。

后面几节课的提纲(outline)——VGG、AlexNet和LeNet-5,以及ResNets和Inception系列,首先我们来看几个经典的网络。

LeNet-5网络(1980年代),经常被引用的AlexNet,还有VGG网络。这些都是非常有效(pretty effective)的神经网络范例,当中的一些思路为现代计算机视觉技术的发展奠定了基础(laid the foundation)。然后是ResNet,又称残差网络。神经网络正在不断加深,对此你可能有所了解。ResNet神经网络训练了一个深达152层的神经网络,并且在如何有效训练方面,总结出了一些有趣的想法和窍门。课程最后,还有一个Inception神经网络的实例分析。了解这些神经网络会对如何构建有效的卷积神经网络更有感觉。即使计算机视觉并不是主要方向,也能从这些实例中找到一些不错的想法。这里面有很多思路都是多学科融合的产物。总之,即便你不打算构建计算机视觉应用程序,试着从中发现一些有趣的思路,对你的工作也会有所帮助。

《2.2 经典网络》Classic Networks

这节课,我们来学习几个经典的神经网络结构(classic neural network architectures),分别是LeNet-5、AlexNet和VGGNet,开始吧。

上图是LeNet-5的网络结构,假设有一张32×32×1的图片(输入),LeNet-5可以识别图中的手写数字,比如像这样手写数字7。LeNet-5是针对灰度图片训练的,所以图片的大小只有32×32×1。实际上LeNet-5的结构和我们上周讲的最后一个范例非常相似,使用6个5×5的过滤器,步幅为1。由于使用了6个过滤器,步幅为1,padding为0,输出结果为28×28×6,图像尺寸从32×32缩小到28×28。然后进行池化(pooling)操作,在这篇论文发布的那个年代,人们更喜欢使用平均池化,而现在我们可能用最大池化更多一些。在这个例子中,我们进行平均池化,过滤器的宽度为2,步幅为2,图像的尺寸,高度和宽度都缩小了2倍,输出结果是一个14×14×6的图像。这张图片应该不是完全按照比例绘制的,如果严格按照比例绘制,新图像的尺寸应该刚好是原图像的一半。

接下来是卷积层,用一组16个5×5的过滤器,新的输出结果有16个通道。LeNet-5的论文是在1998年撰写的,当时人们并不使用padding,或者总是使用valid卷积,这就是为什么每进行一次卷积,图像的高度和宽度都会缩小,所以这个图像从14到14缩小到了10×10。然后又是池化层,高度和宽度再缩小一半,输出一个5×5×16的图像。将所有数字相乘,乘积是400。

下一层是全连接层,在全连接层中,有400个节点,每个节点有120个神经元,这里已经有了一个全连接层。但有时还会从这400个节点中抽取一部分节点构建另一个全连接层,就像这样,有2个全连接层。

最后一步就是利用这84个特征得到最后的输出,我们还可以在这里再加一个节点用来预测y帽的值,y帽有10个可能的值(对应识别0-9这10个数字)。在现在的版本中则使用softmax函数输出十种分类结果,而在当时,LeNet-5网络在输出层使用了另外一种,现在已经很少用到的分类器。

相比现代版本,这里得到的神经网络会小一些,只有约6万个参数。而现在经常看到含有一千万(10 million)到一亿(100 million)个参数的神经网络,比这大1000倍的神经网络也不在少数。

不管怎样,如果我们从左往右看,随着网络越来越深,图像的高度和宽度在缩小,从最初的32×32缩小到28×28,再到14×14、10×10,最后只有5×5。与此同时,随着网络层次的加深,通道数量一直在增加,从1增加到6个,再到16个。

这个神经网络中还有一种模式(other pattern)至今仍然经常用到,就是一个或多个卷积层后面跟着一个池化层,然后又是若干个卷积层再接一个池化层,然后是全连接层,最后是输出,这种排列方式很常用。

对于那些想尝试阅读经典论文的同学,Andrew再补充几点,会更加深入。这些内容你完全可以跳过,算是对神经网络历史的一种回顾吧,听不懂也不要紧

①读到这篇经典论文时,你会发现,过去人们使用sigmoid函数和tanh函数,而不是ReLu函数,这篇论文中使用的正是sigmoid函数和tanh函数。这种网络结构的特别之处还在于,各网络层之间是有关联的,这在今天看来显得很有趣。

②经典的LeNet-5网络使用了非常复杂的计算方式,每个过滤器都采用和输入模块一样的通道数量。论文中提到的这些复杂细节,现在一般都不用了。

③Andrew认为当时所进行的最后一步其实到现在也还没有真正完成,就是经典的LeNet-5网络在池化后进行了非线性函数处理,在这个例子中,池化层之后使用了sigmoid函数。如果你真的去读这篇论文,这会是最难理解的部分之一,我们会在后面的课程中讲到。

总的来说,上图要讲的网络结构简单一些,来自于原文的第二段(section two)和第三段,原文的后几段介绍了另外一种思路。文中提到的这种图形变形网络如今并没有得到广泛应用,所以在读这篇论文的时候,Andrew建议精读第二段,这段重点介绍了这种网络结构。泛读第三段,这里面主要是一些有趣的实验结果(experimental results)。

下面介绍第二种神经网络AlexNet,是以论文的第一作者Alex Krizhevsky的名字命名的,另外两位合著者是Ilya Sutskever和Geoffery Hinton。

AlexNet首先用一张227×227×3的图片作为输入(实际上原文中使用的图像是224×224×3),但是如果你尝试去推导一下,你会发现227×227这个尺寸更好一些。第一层使用96个11×11的过滤器,步幅为4,因此尺寸缩小到55×55,缩小了4倍左右。然后用一个3×3的过滤器构建最大池化层,f = 3,步幅为2,卷积层尺寸缩小为27×27×96。接着再执行一个5×5的卷积,padding之后,输出是27×27×276。然后再次进行最大池化,尺寸缩小到13×13。再执行一次same卷积,相同的padding,得到的结果是13×13×384,384个过滤器。再做一次same卷积。再做一次同样的操作,最后再进行一次最大池化,尺寸缩小到6×6×256。6×6×256等于9216,将其展开为9216个单元,然后是一些全连接层。最后使用softmax函数输出识别的结果,看它究竟是1000个可能的对象中的哪一个。

实际上,AlexNet神经网络与LeNet有很多相似之处,不过AlexNet要大得多。正如前面讲到的LeNet或LeNet-5大约有6万个参数,而AlexNet包含约6000万个参数。当用于训练图像和数据集时,AlexNet能够处理非常相似(pretty similar)的基本构造模块(basic building blocks),这些模块往往包含着大量的隐藏单元或数据,这一点AlexNet表现出色。AlexNet比LeNet表现更为出色的另一个原因是它使用了ReLu激活函数。

下面提一些比较深奥的内容,如果你并不打算阅读论文,不听也没有关系。(上图下方的红色笔记)(1)第一点,在写这篇论文的时候,GPU的处理速度还比较慢,所以AlexNet采用了非常复杂的方法在两个GPU上进行训练。大致原理是,这些层分别拆分到两个不同的GPU上,同时还专门有一个方法用于两个GPU进行交流。(2)论文还提到,经典的AlexNet结构还有“局部响应归一化层”(Local Response Normalization),即LRN层,这类层应用得并不多,所以Andrew并没有专门讲。局部响应归一层的基本思路(basic idea)是,假如这是网络的一块,比如是13×13×256,LRN要做的就是选取一个位置,从这个位置穿过整个通道,能得到256个数字,并进行归一化。进行局部响应归一化的动机是,对于这张13×13的图像中的每个位置来说,我们可能并不需要太多的高激活神经元(a very high activation)。后来,很多研究者发现LRN起不到太大作用,现在并不用LRN来训练网络。

在AlexNet之前,深度学习已经在语音识别(speech recognition)和其它几个领域获得了一些关注,但正是通过这篇论文,计算机视觉群体开始重视深度学习,并确信深度学习可以应用于计算机视觉领域。此后,深度学习在计算机视觉及其它领域的影响力与日俱增。如果你并不打算阅读这方面的论文,其实可以不用学习这节课。但如果你想读懂一些相关的论文,这是比较好理解的一篇,学起来会容易一些。

最后一个范例是VGG,也叫作VGG-16网络VGG-16网络没有那么多超参数,这是一种只需要专注于构建卷积层的简单网络。首先用3×3,步幅为1的过滤器构建卷积层,padding参数为same卷积中的参数。然后用一个2×2,步幅为2的过滤器构建最大池化层。因此VGG网络的一大优点是它确实简化了神经网络结构,下面具体看看这种网络结构。

假设要识别这个图像224×224×3,在最开始的两层用64个3×3的过滤器对输入图像进行卷积,输出结果是224×224×64,因为使用了same卷积,通道数量也一样。(注意这里没有画出所有的卷积层)进行第一个卷积之后得到224×224×64的特征图,接着还有一层224×224×64,得到这样2个厚度为64的卷积层,意味着我们用64个过滤器进行了两次卷积。接下来创建一个池化层,池化层将输入图像进行压缩,从224×224×64缩小到多少呢?没错,减少到112×112×64。然后又是若干个卷积层,使用129个过滤器,以及一些same卷积,我们看看输出什么结果,112×112×128。然后进行池化,可以推导出池化后的结果是这样(56×56×128)。接着再用256个相同的过滤器进行三次卷积操作,然后再池化,然后再卷积三次,再池化。如此进行几轮操作后,将最后得到的7×7×512的特征图进行全连接操作,得到4096个单元,然后进行softmax激活,输出从1000个对象中识别的结果。

VGG-16的16,就是指这个网络中包含16个卷积层和全连接层。确实是个很大的网络,总共包含约1.38亿个参数,即便以现在的标准来看都算是非常大的网络。但VGG-16的结构并不复杂,这点非常吸引人,而且这种网络结构很规整(quite uniform),都是几个卷积层后面跟着可以压缩图像大小的池化层,池化层缩小图像的高度和宽度。同时,卷积层的过滤器数量变化存在一定的规律,由64翻倍变成128,再到256和512。作者可能认为512已经足够大了,后面的层就不再翻倍了。无论如何,每一步都进行翻倍,或者说在每一组卷积层进行过滤器翻倍操作,正是设计此种网络结构的另一个简单原则(another simple principle)。这种相对一致的网络结构对研究者很有吸引力,而它的主要缺点(downside)是需要训练的特征数量非常巨大。

有些文章还介绍了VGG-19网络,它甚至比VGG-16还要大,如果你想了解更多细节,请参考幻灯片下方的论文(由Karen Simonyan和Andrew Zisserman撰写的论文)。由于VGG-16的表现几乎和VGG-19不分高下,所以很多人还是会使用VGG-16。Andrew最喜欢它的一点是:随着网络的加深,图像的高度和宽度都在以一定的规律不断缩小,每次池化后刚好缩小一半,而通道数量在不断增加,而且刚好也是在每组卷积操作后增加一倍。图像缩小的比例和通道数增加的比例是有规律的。从这个角度来看,这篇论文很吸引人。

以上就是三种经典的网络结构,如果你对这些论文感兴趣,Andrew建议从介绍AlexNet的论文开始,然后就是VGG的论文,最后是LeNet的论文。虽然有些晦涩难懂,但对于了解这些网络结构很有帮助。

学过这些经典的网络之后,下节课我们会学习一些更先高级更强大的神经网络结构,下节课见。

《2.3 残差网络(ResNets)》Residual Networks (ResNets)

非常非常深的神经网络是很难训练的,因为存在梯度消失和梯度爆炸问题。这节课我们学习跳跃连接(Skip connection),它可以从某一层网络层获取激活,然后迅速反馈给另外一层,甚至是神经网络的更深层。利用跳跃连接构建能够训练深度网络的ResNets,有时深度能够超过100层。ResNets是由残差块(Residual block)构建的,首先看一下什么是残差块。

上图是一个两层神经网络。回顾之前的计算过程:

在残差网络中有一点变化:

如上图的紫色部分,我们直接将a^[l]向后,到神经网络的深层,在ReLU非线性激活函数前加上a^[l],将激活值a^[l]的信息直接传达到神经网络的深层,不再沿着主路进行,因此a^[l+2]的计算公式为:

加上a^[l]后产生了一个残差块(residual block)。插入的时机是在线性激活之后,ReLU激活之前。除了捷径(shortcut),你还会听到另一个术语“跳跃连接”(skip connection),就是指a^[l]跳过一层或者好几层,从而将信息传递到神经网络的更深层。

ResNet的发明者是何恺明(Kaiming He)、张翔宇(Xiangyu Zhang)、任少卿(Shaoqing Ren)和孙剑(Jiangxi Sun),他们发现使用残差块能够训练更深的神经网络。所以构建一个ResNet网络就是通过将很多这样的残差块堆积在一起,形成一个很深神经网络。首先回忆一个普通网络(Plain network),这个术语来自ResNet论文。如下图:

变成ResNet的方法是加上所有跳跃连接,每两层增加一个捷径,构成一个残差块。如下图所示,5个残差块连接在一起构成一个残差网络

假设使用标准优化算法(梯度下降法等)训练一个普通网络,如果没有残差,没有这些捷径或者跳跃连接,凭经验你会发现随着网络深度的加深,训练错误会先减少,然后增多。而理论上,随着网络深度的加深,应该训练得越来越好才对,网络深度越深模型效果越好。但实际上,如果没有残差网络,对于一个普通网络来说,深度越深意味着用优化算法越难训练,随着网络深度的加深,训练错误会越来越多。

但有了ResNets就不一样了,即使网络再深,训练的表现却不错,比如说训练误差减少,就算是训练深达100层的网络也不例外。对x的激活,或者这些中间的激活能够到达网络的更深层。这种方式有助于解决梯度消失和梯度爆炸问题,在训练更深网络的同时,又能保证良好的性能。

现在大家对ResNet已经有了一个大致的了解,至于为什么ResNets能有如此好的表现,接下来Andrew会有更多更棒的内容分享给大家,下个视频见。

《2.4 残差网络为什么有用?》Why ResNets work?

通常来讲,网络在训练集上表现好,才能在Hold-Out交叉验证集或dev集和测试集上有好的表现,所以至少在训练集上训练好ResNets是第一步。看一个例子。

有一个大型神经网络,其输入为X,假设在整个网络中使用ReLU激活函数,所以激活值都大于等于0。下面展开a^[l+2]的表达式,注意如果使用L2正则化或权重衰减,会压缩W^[l+2]的值,这里W是关键项(key term),如果假设b^[l+2]=0,等式如下:

结果表明,残差块学习这个恒等式函数并不难,跳跃连接(skip connection)使我们很容易得出a^[l+2]=a^[l]。这意味着,即使给神经网络增加了这两层,它的效率也并不逊色于更简单的神经网络,因为学习恒等函数(identity function)对它来说很简单。所以给大型的神经网络增加两层,不论是把残差块添加到神经网络的中间还是末端位置,都不会影响网络的表现。想象一下,如果这些隐藏层单元学到一些有用信息,那么它可能比学习恒等函数表现得更好

Andrew认为残差网络起作用的主要原因就是这些残差块学习恒等函数非常容易,能确定网络性能不会受到影响,很多时候甚至可以提高效率,或者说至少不会降低网络的效率,因此创建类似残差网络可以提升网络性能。

另一个值得探讨的细节是,假设z^[l+2]和a^[l]具有相同纬度,所以ResNets使用了许多same卷积(same convolutions)。(如上图红色标记)如果输入和输出有不同纬度,例如输入是128,输出是256,需要进行padding,使用0填充。

最后看看ResNets的图片识别,图片来源何凯明等人论文。

上图第一行是一个普通网络,给它输入一张图片,它有多个卷积层,最后输出了一个Softmax。

上图第二行,添加跳跃连接(skip connection),普通网络转化为ResNets。注意几个细节,这个网络有很多层3×3卷积,而且它们大多都是same卷积,这就是添加等维特征向量(equal dimension feature vectors)的原因。所以这些都是卷积层,而不是全连接层,因为它们是same卷积。当然也会有池化层或类池化层。普通网络和ResNets网络常用的结构是:卷积层-卷积层-卷积层-池化层-卷积层-卷积层-卷积层-池化层……依此重复。直到最后,有一个通过softmax进行预测的全连接层。以上就是ResNets的内容。使用1×1的过滤器,即1×1卷积,这个想法很有意思,下个视频看看为什么。

《2.5 网络中的网络以及 1×1 卷积》Network in Network and 1×1 convolutions

在架构内容设计(designing content architectures)方面,其中一个比较有帮助的想法是使用1×1卷积。

如上图第一行,输入一张6×6×1的图片,然后对它做卷积,过滤器大小为1×1×1,这里是数字2,结果相当于把这个图片乘以数字2,所以前三个单元格分别是2、4、6等等。用1×1的过滤器进行卷积,似乎用处不大,只是对输入矩阵乘以某个数字。但这仅仅是对于6×6×1的一个通道图片来说,1×1卷积效果不佳。

如上图第二行,如果输入是一张6×6×32的图片,那么使用1×1过滤器进行卷积效果更好。具体来说,1×1卷积所实现的功能是遍历这36个单元格,计算左图中32个数字和过滤器中32个数字的元素积之和,然后应用ReLU非线性函数。

所以1×1卷积可以从根本上理解为对这32个不同的位置都应用一个全连接层,全连接层的作用是输入32个数字(在这36个单元上重复此过程),输出结果是6×6×#filters(过滤器数量),以便在输入层上实施一个非平凡计算(non-trivial computation)。

这种方法通常称为1×1卷积,有时也被称为Network in Network,在林敏、陈强和颜水成的论文中有详细描述。虽然论文中关于架构的详细内容并没有得到广泛应用,但是1×1卷积或Network in Network这种理念却很有影响力,很多神经网络架构都受到它的影响,包括下节课要讲的Inception网络。

下面介绍1×1卷积的一个应用

假设这是一个28×28×192的输入层,该如何把它压缩为28×28×32维度的层呢?你可以用32个大小为1×1的过滤器,严格来讲每个过滤器大小都是1×1×192维,因为过滤器中通道数量必须与输入层中通道的数量保持一致。在某些网络中1×1卷积是如何压缩通道数量并减少计算的。

如上图红色标记,其输入为28×28×192,输出变成28×28×192。1×1卷积层就是这样实现了一些重要功能的(doing something pretty non-trivial),它给神经网络添加了一个非线性函数,从而减少或保持输入层中的通道数量不变,当然如果你愿意,也可以增加通道数量。后面你会发现这对构建Inception网络很有帮助。

《2.6 谷歌 Inception 网络简介》Inception network motivation

构建卷积层时,需要决定过滤器的大小,而Inception网络的作用就是代替你来决定,虽然网络架构因此变得更加复杂,但网络表现却非常好,我们来了解一下其中的原理。

上图是28×28×192维度的输入层,Inception网络或Inception层的作用就是代替人工来确定卷积层中的过滤器(filter)类型,或者确定是否需要创建卷积层(conv)或池化层(pooling)

如果使用1×1卷积,输出结果会是28×28×#(某个值),假设输出为28×28×64(绿色),并且这里只有一个层。

如果使用3×3的过滤器,那么输出是28×28×128(蓝色)。然后我们把第二个值堆积到第一个值上,为了匹配维度,我们应用same卷积,输出维度依然是28×28,和输入维度相同,即高度和宽度相同。

如果希望提升网络的表现,用5×5过滤器或许会更好,不妨试一下,输出变成28×28×32(紫色),我们再次使用same卷积,保持维度不变。

或许你不想要卷积层,那就可以使用池化层,这里用最大池化操作,得到一些不同的输出结果,我们把它也堆积起来,这里的池化输出是28×28×32(橘色)。为了匹配所有维度,对最大池化使用padding,它是一种特殊的池化形式,因为如果输入的高度和宽度为28×28,则输出的相应维度也是28×28。然后再进行池化,padding不变,步幅为1。

有了这样的Inception模块,你就可以输入某个量,这里的最终输出为32+32+128+64=256(因为它累加了所有数字)。Inception模块的输入为28×28×192,输出为28×28×256这就是Inception网络的核心内容(heart),提出者包括Christian Szegedy、刘伟、贾扬清、Pierre Sermanet、Scott Reed、Dragomir Anguelov、Dumitru Erhan、Vincent Vanhoucke和Andrew Rabinovich。基本思想是Inception网络不需要人为决定使用哪个过滤器或者是否需要池化,而是由网络自行确定这些参数,你可以给网络添加这些参数的所有可能值,然后把这些输出连接起来,让网络自己学习它需要什么样的参数,采用哪些过滤器组合。

下面,计算这个5×5过滤器在该模块中的计算成本(computational cost)

这是一个28×28×192的输入块,这里用一个看起来更普通的蓝色块表示。执行一个5×5卷积,它有32个过滤器,每个过滤器大小为5×5×192,输出为28×28×32。对于输出中的每个数字来说,你都需要执行5×5×192次乘法运算,所以乘法运算的总次数为每个输出值所需要执行的乘法运算次数(5×5×192)乘以输出值个数(28×28×32),把这些数相乘结果等于1.2亿(120422400)。即使在现在,用计算机执行1.2亿次乘法运算,成本也是相当高的。为了降低计算成本,用计算成本除以因子10,结果它从1.2亿减小到原来的十分之一。请记住120这个数字。

上图是另一种结构:1*1卷积降低参数和计算量。对于输入层,使用1×1卷积把输入值从192个通道减少到16个通道。然后对这个较小层运行5×5卷积,得到最终输出。请注意,输入和输出的维度依然相同,输入是28×28×192,输出是28×28×32,和上一页的相同。但我们要做的就是把左边这个大的输入层压缩成这个较小的的中间层,它只有16个通道,而不是192个。有时候这被称为瓶颈层(bottleneck layer),瓶颈通常是某个对象最小的部分。因此我们先缩小网络表示,然后再扩大它。应用1×1卷积,过滤器个数为16,每个过滤器大小为1×1×192,这两个维度相匹配(输入通道数与过滤器通道数),28×28×16这个层的计算成本是,输出28×28×192中每个元素都做192次乘法,用1×1×192来表示,相乘结果约等于240万。第二层卷积层的输出是28×28×32,对每个输出值应用一个5×5×16维度的过滤器,计算结果为1000万。

因此所需要乘法运算的总次数是这两层的计算成本之和,即1204万(12.4 million multiplications),与上一张幻灯片中的值做比较,计算成本从1.2亿下降到了原来的十分之一,即1204万。所需要的加法运算(additions)与乘法运算(multiplications)的次数近似相等,所以这里只统计了乘法运算的次数

总结一下,当你在构建神经网络层的时候,不想决定池化层是使用1×1,3×3还是5×5的过滤器,那么Inception模块就是最好的选择。可以应用各种类型的过滤器,只需要把输出连接起来。对于计算成本问题,通过使用1×1卷积来构建瓶颈层,从而大大降低计算成本。

你可能会问,仅仅大幅缩小表示层规模会不会影响神经网络的性能?事实证明,只要合理构建瓶颈层,你既可以显著缩小表示层规模(shrink down the representation size significantly),又不会降低网络性能(and it doesn’t seem to hurt the performance),从而节省了计算(that saves you a lot of computation)。

这就是Inception模块的主要思想(key ideas)。下个视频,我们将演示一个完整的Inception网络。

《2.7 Inception网络》Inception network

上个视频介绍了Inception网络基础模块(basic building blocks)。在本视频中,我们将学习如何将这些模块组合起来,构建你自己的Inception网络。Inception网络又叫做GoogLeNet。

Inception模块会将之前层的激活或者输出作为它的输入,这是一个28×28×192的输入,和之前视频中的一样。

①第三行:先通过一个1×1的层,再通过一个5×5的层,1×1的层可能有16个通道,而5×5的层输出为28×28×32,共32个通道。

②第二行:为了在这个3×3的卷积层中节省运算量,你也可以做相同的操作,这样的话3×3的层将会输出28×28×128。

③第一行:直接通过一个1×1的卷积层,这时就不必在后面再跟一个1×1的层了,这样的话过程就只有一步,假设这个层的输出是28×28×64。

④第四行:最后是池化层,这里进行最大池化操作,采用same类型的padding进行池化。

为了能在最后将这些输出都连接起来,我们会使用same类型的padding来池化,使得输出的高和宽依然是28×28。但注意,如果你进行了最大池化,即便用了same padding,3×3的过滤器,stride为1,其输出将会是28×28×192,其通道数(the number of channels)或者说深度(depth)与这里的输入(通道数)相同。所以看起来它会有很多通道,我们实际要做的就是再加上一个1×1的卷积层,去进行我们在1×1卷积层的视频里所介绍的操作,将通道的数量缩小,缩小到28×28×32。也就是使用32个维度为1×1×192的过滤器,所以输出的维度其通道数缩小为32。这样就避免了最后输出时,池化层占据所有的通道。这些操作之后,将这些方块全都连接起来(do channel concatenation)。在这过程中,把得到的各个层的通道都加起来,最后得到一个28×28×256的输出。这就是一个Inception模块(Inception module),而Inception网络所做的就是将这些模块都组合到一起。

上图是一张取自Szegety et al的论文中关于Inception网络的图片,图中有许多重复的模块,可能整张图看上去很复杂,但如果你只截取其中一个环节,就会发现这是Inception模块。所以Inception网络只是很多这些你学过的模块在不同的位置重复组成的网络,所以如果你理解了之前所学的Inception模块,你就也能理解Inception网络。

事实上,论文中还有一些分支(上图绿色笔记),在网络的最后几层,通常称为全连接层(fully connected layer),在它之后是一个softmax层来做出预测,这些分支所做的就是通过隐藏层来做出预测,所以这其实是一个softmax输出。这是另一条分支,它也包含了一个隐藏层,通过一些全连接层,然后有一个softmax来预测,输出结果的标签。这个可以看做Inception网络的一个细节,它确保了即便是隐藏单元和中间层也参与了特征计算,它们也能预测图片的分类。在Inception网络中,起到一种调整的效果,并且能防止网络发生过拟合。

最后,有个有趣的事实,Inception网络这个名字又是缘何而来呢?Inception的论文引用了这个网址(http://knowyourmeme.com/memes/we-need-to-go-deeper),连接到这幅图片上:

如果你看过Inception(盗梦空间)这个电影,你应该能看懂这个由来。作者其实是通过它来表明了建立更深的神经网络的决心,他们正是这样构建了Inception。

自从Inception模块诞生以来,经过研究者们的不断发展,衍生了许多新的版本。你会发现人们使用这些新版本的算法效果也一样很好,比如Inception V2、V3以及V4,还有一个版本引入了跳跃连接(skip connections)的方法,有时也会有特别好的效果。通过这个视频,你应该能去阅读和理解这些Inception的论文,甚至是一些新版本的论文。在下个视频中,Andrew将会讨论如何真正去使用这些算法来构建自己的计算机视觉系统,下节视频再见。

《2.8 使用开源的实现方案》Using open-source implementations

现在我们已经学过几个非常有效的神经网络(several highly effective neural network)和ConvNet架构(ConvNet architectures),在接下来的几段视频中Andrew将与我们分享几条如何使用它们的实用性建议(some practical advice),首先从使用开放源码(open-source)的实现开始。这个视频主要讲解如何使用GitHub,网上有很多不错的操作指南,可自行查阅资料

ResNets实现的GitHub地址为:

https://github.com/KaimingHe/deep-residual-networks

总之,如果你在开发一个计算机视觉应用,一个常见的工作流程是,先选择一个你喜欢的架构,或许是你在这门课中学习到的,或者是你从朋友那听说的,或者是从文献中看到的,接着寻找一个开源实现,从GitHub下载下来,以此基础开始构建。这样做的优点在于,这些网络通常都需要很长的时间来训练,而或许有人已经使用多个GPU,通过庞大的数据集预先训练了这些网络,这样一来你就可以使用这些网络进行迁移学习,我们将在下一节课讨论这些内容。

《2.9 迁移学习》Tranfer Learning

计算机视觉的研究社区(computer vision research community)非常喜欢把许多数据集上传到网上,比如ImageNet、MS COCO、Pascal类型的数据集,它们都是由大家上传到网络的,并且有大量的计算机视觉研究者已经用这些数据集训练过他们的算法了。有时候这些训练过程需要花费好几周,并且需要很多的GPU,其它人已经做过了,并且经历了非常痛苦的找最优过程(high performance search process),这就意味着你可以下载花费了别人好几周甚至几个月而做出来的开源的权重参数,把它当作一个很好的初始化用在你自己的神经网络上。用迁移学习(transfer learning)把公共的数据集的知识迁移到你自己的问题上,让我们看一下怎么做。

如上图,举个例子,假如你要建立一个猫咪检测器(cat detection),用来检测你自己的宠物猫(pet cat)。假如你的两只猫叫Tigger和Misty,还有一种情况是,两者都不是。所以是一个三分类问题,我们忽略两只猫同时出现在一张图片里的情况。现在你可能没有Tigger或者Misty的大量的图片,所以你的训练集会很小,你该怎么办呢?

Andrew建议先从网上下载一些神经网络开源的实现,把代码和权重都下载下来。例如,ImageNet数据集,它有1000个不同的类别,因此这个网络会有一个Softmax单元,它可以输出1000个可能类别之一。你可以去掉这个Softmax层,创建自己的Softmax单元,用来输出Tigger、Misty和neither三个类别。就网络而言,Andrew建议把所有的层看作是冻结的,冻结网络中所有层的参数,只需要训练和你的Softmax层有关的参数。幸运的是,大多数深度学习框架都支持这种操作。它也许会有trainableParameter=0这样的参数,有时也会有freeze=1这样的参数。不同的深度学习编程框架有不同的方式,允许你指定是否训练特定层的权重。

(1)还有一个技巧(trick),也许对一些很小的数据集的情况有用(上图第一行紫色部分),由于前面的层都冻结了,相当于一个固定的函数,不需要改变。输入图像,直接把它映射到这层(softmax的前一层)的激活函数。所以这个能加速训练的技巧就是,如果我们先计算这一层(紫色箭头标记),计算特征或者激活值,然后把它们存到硬盘里。你所做的就是用这个固定的函数,在这个神经网络的前半部分(softmax层之前的所有层视为一个固定映射),取任意输入图像,然后计算它的某个特征向量(feature vector),这样你训练的就是一个很浅的softmax模型,用这个特征向量来做预测(make a prediction)。对你的计算有用的一步就是对你的训练集中所有样本的这一层的激活值进行预计算,然后存储到硬盘里,然后在此之上训练softmax分类器。所以,存储到硬盘或者说预计算方法的优点就是,你不需要每次遍历训练集再重新计算这个激活值了。

(2)对于很小的数据集,你可以这样做。(上图第二行)根据经验,如果你有一个更大的标定的数据集,也许你有大量的Tigger和Misty以及两者都不是的照片,你应该冻结更少的层,比如只把这些层冻结(括号中的层),然后训练后面的层。如果你的输出层的类别不同,那么你需要构建自己的输出单元,Tigger、Misty或者两者都不是三个类别。有很多方式可以实现,你可以取后面几层的权重,用作初始化,然后从这里开始梯度下降。或者也可以直接去掉后面这几层,换成你自己的隐藏单元和你自己的softmax输出层,这些方法值得一试。注意有一个规律(pattern),如果你有越来越多的数据,你需要冻结的层数越少,能够训练的层数就越多。

(3)如果你有大量数据(上图第三行)你应该做的就是用开源的网络和它的权重,把所有的权重当作初始化,然后训练整个网络。如果这是一个1000节点的softmax,而你只有三个输出,你需要你自己的softmax输出层来输出你要的标签。如果你有越多的标定的数据,你可以训练越多的层。极端情况下,你可以用下载的权重只作为初始化,用它们来代替随机初始化,接着你可以用梯度下降训练,更新网络所有层的所有权重。

以上这就是卷积网络训练中的迁移学习,事实上,网上的公开数据集非常庞大,并且你下载的其他人已经训练好几周的权重,已经从数据中学习了很多了。对于很多计算机视觉的应用,如果你下载其他人的开源的权重来初始化,你会做的更好。在所有不同学科中(in all the different disciplines),以及所有深度学习不同的应用中,Andrew认为计算机视觉(computer vision)是一个你经常用到迁移学习的领域,除非你有非常非常大的数据集,可以从头开始训练所有的东西。总之,迁移学习是非常值得你考虑的,除非你有一个极其大的数据集(have an exceptionally large data set)和非常大的计算量预算(a very large computational budget)来从头训练你的网络。

《2.10 数据增强》Data augmentation

大部分的计算机视觉任务需要很多的数据,所以数据增强(data augmentation)是经常使用的一种技巧来提高计算机视觉系统的表现。计算机视觉是一个相当复杂的工作,输入图像的像素值,然后弄清楚图片中有什么,似乎你需要学习一个复杂方程(complicated function)来做这件事。在实践中,更多的数据对大多数计算机视觉任务都有所帮助。但是,当下计算机视觉的主要问题是没有办法得到充足的数据(can’t get enough data)。这就意味着当你训练计算机视觉模型的时候,数据增强会有所帮助无论你是使用迁移学习,使用别人的预训练模型开始,或者从源代码开始训练模型。下面来看一下计算机视觉中常见的数据增强的方法。

如上图第一行,或许最简单的数据增强方法就是垂直镜像对称(mirroring on the vertical axis),假如,训练集中有这张图片,然后将其翻转得到右边的图像。对大多数计算机视觉任务,左边的图片是猫,然后镜像对称仍然是猫,如果镜像操作保留了图像中想识别的物体的前提下,这是个很实用的数据增强技巧。

如上图第二行,另一个常用的技巧是随机裁剪(random cropping),给定一个数据集,然后开始随机裁剪。随机裁剪并不是一个完美的数据增强的方法,如果你随机裁剪的那一部分(红色方框标记部分),这部分看起来不像猫。但在实践中,这个方法还是很实用的,随机裁剪构成了很大一部分的真实图片。

镜像对称和随机裁剪是经常被使用的。当然,理论上,你也可以使用旋转(rotation)剪切(shearing)局部弯曲(local warping)等等。当然使用这些方法并没有坏处,尽管在实践中,因为太复杂了所以使用的很少。

还有一种常用方法是彩色转换(color shifting),有这样一张图片,然后给R、G和B三个通道上加上不同的失真值(distortions)。在这个例子中(中间第一张图片),给红色、蓝色通道加值(+20),绿色通道减值(-20)。红色和蓝色会产生紫色,使整张图片看起来偏紫。(中间第二张图片)我们少用了一点红色(-20),更多的绿色和蓝色色调(+20),这就使得图片偏黄一点(yellowish)。(中间第三张图片)使用了更多的蓝色(+50),仅仅多了点红色(+5)。在实践中,R、G和B的值是根据某种概率分布来决定的。这么做的理由是,可能阳光会有一点偏黄,或者是灯光照明有一点偏黄,这些可以轻易的改变图像的颜色,但是对猫的识别,或者是内容的识别,以及标签,还是保持不变的。颜色失真或者是颜色变换方法,这样会使得你的学习算法对照片的颜色更改更具鲁棒性

上图右侧的红色标记是对更高级的学习者的一些注意提醒,也可以不理解。对R、G和B有不同的采样方式,其中一种影响颜色失真的算法是PCA,即主成分分析(Principles Components Analysis),Andrew在Coursera ml-class.Org机器学习这门课中讲过。但具体颜色改变的细节在AlexNet的论文中有时候被称作PCA颜色增强(PCA color augmentation),大概含义是,如果你的图片呈现紫色,即主要含有红色和蓝色,绿色很少,然后PCA颜色增强算法就会对红色和蓝色增减很多,绿色变化相对少一点,所以使总体的颜色保持一致。如果这些你都不懂,不需要担心,可以在网上搜索(search online)你想要了解的东西,如果你愿意的话可以阅读AlexNet论文中的细节,你也能找到PCA颜色增强的开源实现方法,然后直接使用它。

如果数据存在硬盘(hard disk)上,然后使用符号(uses symbol),如上图,用圆桶来表示你的硬盘。如果你有很多数据,你可能会使用CPU线程,然后它不停的从硬盘中读取数据,所以你有一个从硬盘过来的图片数据流。用CPU线程来实现这些失真变形,可以是随机裁剪、颜色变化,或者是镜像。但是对每张图片得到对应的某一种变形失真形式,对其进行镜像变换,以及使用颜色失真,这张图最后会颜色变化,从而得到不同颜色的猫。与此同时,CPU线程持续加载数据,然后实现任意失真变形,从而构成批数据或者最小批数据,这些数据持续的传输给其他线程(thread)或者其他的进程(progress),然后开始训练,可以在CPU或者GPU上实现训一个大型网络的训练。常用的实现数据增强的方法是使用一个线程或者是多线程

这就是数据增强,与训练深度神经网络的其他部分类似,在数据增强过程中也有一些超参数,比如说颜色变化了多少,以及随机裁剪的时候使用的参数。与计算机视觉其他部分类似,一个好的开始可能是使用别人的开源实现,了解他们如何实现数据增强。当然如果你想获得更多的不变特性(capture more invariances),而其他人的开源实现并没有实现这个,你也可以去调整这些参数。

《2.11 计算机视觉现状》The state of computer vision

深度学习已经成功地应用于计算机视觉(computer version)自然语言处理(natural language processing)语音识别(speech recognition)在线广告(online advertising)物流(logistics)还有其他许多问题。在计算机视觉的现状下,深度学习应用于计算机视觉应用有一些独特之处。在这个视频中,Andrew将和你们分享一些对深度学习在计算机视觉方面应用的认识(observations),希望能帮助你们更好地理解计算机视觉作品(此处指计算机视觉或者数据竞赛中的模型)以及其中的想法,以及如何自己构建这些计算机视觉系统。

大部分机器学习问题是介于少量数据和大量数据范围之间的。举个例子,今天我们有相当数量的语音识别数据,至少相对于这个问题的复杂性而言。虽然现在图像识别或图像分类方面有相当大的数据集,因为图像识别是一个复杂的问题,通过分析像素并识别出它是什么,感觉即使在线数据集非常大,如超过一百万张图片,仍然希望我们能有更多的数据。比如目标检测(object detection),我们拥有的数据更少。提醒一下,图像识别其实是如何看图片的问题,并且告诉你这张图是不是猫,而目标检测则是看一幅图,你画一个框,告诉你图片里的物体,比如汽车等等。因为获取边框的成本比标记对象的成本更高,所以我们进行对象检测的数据往往比图像识别数据要少,目标检测是我们下周要讨论的内容。

如果你能从机器学习中发散思维(look across a broad spectrum of machine learning problems),你会发现当你有很多数据时,人们倾向于使用更简单的算法(using simpler algorithm)和更少的手工工程(less hand engineering),因为我们不需要为这个问题精心设计特征。当你有大量的数据时,只要有一个大型的神经网络,甚至一个更简单的架构,可以是一个神经网络,就可以去学习它想学习的东西。相反(whereas in contrast)当你没有那么多的数据时,人们从事更多的是手工工程(engaging in more hand-engineering)Andrew认为当你没有太多数据时,手工工程实际上是获得良好表现的最佳方式

如上图下方,当看机器学习应用时,我们认为通常我们的学习算法有两种知识来源(two sources of konwledge),一个来源是被标记的数据(labeled data),就像(x,y)应用在监督学习。第二个知识来源是手工工程(hand engineering),有很多方法去建立一个手工工程系统,它可以是源于精心设计的特征,手工精心设计的网络体系结构或者是系统的其他组件。

所以Andrew认为计算机视觉是在试图学习一个非常复杂的函数,我们经常感觉我们没有足够的数据,即使获得了更多数据,我们还是经常觉得还是没有足够的数据来满足需求。这就是为什么计算机视觉,从过去甚至到现在都更多地依赖于手工工程。当你没有足够的数据时,手工工程对一个项目来说贡献就很大。当你有很多数据的时候应该花时间去建立学习系统。但我认为从历史而言,计算机视觉领域还只是使用了非常小的数据集,因此从历史上来看计算机视觉还是依赖于大量的手工工程。甚至在过去的几年里,计算机视觉任务的数据量急剧增加(increased dramatically),Andrew认为这导致了手工工程量大幅减少(resulted in a significant reduction),但是在计算机视觉上仍然有很多的网络架构使用手工工程,这就是为什么你会在计算机视觉中看到非常复杂的超参数选择,比你在其他领域中要复杂的多。幸运的是,当你有少量的数据时,有一件事对你很有帮助,那就是迁移学习(transfer learning)。

下面是一些有助于在基准测试中表现出色的小技巧,这些都是Andrew自己从来没使用过的东西,如果我把一个系统投入生产(production),那就是为客户服务(serve customers)。

其中一个是集成(ensembling),这就意味着在你想好了你想要的神经网络之后,可以独立训练几个神经网络,并平均它们的输出。另一个技巧就是Multi-crop at test time,假设你已经看到了如何进行数据增强,Multi-crop是一种将数据增强应用到你的测试图像中的一种形式(crop理解为裁剪的意思)。集成的一个大问题是你需要保持所有这些不同的神经网络,这就占用了更多的计算机内存(takes up a lot more computer memory)。对于multi-crop,你只保留一个网络,所以它不会占用太多的内存,但它仍然会让你的运行时间变慢。

计算机视觉问题建立在小数据集之上,其他人已经完成了大量的网络架构的手工工程。一个神经网络在某个计算机视觉问题上很有效,但令人惊讶的是它通常也会解决其他计算机视觉问题。所以,要想建立一个实用的系统,最好先从其他人的神经网络架构入手。如果可能的话,你可以使用开源的一些应用,因为开放的源码实现可能已经找到了所有繁琐的细节,比如学习率衰减方式或者超参数。最后,其他人可能已经在几路GPU上花了几个星期的时间来训练一个模型,训练超过一百万张图片,所以通过使用其他人的预先训练得模型,然后在数据集上进行微调,你可以在应用程序上运行得更快。

Summary

这就是本周的学习,Andrew希望通过大量的计算机视觉架构能够帮助我们理解什么是有效的。这周介绍了几个经典的神经网络模型(VGG、AlexNet和LeNet-5,以及ResNets和Inception系列)和实例研究。最好是阅读一些经典网络的论文以及新的论文,Andrew希望这也是你学习本课程的收获。当然,读论文并不是必须的。更重要是把握现有开源的资源,多交流多讨论。

说明:记录学习笔记,如果错误欢迎指正!转载请联系我。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值