课程笔记地址:https://blog.csdn.net/column/details/26931.html
课程代码地址:https://github.com/duboya/DeepLearning.ai-pragramming-code/tree/master
欢迎大家fork及star!(-O-)
介绍几种经典的卷积神经网络结构,分别是LeNet、AlexNet、VGGNet。
LeNet-5:
LeNet-5主要是针对灰度设计的,所以其输入较小,为32×32×1,其结构如下:
在LeNet中,存在的经典模式:
AlexNet:
AlexNet直接对彩色的大图片进行处理,其结构如下:
AlexNet使得深度学习在计算机视觉方面受到极大的重视。
VGG-16:
VGG卷积层和池化层均具有相同的卷积核大小,都使用3×3,stride=1, SAME的卷积和2×2,stride=2 的池化,采用的same convolution形式(即自动添加padding以保证通过卷积核后图像的长宽不变,只改变channel)。其结构如下卷积核下方x2 x3表示连续两个或者连续三个卷积核):
注:VGG-16的一个好处就是除了其表现性能优异之外,具有非常对称(symmetrical)结构。
ResNet是由残差块所构建。
残差块:
下面是一个普通的神经网络块的传输:
其前向传播公式的计算步骤为:
而ResNet块则将其传播过程增加了一个从 a [ l ] a^{[l]} a[l]直接到 z [ l + 2 ] z^{[l+2]} z[l+2]的连接,将其称之为“short cut”或者“skip connection”:
也就是前向传播公式的最后一个步骤变为: a [ l + 2 ] = g ( z [ l + 2 ] + a [ l ] ) a^{[l+2]} = g(z^{[l+2]} + a^{[l]}) a[l+2]=g(z[l+2]+a[l])
增加“short cut”后,成为残差块的网络结构:
注意这里是连接在Relu激活函数之前。
Residual Network:
多个残差块堆积起来构成ResNet网络结构,其结构如下:
没有“short cut”的普通神经网络和ResNet的误差曲线
ResNet对于中间的激活函数来说,有助于能够达到更深的网络,解决梯度消失和梯度爆炸的问题。
假设有个比较大的神经网络,输入为x,输出为 a [ l ] a^{[l]} a[l]。如果我们想增加网络的深度,这里再给网络增加一个残差块:
假设网络中均使用Relu激活函数,所以最后的输出 a ≥ 0 a \ge 0 a≥0。这里我们给出 a [ l + 2 ] a^{[l+2]} a[l+2]的值:
a [ l + 2 ] = g ( z [ l + 2 ] + a [ l ] ) = g ( W [ l + 2 ] a [ l + 1 ] + b [ l + 2 ] + a [ l ] ) a^{[l+2]} = g(z^{[l+2]}+a^{[l]})=g(W^{[l+2]}a^{[l+1]}+b^{[l+2]}+a^{[l]}) a[l+2]=g(z[l+2]+a[l])=g(W[l+2]a[l+1]+b[l+2]+a[l])
如果使用L2正则化或者权重衰减,会压缩W和b的值,如果 W [ l + 2 ] = 0 W^{[l+2]}=0 W[l+2]=0同时 b [ l + 2 ] = 0 b^{[l+2]}=0 b[l+2]=0,那么上式就变成:
a [ l + 2 ] = g ( z [ l + 2 ] + a [ l ] ) = g ( a [ l ] ) = r e l u ( a [ l ] ) = a [ l ] a^{[l+2]}=g(z^{[l+2]}+a^{[l]})=g(a^{[l]})=relu(a^{[l]})=a^{[l]} a[l+2]=g(z[l+2]+a[l])=g(a[l])=relu(a[l])=a[l]
所以从上面的结果我们可以看出,对于残差块来学习上面这个恒等函数是很容易的。所以在增加了残差块后更深的网络的性能也并不逊色于没有增加残差块简单的网络。所以尽管增加了网络的深度,但是并不会影响网络的性能。同时如果增加的网络结构能够学习到一些有用的信息,那么就会提升网络的性能。
同时由于结构 a [ l + 2 ] = g ( z [ l + 2 ] + a [ l ] ) a^{[l+2]}=g(z^{[l+2]}+a^{[l]}) a[l+2]=g(z[l+2]+a[l]),ResNet在设计中使用了很多相同的卷积,以保持 z [ l + 2 ] z^{[l+2]} z[l+2]和 a [ l ] a^{[l]} a[l]的维度相同。
将普通深度神经网络变为ResNet:
在两个相同的卷积层之间增加“skip connection”。
注意:上图很有意思的一个地方就是当只在相同卷基层之间增加了skip connection,如上图实现部分的skip connection都是相同卷积层(前三个skip connection加在了 (3x3 conv, 64)上面,经过3x3 conv 128的时候,变为虚线(即没有添加),而后在后面连着都是3x3 conv 128的地方又连着做了三个skip connection,这样做的原因就是 如上面结构所述:保持 z(l+2) 与 a(l) 维度相同。
这一点在Ng课程作业里面也有提到,如下:
但是Ng也有在视频中提到,当上图中虚线上操作也进行了的时候,可以采用padding加0的方法把原来a(l)的维度变为z(l+2)的维度,但是我个人在这个地方是有疑问的,padding可以处理图片长宽维度不一致,但是channel维度不一致该当如何,如上图的从64channel变化到128channel。暂时先留个小疑问。(目前可以想到的方法就是采用1x1卷积,将其channel由64变为128)
注:之前的猜测是正确的,如下面Ng作业所述:
即:通过padding来成比例缩放image长宽,通过1x1 filter改变channel,filter卷积核后面不添加任何激活函数,即文中所谓的只做线性变换改变维度使其匹配插入的层维度,但不添加任何非线性激活函数。
注:之所以采用resnet来增大层数,就是因为对于普通卷积神经网络,当层数增大到一定程度之后,会产生梯度消失或者梯度爆炸,这一点在Ng作业里面resnet实现时候也有提到,如下:
1x1卷积:
在二维上的卷积相当于图片的每个元素和一个卷积核数字相乘。
但是在三维上,与 1 × 1 × n C 1×1×n_C 1×1×nC卷积核进行卷积,相当于三维图像上的 1 × 1 × n C 1×1×n_C 1×1×nC的切片,也就是 n C n_C nC个点乘以卷积数值权重,通过Relu函数后,输出对应的结果。而不同的卷积核则相当于不同的隐层神经元结点与切片上的点进行一一连接。
所以根本上1×1卷积核相当于对一个切片上的 n C n_C nC个单元都应用了一个全连接的神经网络。
最终三维的图形应用1×1的卷积核得到一个相同长宽但第三维度变为卷积核个数的图片。
1x1卷积应用:
Inception Network 的作用就是使我们无需去考虑在构建深度卷积神经网络时,使用多大的卷积核以及是否添加池化层等问题。
Inception主要结构:
在上面的Inception结构中,应用了不同的卷积核,以及带padding的池化层。在保持输入图片大小不变的情况下,通过不同运算结果的叠加,增加了通道的数量。
计算成本的问题:
对于上面的 5 × 5 5×5 5×5大小卷积核的计算成本:
对于 1 × 1 1 \times 1 1×1大小卷积核用作过渡的计算成本,也将下面的中间的层叫做“bottleneck layer”:
所以1×1卷积核作为 “bottleneck layer” 的过渡层能够有效减小卷积神经网的计算成本。事实证明,只要合理地设置“bottleneck layer”,既可以显著减小上层的规模,同时又能降低计算成本,从而不会影响网络的性能。
Inception 模块:
将上面说介绍的两种主要思想和模式结合到一起构成 Inception 模块,如下:
Inception Network:
多个Inception 模块的堆叠构成Inception Network,下面是GoogleNet的结构:
注:中间层添加了很多的softmax分类器,用于防止过拟合,即:当进行inception network时候,各分支同样输出结果,旨在充分利用神经网络结构,在中间层即输出结果,最后对比各输出结果,从而寻找最佳输出结果对应的结构。
小数据集:
如今在深度学习领域,许多研究者都会将他们的工作共享到网络上。在我们实施自己的工作的时候,比如说做某种物体的识别分类,但是只有少量的数据集,对于从头开始训练一个深度网络结构是远远不够的。
但是我们可以应用迁移学习,应用其他研究者建立的模型和参数,用少量的数据仅训练最后自定义的softmax网络。从而能够在小数据集上达到很好的效果。
大数据集:
如果我们在自己的问题上也拥有大量的数据集,我们可以多训练后面的几层。总之随着数据集的增加,我们需要“ freeze”的层数越来越少。最后如果我们有十分庞大的数据集,那么我们可以训练网络模型的所有参数,将其他研究者训练的模型参数作为参数的初始化来替代随机初始化,来加速我们模型的训练。
- 该章节也潜意识地表达了构建一个深度学习网络架构,难度是很大的,最合适的方法就是采用别人已经开源的架构,做迁移学习;将自身要求分类结果替换原架构softmax分类结果,前面层架构及权重参数不变(freeze),依据自身数据量多少,决定freeze的层数,最后仅对自己修改部分的层进行训练调参。
- 还有一个需要注意的地方是Ng提到freeze的方法有两种,一种是各大框架(TensorFlow、caffe等)支持这种迁移学习,提供了freeze操作,直接利用框架将前面不用动的层进行freeze(即固定了结构、权重),然后用自身数据进行后面修改部分的训练(微调: fine-tune)。
- 另一种方式是采用直接将前面需要freeze的部分权重结构等保存到本地,然后对输入先走一遍这些部分,将最后层神经元输出结果作为训练集,来训练自己新架构的层。
与其他机器学习问题相比,在计算机视觉领域当下最主要的问题是没有办法得到充足的数据。所以在我们训练计算机数据模型的时候,数据的扩充就是会非常有用。
数据扩充的方法:
注:数据扩充方法中也有很多超参数(如 random cropping 的 random 程度以及 color shifting 中 shifting 往往不是随机的,而是采用符合某种分布的,如Ng提到一种方法 PCA color 增强)需要设定,Ng建议参考别人 data augment 的开源实现中的超参数设定。
训练过程中的数据扩充:
为了节省时间,数据扩充的过程和训练过程可以多CPU多线程来并行的实现。
数据和手工工程:
不同问题当前的数据集大小:
在有大量数据的时候,我们更倾向于使用简单的算法和更少的手工工程。因为此时有大量的数据,我们不需要为这个问题来精心设计特征,我们使用一个大的网络结果或者更简单的模型就能够解决。
相反,在有少量数据的时候,我们从事更多的是手工工程。因为数据量太少,较大的网络结构或者模型很难从这些少量的数据中获取足够的特征,而手工工程实际上是获得良好表现的最佳方式。
对于机器学习应用:
Tips for doing well:
在基准研究和比赛中,下面的tips可能会有较好的表现:
- ensembling的一个问题就是需要计算机同时存储多个网络模型,很占内存。
- muti-crop使用中,Ng建议只保留一个neural network,进行muti-crop,即便如此,此工作也会让运行时间变慢。
- 以上两种方法可以用于bench mark dataset上跑结果发文章,可以参加比赛,但几乎不用于生产环境中(至少Ng自己从来不用,一是太浪费时间,二是需要耗费太多计算资源)。
注:参考补充自:
https://blog.csdn.net/koala_tree/article/details/78531398