作者:Eugenio Culurciello
翻译:叶俊贤
校对:叶俊贤
原文链接:https://medium.com/towards-data-science/neural-network-architectures-156e5bad51ba
声明:本文的转载与翻译工作已获得原文作者同意,如果喜欢本文欢迎转载,但是请注明出处。另外笔者能力有限,翻译过程中难免发生错误,欢迎讨论与指正。
深度神经网络和深度学习算法因为在科研工作与工程任务中都取得了显著的效果从而大受欢迎。而其中取得显著成功的深度神经网络通常是由于它们成功的架构设计。因此,在这里我准备同大家分享并回顾一下最近几年神经网络架构的发展历史。
请注意,本篇博客仅仅做了一个比较简单的介绍,如果看完博客之后还想更深入地了解博客中提到的每种神经网络之间的差异,请继续阅读论文《An Analysis of Deep Neural Network Models for Practical Applications》。下图展示该篇论文中的一个代表性工作。
该图展示的了多种主流的神经网络体系架构。其中横轴表示完成一次前向传播所需的操作量,竖轴表示 top-1 准确率。
LeNet5
LeNet5 的提出可以追溯到 1994 年,它可以算作最早的卷积神经网络之一,而且有效地推进了深度学习的发展进程。下图展示的是这一富有先驱性的神经网络架构,它是由 Yann LeCun 提出的。LeCun 自 1988 年开始探索,经过多年的成功迭代才最终提出了 LeNet5 。
LeNet5 的网络架构非常基础,特别是发现了图像特征分布于整个图像之中,而且具有可学习参数的卷积操作是通过少量参数从(图像)多个位置提取相似特征的有效方式。不过在当时并没有 GPU 可以用于加速训练过程,甚至连 CPU 的计算速度也相当慢。因此能够保存参数和计算是该模型的关键优势。它与将每个像素点单独输入大型多层神经网络的做法不同。 LeNet5 认为将每个像素点都作为单独输入的全连接方式不应该被应用在第一层,因为图像像素间具有高度的空间相关性,而将所有像素都进行单独输入的做法将丢失像素间的空间相关性。
LeNet5 的特点可以被总结如下:
- 确定了卷积神经网络的 3 层序列:卷积层(Convolution)、池化层(Pooling)和非线性层(Non-linearity)。也许自本篇论文发表之后,这一点就成为了深度学习处理图像问题的一大关键特性
- 使用卷积操作来提取空间特征
- 使用图空间平均来实现子采样
- 通过 tanh 或 sigmoids 函数引入非线性
- 使用多层神经网络作为最后的分类器
- 在层与层之间使用稀疏连接矩阵来避免大量的计算
总而言之,LeNet5 是当前许多神经网络的鼻祖,而且也启发了许多从事该领域研究的人。
空白期
从 1998 年到 2010 年期间,神经网络处于一个酝酿期。大多数人还没有注意到它的潜力,不过仍有研究员在缓慢地推进着神经网络的发展。后来,因为手机相机和廉价数码相机的兴起,使得图像数据变得越来越多。同时计算机的运算能力也在逐步提升,CPU 变得越来越快,而 GPU 成为了通用计算工具。虽然速度很慢,但这两个趋势都推动着神经网络的发展。数据和计算能力的进步使得神经网络能够处理的任务变得越来越有趣,然后一切开始变得清晰。
Dan Ciresan Net
在 2010,Dan Claudiu Ciresan 和 Jurgen Schmidhuber 实现了最早的基于 GPU 的神经网络之一。他们在 NVIDIA GTX 280 图形处理器上实现了前向传播和后向反馈计算,并且该神经网络高达 9 层。
AlexNet
在 2012 年,Alex Krizhevsky 发表了 AlexNet。 该神经网络在 LeNet 的基础上调整了网络架构并加深了深度,在当年的 ImageNet 大赛上以明显优势夺得了冠军。
AlexNet 将 LeNet 对神经网络的研究扩展到一个更大的网络中,通过它可以学习更加复杂的对象和对象层次架构。AlexNet 的贡献有:
- 使用整流线性单元(ReLU)引入非线性
- 使用了 dropout 技术在网络训练期间选择性地忽视掉一些神经元,以此来避免模型过拟合
- 堆叠最大池化层(Max pooling)以避免平均池化(Average pooling)的平均效果
- 使用 NVIDIA GTX 580 显卡来减少训练时间
在当时,GPU 比 CPU 提供了更多的内核数,并且训练速度也得到了 10 倍提升。这一优势反过来又允许我们使用更大的数据集和更高分辨率的图像。
AlexNet 的成功引发了一场小变革。卷积神经网络成为了现在深度学习的主力,而深度学习则成为了“能够解决有用任务的大型神经网络”的新代名词。
OverFeat
2013 年 12 月,Yann LeCun 所在的纽约大学实验室提出了 OverFeat,它是 AlexNet 的衍生品。该论文还提出了学习边框(Learning bounding boxes)的概念,这在后来引起了许多其它相同主题论文的出现。我认为学习分割对象比学习人造边框要来得好。
VGG
来自牛津大学的 VGG 网络首次尝试了在每个卷积层中使用更小的 3x3 卷积核,并且将它们组合成一系列卷积。
然而 LeNet 认为通过较大的卷积可以捕获到图像中相似的特征,VGG 的这一做法似乎违背的 LeNet 的原则。VGG 所使用的卷积代替了 AlexNet 中的 9x9 或者 11x11 的卷积核,卷积核开始变得越来越小,以至于开始非常接近于 LeNet 极力想要避免的臭名昭著的 1x1 卷积。但是 VGG 的巨大优势是发现了连续多次的 3x3 卷积可以模拟出较大卷积核的效果,比如 5x5 或者 7x7。而这些想法也被应用在了诸如 Inception 和 ResNet 这些更新的网络架构当中。
VGG 网络使用多个 3x3 卷积层来表达复杂特征。注意到上图中 VGG-E 网络的3、4、5块(译者注:应该指的是卷积层5~16层),这里多次使用了 3x3 的卷积核以提取更加复杂的特征以及这些特征的组合。这样显然增加了参数的数量和对计算能力的要求。同时训练这些网络也是困难的,必须分成更小的网络,然后再逐层添加上去。这是因为缺乏强大的机制来正则化模型,或者以某种方式限制由于大量参数而提升的搜索空间。
VGG 在许多层中都使用了较大规模的特征图(Feature maps),因此在模型推理的过程中对计算资源的花销比较大。在 Inception 和 Bottlenecks 中,采用了减少特征数量的策略来节约计算花销。
Network-in-network
Network-in-netwok ( NiN ) 对使用 1x1 大小的卷积来为每个卷积层的特征提供更多组合能力做了很棒而又简单的分析。
NiN 网络在每次卷积之后使用了空间 MLP 层,以便于在下一层之前能够更好地组合特征。再一次地,有些人可能认为 1x1 卷积与 LeNet 的原理相违背,但是实际上它们帮助卷积特征以更好的方式组合起来,而这点通过简单地堆叠更多的卷积层是无法做到的。这与直接使用原始像素值作为下一层的输入不同,1x1 卷积核被用来在卷积操作之后将所有特征图(Feature maps)的空间特征组合起来。并且它们只使用了很少的参数,因为这些参数在特征图的所有像素间是共享的。
通过将独立的卷积特征组合成更加复杂的组,MLP 可以大大地增加这些独立卷积特征的有效性。这个想法将在以后的最新架构中(比如 ResNet、Inception和其它衍生品)被广泛使用。
NiN 还使用了平均采样层(Average pooling layer)作为最后分类器的一部分,这项做法是 NiN 的另外一个贡献,并且在后来也被普遍使用。这是为了在分类之前将网络的响应平均为输入图像的多个区域。
GoogLeNet and Inception
来自的 Google 的 Christian Szegedy 开始研究如何减少深度神经网络的计算负担,并设计第一个 Inception 架构——GoogLeNet 。
到目前为止,2014 年秋季,深度学习模型在图像和视频帧的内容分类问题上变得非常有用。大多数怀疑论者认为这一次深度学习和神经网络强势回归并且将留下。鉴于这些技术的实用性,像 Google 这样的互联网巨头对于如何能在他们服务器集群上高效和大规模地部署这些架构非常感兴趣。
Christian 想出了许多办法来减少深度神经网络的计算负担,同时还要保证算法的性能要取得最好的表现(比如 ImageNet 竞赛)。或者能够维持相同的计算花销,但是却取得更好的性能表现。
他和他的团队想出了一种 Inception 模块:
上图展示了一系列的 1x1、 3x3 和 5x5 卷积的并行组合。但是 Inception 模块的一大洞见是,在计算昂贵的并行块之前,使用 1x1 卷积块(NiN)来减少特征的数量。这通常被称为“Bottleneck”。这一点在下一节“Bottleneck layer”中将有专门介绍。
GoogLeNet 使用一个没有 Inception 的模块作为初始层,并且类似于 NiN, 采用平均池化加上 Softmax 作为最终的分类器的一部分。与 AlexNet 和 VGG 相比,该分类器的操作数被极大地减少。并且也为高效的网络设计做出了贡献。
Bottleneck layer
受 NiN 的启发,Inception 的 bottleneck layer 通过减少特征数量从而减少每一层的操作数,也因此加速了模型推理过程。在将数据传送到计算昂贵的卷积模块前,特征的数量已经被减少了 4 倍。这节约了大量的计算成本,并且促进了该架构的成功。
让我们来仔细研究一下。假设有 256 个特征作为输入,并且需要输出 256 个特征,而 Inception 层只执行 3x3 的卷积运算。这就必须执行的 256x256 x 3x3 次卷积(589,000 次乘法累加操作)。这可能超出了我们的计算预算,比如说,要实现在 Google 服务器上以 0.5 毫秒来运行这一层。因此我们决定减少被卷积的特征数量,比如减少为 64 或者 256/4 。在这种情况下,我们首先执行 1x1 卷积使得特征数 256->64 ,然后在所有的 Inception 分支上进行 64 次卷积,最后我们再次使用 1x1 卷积使得特征数恢复 64->256 。现在的操作数是:
- 256 x 64 x 1 x 1 = 16,000s
- 64 x 64 x 3 x 3 = 36,000s
- 64 x 256 x 1 x 1 = 16,000s
现在总的操作数是 7 万次,这要远远少于最开始接近 60 万次的操作,而且少了几乎 10 倍的操作量。
虽然我们减少了操作数,但是我们并么有失去这一层的通用性。事实上,bottleneck layer 已经被证明了在 ImageNet 数据集上可以取得很好的效果,并且也被应用于后续的其它架构中,比如 ResNet 。
它成功的原因是发现输入的特征是相关的,因此可以通过将特征适当地与 1x1 卷积结合来去除冗余。在已经缩小规模的特征上执行卷积之后,可以再次被扩展成对下一层有意义的组合。
Inception V3(and V2)
Christian 和他的团队是一支非常高效的科研队伍。在 2015 年 2 月 Batch-normalized Inception 被作为 Inception V2 而发表。批量正则化(Batch-normalization)计算输出层中的所有特征图的均值和标准差,并且利用这些值对其响应进行归一化处理。这对应于“白化(Whitening)”数据,从而使得所有神经图具有相同规模的响应,并且均值为零。这样有助于训练,因为下一层就不需要从输入数据中学习偏移量,并且可以专注于如何最好地组合特征。
2015 年 12 月,他们又发表了一个新版的 Inception 模块和相对应的架构。这篇论文更好地解释原先的 GooLeNet 架构,而且给出了许多关于设计选择上的细节。以下是一些原始想法:
通过仔细构建深度与宽度平衡的网络来最大化流入网络的信息。在每一次池化操作前,增大特征图的规模
当深度增加时,特征的数量或者该层的宽度也相应地有所增加
-
如果有可能,则只使用 3x3 卷积。因为 5x5 和 7x7 的卷积都可以被分解为多个连续的 3x3 卷积。见下图:
-
新版本的 Inception 模块因此变成了:
-
卷积核也可以通过扁平卷积(Flattened convolutions)分解成更加复杂的模块:
-
Inception 模块可以通过在执行 inception 计算的时候提供池化来减小数据的大小。这与执行简单池化层的并行卷积基本相同:
最后 Incetption 依然采用池化层加 Softmax 作为最后的分类器。
ResNet
这场革命发生在 2015 年 12 月。ResNet 有一个很朴素的思想:将经过两个连续卷积层运算的输出与输入进行与(AND)运算。
这与这种已有的想法相类似。但是此处,输入绕过了两层卷积,并且被应用到了更大的规模中。将输入直接绕过两层卷积是一个关键的洞察,因为如果只绕过一层并不会带来太多的提升。通过两层可以被认为是一个小型分类器,或者是网络中的网络(Network-in-Network)。
这也是第一次有人训练了超过百层,甚至 1000 层的神经网络。
包含有许多层的 ResNet 开始使用 bottleneck 层,类似于 Inception 中的 bottleneck:
这种架构通过在第一层使用一个具有更小输出(通常是输入的 1/4)的 1x1 卷积来减少之后每一层的特征数量,之后是一个 3x3 的卷积层,然后又是通过一个 1x1 的卷积将特征数量恢复到一个较大值。就像 Inception 模块一样,这么做允许在保持较低计算量的同时还能提供特征的丰富组合。参见 “GoogLeNet and Inception”之后的“bottleneck layer”部分。
ResNet 在输入层上使用了相当简单的初始层:一个 7x7 的卷积层之后跟随着一个大小为 2 的池化层。这一点与 Inception V3(V4) 中复杂而且不直观的初始层大不相同。
ResNet 也使用了一个池化层加 Softmax 作为最后的分类器。
更多的有关于 ResNet 架构的见解每天都在出现:
- ResNet 可以被同时看做是并行和串行模块。因为输入并行地进入到许多模块,同时每个模块的输出也被串联起来
- ResNet 也可以被看做是多个并行或串行模块的整体
- 研究已经发现 ResNet 通常以相对较浅 20~30 层的方式在块中操作,这些层之间是并行的,而不是串行地流过整个网络
- ResNet 的输出被反馈到输入中,这类似于 RNN。该网络可以被看做是更好的生物似然的皮质模型(bio-plausible model of the cortex)
Inception V4
然后 Christian 和他的团队再次发表了新一版本的 Inception 。
该 Inception 模块在 stem 之后的部分与 Inception V3 很相似:
他们同时也将 Inception 模块与 ResNet 模块相结合:
这一次,在我看来,该解决方案不太优雅也更加复杂,而且还具有不太透明的启发式。很难理解为什么做出了这样的选择,并且作者自身也难解释清楚。
在这方面,能够被轻易地理解和修改而又干净简洁的网络应该算是 ResNet 了。
SqueezeNet
SqueezeNet 在最近被发表。它是 ResNet 和 Inception 中许多概念的重新散列,而且表明了更好的架构设计能够提供更小规模的网络和参数,从而不需要使用复杂的压缩算法。
ENet
我们的团队将最新架构的所有特点组合成一个非常高效并且轻量级的网络,该网络只需要非常少的参数而且还能获得最好的结果。该网络架构被称为 ENet,由 Adam Paszke 设计。我们已经将该网络应用于像素标签(Pixel-wise labeling)和场景分析(Scene-parsing)。这些是一些 ENet 的视频,这些视频并不属于 ENet 网络训练数据中的一部分。
有关于 ENet 的技术报告可以在这里获得。ENet 是一个编码器加解码器网络。编码器就是一个用于分类的常规 CNN,而解码器则是一个用于图像分割的将类别传播回原始图像大小的上采样网络。该研究工作只使用神经网络,并且没有使用任何其它的算法来实现图像分割。
如图所示,ENet 取得了最高的 Top-1 准确率密度。
ENet 设计的初衷就是尽可能减少资源的使用量。因此它实现了在 16 帧的精度下,编解码网络的总参数只占到了 0.7 MB 空间。即使参数的体量这么小,ENet 与其它使用纯神经网络解决图像分割问题的方案相比依然拥有相似或者更高的正确率。
模块分析
一项系统性地评价 CNN 模块的工作已经被发表了。该项工作的发现有利于我们更好地使用 CNN :
- 使用 ELU 函数引入非线性,而不是 batchnorm 或者 ReLU
- 应用学习到的 RGB 颜色空间转换
- 使用线性学习率衰减策略
- 使用平均池化(Average pooling)和最大池化(Max pooling)的和
- 使用 128 或 256 作为小批量(mini-batch)的取值。如果这个数值对于你的 GPU 来说太大了,可以将学习率与批量大小成比例地降低
- 将全连接层转化成卷积形式,并且对最终决定的预测取平均
- 当准备增加训练集规模的时候,首先检查是否还没有达到高原(plateau)
- 数据的清晰程度比数据的数量要重要
- 如果无法增加输入图像的大小,可以尝试减小后续卷积层的步幅(stride),它们具有大致相同的效果
- 如果你的网络架构很复杂并且高度优化,例如 GoogLeNet,请小心改动。
Xception
Xception 通过简单而优雅的方案改进了 Inception 模块和架构,并且它和 ResNet 以及 Inception V4 一样的有效。
Xception 模块图:
鉴于该网络架构的简洁和优雅,它可以成为任何人的最爱,如下图。
该架构有 36 个卷积阶段,这一点与 ResNet-34 很相似。但是该模型的代码与 ResNet 一样简单,并且比 Inception V4 来得更好理解。
- 这里有该模型的 Torch7 实现:
https://gist.github.com/culurciello/554c8e56d3bbaf7c66bf66c6089dc221- 这里是 Keras/TF 的实现版本:
https://keras.io/applications/#xception
有趣的是,最近的 Xception 架构也受到了我们在可分离卷积滤波器上的工作的启发。
其它值得注意的架构
FractalNet 使用了递归的架构,它并没有在 ImageNet 上做过测试,算是 ResNet 的衍生或者更通用的 ResNet 。
未来
我们认为制定神经网络架构对于深度学习领域的发展至关重要。我们团队强烈建议您仔细阅读并理解本文中提到的所有论文。
但是也许有人会有疑问,为什么我们不得不花费很多时间来制定架构?为什么我们不用数据来告诉我们要使用什么以及如何组合各个模块?有这些疑问是很好的,但现在与这些有关的研究正在进行当中。这里有一些初步的有趣结果。
还要注意,在这里我们主要谈论了计算机视觉的架构。但是在其它领域也有类似的神经网络架构正在被研发,并且研究所有其它任务的架构演进过程也是非常有趣的。
如果你对神经网络架构和计算性能之间的对比感兴趣,请参阅我们最近的论文。
致谢
本文的灵感来源于我们在普渡大学 e-Lab 实验室与 Abhishek Chaurasia, Adam Paszke, Sangpil Kim, Alfredo Canziani 等人的一次讨论。