《吴恩达深度学习》学习笔记011_深度卷积网络:实例探究(Deep convolutional models: case studies)

http://www.ai-start.com/dl2017/html/lesson4-week2.html

深度卷积网络:实例探究(Deep convolutional models: case studies)

为什么要进行实例探究?(Why look at case studies?)

LeNet-5网络,我记得应该是1980年代的,经常被引用的AlexNet,还有VGG网络。这些都是非常有效的神经网络范例,当中的一些思路为现代计算机视觉技术的发展奠定了基础。论文中的这些想法可能对你大有裨益,对你的工作也可能有所帮助。

然后是ResNet,又称残差网络。神经网络正在不断加深,对此你可能有所了解。ResNet神经网络训练了一个深达152层的神经网络,并且在如何有效训练方面,总结出了一些有趣的想法和窍门。课程最后,我们还会讲一个Inception神经网络的实例分析。

了解了这些神经网络,我相信你会对如何构建有效的卷积神经网络更有感觉。即使计算机视觉并不是你的主要方向,但我相信你会从ResNet和Inception网络这样的实例中找到一些不错的想法。这里面有很多思路都是多学科融合的产物。总之,即便你不打算构建计算机视觉应用程序,试着从中发现一些有趣的思路,对你的工作也会有所帮助。

经典网络(Classic networks)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

VGG-16的这个数字16,就是指在这个网络中包含16个卷积层和全连接层。

残差网络(ResNets)(Residual Networks (ResNets))

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

ResNets是由残差块(Residual block)构建的,首先我解释一下什么是残差块。
在这里插入图片描述
这是一个两层神经网络,在 L L L层进行激活,得到 a [ l + 1 ] a^{\left\lbrack l + 1 \right\rbrack} a[l+1],再次进行激活,两层之后得到 a [ l + 2 ] a^{\left\lbrack l + 2 \right\rbrack} a[l+2]。计算过程是从 a [ l ] a^{[l]} a[l]开始,首先进行线性激活,根据这个公式: z [ l + 1 ] = W [ l + 1 ] a [ l ] + b [ l + 1 ] z^{\left\lbrack l + 1 \right\rbrack} = W^{\left\lbrack l + 1 \right\rbrack}a^{[l]} + b^{\left\lbrack l + 1 \right\rbrack} z[l+1]=W[l+1]a[l]+b[l+1],通过 a [ l ] a^{[l]} a[l]算出 z [ l + 1 ] z^{\left\lbrack l + 1 \right\rbrack} z[l+1],即 a [ l ] a^{[l]} a[l]乘以权重矩阵,再加上偏差因子。然后通过ReLU非线性激活函数得到 a [ l + 1 ] a^{\left\lbrack l + 1 \right\rbrack} a[l+1] a [ l + 1 ] = g ( z [ l + 1 ] ) a^{\left\lbrack l + 1 \right\rbrack} =g(z^{\left\lbrack l + 1 \right\rbrack}) a[l+1]=g(z[l+1])计算得出。接着再次进行线性激活,依据等式 z [ l + 2 ] = W [ 2 + 1 ] a [ l + 1 ] + b [ l + 2 ] z^{\left\lbrack l + 2 \right\rbrack} = W^{\left\lbrack 2 + 1 \right\rbrack}a^{\left\lbrack l + 1 \right\rbrack} + b^{\left\lbrack l + 2 \right\rbrack} z[l+2]=W[2+1]a[l+1]+b[l+2],最后根据这个等式再次进行ReLu非线性激活,即 a [ l + 2 ] = g ( z [ l + 2 ] ) a^{\left\lbrack l + 2 \right\rbrack} = g(z^{\left\lbrack l + 2 \right\rbrack}) a[l+2]=g(z[l+2]),这里的 g g g是指ReLU非线性函数,得到的结果就是 a [ l + 2 ] a^{\left\lbrack l + 2 \right\rbrack} a[l+2]。换句话说,信息流从 a [ l ] a^{\left\lbrack l \right\rbrack} a[l] a [ l + 2 ] a^{\left\lbrack l + 2 \right\rbrack} a[l+2]需要经过以上所有步骤,即这组网络层的主路径。

在残差网络中有一点变化,我们将 a [ l ] a^{[l]} a[l]直接向后,拷贝到神经网络的深层,在ReLU非线性激活函数前加上 a [ l ] a^{[l]} a[l],这是一条捷径。 a [ l ] a^{[l]} a[l]的信息直接到达神经网络的深层,不再沿着主路径传递,这就意味着最后这个等式( a [ l + 2 ] = g ( z [ l + 2 ] ) a^{\left\lbrack l + 2 \right\rbrack} = g(z^{\left\lbrack l + 2 \right\rbrack}) a[l+2]=g(z[l+2]))去掉了,取而代之的是另一个ReLU非线性函数,仍然对 z [ l + 2 ] z^{\left\lbrack l + 2 \right\rbrack} z[l+2]进行 g g g函数处理,但这次要加上 a [ l ] a^{[l]} a[l],即:   a [ l + 2 ] = g ( z [ l + 2 ] + a [ l ] ) \ a^{\left\lbrack l + 2 \right\rbrack} = g\left(z^{\left\lbrack l + 2 \right\rbrack} + a^{[l]}\right)  a[l+2]=g(z[l+2]+a[l]),也就是加上的这个 a [ l ] a^{[l]} a[l]产生了一个残差块。

在这里插入图片描述
在上面这个图中,我们也可以画一条捷径,直达第二层。实际上这条捷径是在进行ReLU非线性激活函数之前加上的,而这里的每一个节点都执行了线性函数和ReLU激活函数。所以 a [ l ] a^{[l]} a[l]插入的时机是在线性激活之后,ReLU激活之前。除了捷径,你还会听到另一个术语“跳跃连接”,就是指 a [ l ] a^{[l]} a[l]跳过一层或者好几层,从而将信息传递到神经网络的更深层。

ResNet的发明者是何凯明(Kaiming He)、张翔宇(Xiangyu Zhang)、任少卿(Shaoqing Ren)和孙剑(Jiangxi Sun),他们发现使用残差块能够训练更深的神经网络。所以构建一个ResNet网络就是通过将很多这样的残差块堆积在一起,形成一个很深神经网络,我们来看看这个网络。

这并不是一个残差网络,而是一个普通网络(Plain network),这个术语来自ResNet论文。
在这里插入图片描述
把它变成ResNet的方法是加上所有跳跃连接,正如前一张幻灯片中看到的,每两层增加一个捷径,构成一个残差块。如图所示,5个残差块连接在一起构成一个残差网络。

在这里插入图片描述
如果我们使用标准优化算法训练一个普通网络,比如说梯度下降法,或者其它热门的优化算法。如果没有残差,没有这些捷径或者跳跃连接,凭经验你会发现随着网络深度的加深,训练错误会先减少,然后增多。而理论上,随着网络深度的加深,应该训练得越来越好才对。也就是说,理论上网络深度越深越好。但实际上,如果没有残差网络,对于一个普通网络来说,深度越深意味着用优化算法越难训练。实际上,随着网络深度的加深,训练错误会越来越多。

但有了ResNets就不一样了,即使网络再深,训练的表现却不错,比如说训练误差减少,就算是训练深达100层的网络也不例外。有人甚至在1000多层的神经网络中做过实验,尽管目前我还没有看到太多实际应用。但是对 x x x的激活,或者这些中间的激活能够到达网络的更深层。这种方式确实有助于解决梯度消失和梯度爆炸问题,让我们在训练更深网络的同时,又能保证良好的性能。也许从另外一个角度来看,随着网络越来深,网络连接会变得臃肿,但是ResNet确实在训练深度网络方面非常有效。

残差网络为什么有用?(Why ResNets work?)

为什么ResNets能有如此好的表现,我们来看个例子,它解释了其中的原因,至少可以说明,如何构建更深层次的ResNets网络的同时还不降低它们在训练集上的效率。希望你已经通过第三门课了解到,通常来讲,网络在训练集上表现好,才能在Hold-Out交叉验证集或dev集和测试集上有好的表现,所以至少在训练集上训练好ResNets是第一步。

先来看个例子,上节课我们了解到,一个网络深度越深,它在训练集上训练的效率就会有所减弱,这也是有时候我们不希望加深网络的原因。而事实并非如此,至少在训练ResNets网络时,并非完全如此,举个例子。

在这里插入图片描述
假设有一个大型神经网络,其输入为 X X X,输出激活值 a [ l ] a^{[l]} a[l]。假如你想增加这个神经网络的深度,那么用Big NN表示,输出为$ a^{\left\lbrack l\right\rbrack} 。 再 给 这 个 网 络 额 外 添 加 两 层 , 依 次 添 加 两 层 , 最 后 输 出 为 。再给这个网络额外添加两层,依次添加两层,最后输出为 a^{\left\lbrack l + 2 \right\rbrack} , 可 以 把 这 两 层 看 作 一 个 R e s N e t s 块 , 即 具 有 捷 径 连 接 的 残 差 块 。 为 了 方 便 说 明 , 假 设 我 们 在 整 个 网 络 中 使 用 R e L U 激 活 函 数 , 所 以 激 活 值 都 大 于 等 于 0 , 包 括 输 入 ,可以把这两层看作一个ResNets块,即具有捷径连接的残差块。为了方便说明,假设我们在整个网络中使用ReLU激活函数,所以激活值都大于等于0,包括输入 ResNets便使ReLU0X$的非零异常值。因为ReLU激活函数输出的数字要么是0,要么是正数。

我们看一下 a [ l + 2 ] a^{\left\lbrack l + 2\right\rbrack} a[l+2]的值,也就是上节课讲过的表达式,即 a [ l + 2 ] = g ( z [ l + 2 ] + a [ l ] ) a^{\left\lbrack l + 2\right\rbrack} = g(z^{\left\lbrack l + 2 \right\rbrack} + a^{\left\lbrack l\right\rbrack}) a[l+2]=g(z[l+2]+a[l]),添加项 a [ l ] a^{\left\lbrack l\right\rbrack} a[l]是刚添加的跳跃连接的输入。展开这个表达式 a [ l + 2 ] = g ( W [ l + 2 ] a [ l + 1 ] + b [ l + 2 ] + a [ l ] ) a^{\left\lbrack l + 2 \right\rbrack} = g(W^{\left\lbrack l + 2 \right\rbrack}a^{\left\lbrack l + 1 \right\rbrack} + b^{\left\lbrack l + 2 \right\rbrack} + a^{\left\lbrack l\right\rbrack}) a[l+2]=g(W[l+2]a[l+1]+b[l+2]+a[l]),其中 z [ l + 2 ] = W [ l + 2 ] a [ l + 1 ] + b [ l + 2 ] z^{\left\lbrack l + 2 \right\rbrack} = W^{\left\lbrack l + 2 \right\rbrack}a^{\left\lbrack l + 1 \right\rbrack} + b^{\left\lbrack l + 2\right\rbrack} z[l+2]=W[l+2]a[l+1]+b[l+2]。注意一点,如果使用L2正则化或权重衰减,它会压缩 W [ l + 2 ] W^{\left\lbrack l + 2\right\rbrack} W[l+2]的值。如果对 b b b应用权重衰减也可达到同样的效果,尽管实际应用中,你有时会对 b b b应用权重衰减,有时不会。这里的 W W W是关键项,如果 W [ l + 2 ] = 0 W^{\left\lbrack l + 2 \right\rbrack} = 0 W[l+2]=0,为方便起见,假设 b [ l + 2 ] = 0 b^{\left\lbrack l + 2 \right\rbrack} = 0 b[l+2]=0,这几项就没有了,因为它们( W [ l + 2 ] a [ l + 1 ] + b [ l + 2 ] W^{\left\lbrack l + 2 \right\rbrack}a^{\left\lbrack l + 1 \right\rbrack} + b^{\left\lbrack l + 2\right\rbrack} W[l+2]a[l+1]+b[l+2])的值为0。最后$ a^{\left\lbrack l + 2 \right\rbrack} = \ g\left( a^{[l]} \right) = a^{\left\lbrack l\right\rbrack} , 因 为 我 们 假 定 使 用 R e L U 激 活 函 数 , 并 且 所 有 激 活 值 都 是 非 负 的 , ,因为我们假定使用ReLU激活函数,并且所有激活值都是非负的, 使ReLUg\left(a^{[l]} \right) 是 应 用 于 非 负 数 的 R e L U 函 数 , 所 以 是应用于非负数的ReLU函数,所以 ReLUa^{[l+2]} =a^{[l]}$。

在这里插入图片描述
在这里插入图片描述
结果表明,残差块学习这个恒等式函数并不难,跳跃连接使我们很容易得出$ a^{\left\lbrack l + 2 \right\rbrack} = a^{\left\lbrack l\right\rbrack} 。 这 意 味 着 , 即 使 给 神 经 网 络 增 加 了 这 两 层 , 它 的 效 率 也 并 不 逊 色 于 更 简 单 的 神 经 网 络 , 因 为 学 习 恒 等 函 数 对 它 来 说 很 简 单 。 尽 管 它 多 了 两 层 , 也 只 把 。这意味着,即使给神经网络增加了这两层,它的效率也并不逊色于更简单的神经网络,因为学习恒等函数对它来说很简单。尽管它多了两层,也只把 使a{[l]}$的值赋值给$a{\left\lbrack l + 2 \right\rbrack}$。所以给大型神经网络增加两层,不论是把残差块添加到神经网络的中间还是末端位置,都不会影响网络的表现。

当然,我们的目标不仅仅是保持网络的效率,还要提升它的效率。想象一下,如果这些隐藏层单元学到一些有用信息,那么它可能比学习恒等函数表现得更好。而这些不含有残差块或跳跃连接的深度普通网络情况就不一样了,当网络不断加深时,就算是选用学习恒等函数的参数都很困难,所以很多层最后的表现不但没有更好,反而更糟。

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

在这里插入图片描述
除此之外,关于残差网络,另一个值得探讨的细节是,假设$ z^{\left\lbrack l + 2\right\rbrack} 与 与 a{[l]}$具有相同维度,所以ResNets使用了许多same卷积,所以这个$a{\left\lbrack l\right\rbrack}$的维度等于这个输出层的维度。之所以能实现跳跃连接是因为same卷积保留了维度,所以很容易得出这个捷径连接,并输出这两个相同维度的向量。

如果输入和输出有不同维度,比如输入的维度是128,$ a^{\left\lbrack l + 2\right\rbrack} 的 维 度 是 256 , 再 增 加 一 个 矩 阵 , 这 里 标 记 为 的维度是256,再增加一个矩阵,这里标记为 256W_{s} , , W_{s} 是 一 个 256 × 128 维 度 的 矩 阵 , 所 以 是一个256×128维度的矩阵,所以 256×128W_{s}a^{\left\lbrack l\right\rbrack} 的 维 度 是 256 , 这 个 新 增 项 是 256 维 度 的 向 量 。 你 不 需 要 对 的维度是256,这个新增项是256维度的向量。你不需要对 256256W_{s} 做 任 何 操 作 , 它 是 网 络 通 过 学 习 得 到 的 矩 阵 或 参 数 , 它 是 一 个 固 定 矩 阵 , p a d d i n g 值 为 0 , 用 0 填 充 做任何操作,它是网络通过学习得到的矩阵或参数,它是一个固定矩阵,padding值为0,用0填充 padding00a^{[l]}$,其维度为256,所以者几个表达式都可以。

在这里插入图片描述
最后,我们来看看ResNets的图片识别。这些图片是我从何凯明等人论文中截取的,这是一个普通网络,我们给它输入一张图片,它有多个卷积层,最后输出了一个Softmax。

在这里插入图片描述
如何把它转化为ResNets呢?只需要添加跳跃连接。这里我们只讨论几个细节,这个网络有很多层3×3卷积,而且它们大多都是same卷积,这就是添加等维特征向量的原因。所以这些都是卷积层,而不是全连接层,因为它们是same卷积,维度得以保留,这也解释了添加项$ z^{\left\lbrack l + 2 \right\rbrack} + a^{\left\lbrack l\right\rbrack}$(维度相同所以能够相加)。

在这里插入图片描述
ResNets类似于其它很多网络,也会有很多卷积层,其中偶尔会有池化层或类池化层的层。不论这些层是什么类型,正如我们在上一张幻灯片看到的,你都需要调整矩阵 W s W_{s} Ws的维度。普通网络和ResNets网络常用的结构是:卷积层-卷积层-卷积层-池化层-卷积层-卷积层-卷积层-池化层……依此重复。直到最后,有一个通过softmax进行预测的全连接层。

以上就是ResNets的内容。使用1×1的过滤器,即1×1卷积,这个想法很有意思,为什么呢?我们下节课再讲。

网络中的网络以及 1×1 卷积(Network in Network and 1×1 convolutions)

在架构内容设计方面,其中一个比较有帮助的想法是使用1×1卷积。也许你会好奇,1×1的卷积能做什么呢?不就是乘以数字么?听上去挺好笑的,结果并非如此,我们来具体看看。

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

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

我们以其中一个单元为例,它是这个输入层上的某个切片,用这36个数字乘以这个输入层上1×1切片,得到一个实数,像这样把它画在输出中。

这个1×1×32过滤器中的32个数字可以这样理解,一个神经元的输入是32个数字(输入图片中左下角位置32个通道中的数字),即相同高度和宽度上某一切片上的32个数字,这32个数字具有不同通道,乘以32个权重(将过滤器中的32个数理解为权重),然后应用ReLU非线性函数,在这里输出相应的结果。

在这里插入图片描述

一般来说,如果过滤器不止一个,而是多个,就好像有多个输入单元,其输入内容为一个切片上所有数字,输出结果是6×6过滤器数量。

所以1×1卷积可以从根本上理解为对这32个不同的位置都应用一个全连接层,全连接层的作用是输入32个数字(过滤器数量标记为 n C [ l + 1 ] n_{C}^{\left\lbrack l + 1\right\rbrack} nC[l+1],在这36个单元上重复此过程),输出结果是6×6×#filters(过滤器数量),以便在输入层上实施一个非平凡(non-trivial)计算。

这种方法通常称为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维,因为过滤器中通道数量必须与输入层中通道的数量保持一致。但是你使用了32个过滤器,输出层为28×28×32,这就是压缩通道数( n c n_{c} nc)的方法,对于池化层我只是压缩了这些层的高度和宽度。
在这里插入图片描述
在之后我们看到在某些网络中1×1卷积是如何压缩通道数量并减少计算的。当然如果你想保持通道数192不变,这也是可行的,1×1卷积只是添加了非线性函数,当然也可以让网络学习更复杂的函数,比如,我们再添加一层,其输入为28×28×192,输出为28×28×192。

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

这节课我们演示了如何根据自己的意愿通过1×1卷积的简单操作来压缩或保持输入层中的通道数量,甚至是增加通道数量。下节课,我们再讲讲1×1卷积是如何帮助我们构建Inception网络的,下节课见。

谷歌 Inception 网络简介(Inception network motivation)

构建卷积层时,你要决定过滤器的大小究竟是1×1(原来是1×3,猜测为口误),3×3还是5×5,或者要不要添加池化层。而Inception网络的作用就是代替你来决定,虽然网络架构因此变得更加复杂,但网络表现却非常好,我们来了解一下其中的原理。

例如,这是你28×28×192维度的输入层,Inception网络或Inception层的作用就是代替人工来确定卷积层中的过滤器类型,或者确定是否需要创建卷积层或池化层,我们演示一下。

在这里插入图片描述
如果使用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网络的核心内容,提出者包括Christian Szegedy、刘伟、贾阳青、Pierre Sermanet、Scott Reed、Dragomir Anguelov、Dumitru Erhan、Vincent Vanhoucke和Andrew Rabinovich。基本思想是Inception网络不需要人为决定使用哪个过滤器或者是否需要池化,而是由网络自行确定这些参数,你可以给网络添加这些参数的所有可能值,然后把这些输出连接起来,让网络自己学习它需要什么样的参数,采用哪些过滤器组合。

不难发现,我所描述的Inception层有一个问题,就是计算成本,下一张幻灯片,我们就来计算这个5×5过滤器在该模块中的计算成本。

Inception 网络(Inception network)

在上节视频中,你已经见到了所有的Inception网络基础模块。在本视频中,我们将学习如何将这些模块组合起来,构筑你自己的Inception网络。

在这里插入图片描述
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来池化,使得输出的高和宽依然是28×28,这样才能将它与其他输出连接起来。但注意,如果你进行了最大池化,即便用了same padding,3×3的过滤器,stride为1,其输出将会是28×28×192,其通道数或者说深度与这里的输入(通道数)相同。所以看起来它会有很多通道,我们实际要做的就是再加上一个1×1的卷积层,去进行我们在1×1卷积层的视频里所介绍的操作,将通道的数量缩小,缩小到28×28×32。也就是使用32个维度为1×1×192的过滤器,所以输出的维度其通道数缩小为32。这样就避免了最后输出时,池化层占据所有的通道。

在这里插入图片描述
最后,将这些方块全都连接起来。在这过程中,把得到的各个层的通道都加起来,最后得到一个28×28×256的输出。通道连接实际就是之前视频中看到过的,把所有方块连接在一起的操作。这就是一个Inception模块,而Inception网络所做的就是将这些模块都组合到一起。

在这里插入图片描述
这是一张取自Szegety et al的论文中关于Inception网络的图片,你会发现图中有许多重复的模块,可能整张图看上去很复杂,但如果你只截取其中一个环节(编号1),就会发现这是在前一页ppt中所见的Inception模块。

我们深入看看里边的一些细节,这是另一个Inception模块(编号2),这也是一个Inception模块(编号3)。这里有一些额外的最大池化层(编号6)来修改高和宽的维度。这是另外一个Inception模块(编号4),这是另外一个最大池化层(编号7),它改变了高和宽。而这里又是另一个Inception模块(编号5)。

所以Inception网络只是很多这些你学过的模块在不同的位置重复组成的网络,所以如果你理解了之前所学的Inception模块,你就也能理解Inception网络。

在这里插入图片描述
事实上,如果你读过论文的原文,你就会发现,这里其实还有一些分支,我现在把它们加上去。所以这些分支有什么用呢?在网络的最后几层,通常称为全连接层,在它之后是一个softmax层(编号1)来做出预测,这些分支(编号2)所做的就是通过隐藏层(编号3)来做出预测,所以这其实是一个softmax输出(编号2),这(编号1)也是。这是另一条分支(编号4),它也包含了一个隐藏层,通过一些全连接层,然后有一个softmax来预测,输出结果的标签。

你应该把它看做Inception网络的一个细节,它确保了即便是隐藏单元和中间层(编号5)也参与了特征计算,它们也能预测图片的分类。它在Inception网络中,起到一种调整的效果,并且能防止网络发生过拟合。

还有这个特别的Inception网络是由Google公司的作者所研发的,它被叫做GoogleLeNet,这个名字是为了向LeNet网络致敬。在之前的视频中你应该了解了LeNet网络。我觉得这样非常好,因为深度学习研究人员是如此重视协作,深度学习工作者对彼此的工作成果有一种强烈的敬意。

最后,有个有趣的事实,Inception网络这个名字又是缘何而来呢?Inception的论文特地提到了这个模因(meme,网络用语即“梗”),就是“我们需要走的更深”(We need to go deeper),论文还引用了这个网址(http://knowyourmeme.com/memes/we-need-to-go-deeper),连接到这幅图片上,如果你看过Inception(盗梦空间)这个电影,你应该能看懂这个由来。作者其实是通过它来表明了建立更深的神经网络的决心,他们正是这样构建了Inception。我想一般研究论文,通常不会引用网络流行模因(梗),但这里显然很合适。

使用开源的实现方案(Using open-source implementations)

ResNets实现的GitHub地址https://github.com/KaimingHe/deep-residual-networks

迁移学习(Transfer Learning)

我建议你从网上下载一些神经网络开源的实现,不仅把代码下载下来,也把权重下载下来。有许多训练好的网络,你都可以下载。举个例子,ImageNet数据集,它有1000个不同的类别,因此这个网络会有一个Softmax单元,它可以输出1000个可能类别之一。
在这里插入图片描述
你可以去掉这个Softmax层,创建你自己的Softmax单元,用来输出Tigger、Misty和neither三个类别。就网络而言,我建议你把所有的层看作是冻结的,你冻结网络中所有层的参数,你只需要训练和你的Softmax层有关的参数。这个Softmax层有三种可能的输出,Tigger、Misty或者都不是。

通过使用其他人预训练的权重,你很可能得到很好的性能,即使只有一个小的数据集。幸运的是,大多数深度学习框架都支持这种操作,事实上,取决于用的框架,它也许会有trainableParameter=0这样的参数,对于这些前面的层,你可能会设置这个参数。为了不训练这些权重,有时也会有freeze=1这样的参数。不同的深度学习编程框架有不同的方式,允许你指定是否训练特定层的权重。在这个例子中,你只需要训练softmax层的权重,把前面这些层的权重都冻结。

最后,如果你有大量数据,你应该做的就是用开源的网络和它的权重,把这、所有的权重当作初始化,然后训练整个网络。再次注意,如果这是一个1000节点的softmax,而你只有三个输出,你需要你自己的softmax输出层来输出你要的标签。

如果你有越多的标定的数据,或者越多的Tigger、Misty或者两者都不是的图片,你可以训练越多的层。极端情况下,你可以用下载的权重只作为初始化,用它们来代替随机初始化,接着你可以用梯度下降训练,更新网络所有层的所有权重。

这就是卷积网络训练中的迁移学习,事实上,网上的公开数据集非常庞大,并且你下载的其他人已经训练好几周的权重,已经从数据中学习了很多了,你会发现,对于很多计算机视觉的应用,如果你下载其他人的开源的权重,并用作你问题的初始化,你会做的更好。在所有不同学科中,在所有深度学习不同的应用中,我认为计算机视觉是一个你经常用到迁移学习的领域,除非你有非常非常大的数据集,你可以从头开始训练所有的东西。总之,迁移学习是非常值得你考虑的,除非你有一个极其大的数据集和非常大的计算量预算来从头训练你的网络。

数据增强(Data augmentation)

翻转
旋转裁切
彩色转换,给R、G和B三个通道上加上不同的失真值

计算机视觉现状(The state of computer vision)

下面是一些有助于在基准测试中表现出色的小技巧,这些都是我自己从来没使用过的东西,如果我把一个系统投入生产,那就是为客户服务。
在这里插入图片描述
其中一个是集成,这就意味着在你想好了你想要的神经网络之后,可以独立训练几个神经网络,并平均它们的输出。比如说随机初始化三个、五个或者七个神经网络,然后训练所有这些网络,然后平均它们的输出。另外对他们的输出进行平均计算是很重要的,不要平均他们的权重,这是行不通的。看看你的7个神经网络,它们有7个不同的预测,然后平均他们,这可能会让你在基准上提高1%,2%或者更好。这会让你做得更好,也许有时会达到1%或2%,这真的能帮助你赢得比赛。但因为集成意味着要对每张图片进行测试,你可能需要在从3到15个不同的网络中运行一个图像,这是很典型的,因为这3到15个网络可能会让你的运行时间变慢,甚至更多时间,所以技巧之一的集成是人们在基准测试中表现出色和赢得比赛的利器,但我认为这几乎不用于生产服务于客户的,我想除非你有一个巨大的计算预算而且不介意在每个用户图像数据上花费大量的计算。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值