Chapter 13. Convolutional Neural Networks

来源:互联网 发布:河北高速网络查询 编辑:程序博客网 时间:2024/06/03 23:44

本篇文章是个人翻译的,如有商业用途,请通知本人谢谢.

Convolutional Layer

CNN最重要的组成部分是卷积层:第一卷积层中的神经元不是连接到输入图像中的每一个像素(就像它们在前面的章节中那样),而是仅仅连接到它们的局部感受野中的像素(参见图13-2)。 进而,第二卷积层中的每个神经元只与位于第一层中的小矩形内的神经元连接。 这种架构允许网络专注于第一隐藏层中的低级特征,然后将其组装成下一隐藏层中的高级特征,等等。 这种层次结构在现实世界的图像中是很常见的,这也是CNN在图像识别方面效果很好的原因之一。


到目前为止,我们所看到的所有多层神经网络都有由一长串神经元组成的层,在输入到神经网络之前我们必须将输入图像压缩成1D。 现在,每个图层都以2D表示,这使得神经元与其相应的输入进行匹配变得更加容易。


位于给定层的第i行第j列的神经元连接到位于前一层中的神经元的输出的第i行到第行,第j列到第列.fh和fw是局部感受野的高度和宽度(见图13-3)。 为了使图层具有与前一图层相同的高度和宽度,通常在输入周围添加零,如图所示。 这被称为零填充.


如图13-4所示,通过将局部感受野隔开,还可以将较大的输入层连接到更小的层。 两个连续的感受野之间的距离被称为步幅。 在图中,一个5×7的输入层(加零填充)连接到一个3×4层,使用3×3的卷积核和一个步幅为2(在这个例子中,步幅在两个方向是相同的,但是它并不一定总是如此)。 位于上层第i行第j列的神经元与位于前一层中的神经元的输出连接的行,第列, Sh和Sw是垂直和水平的步幅。




Filters(卷积核)

神经元的权重可以表示为局部感受野大小的小图像。 例如,图13-5显示了两个可能的权重集,称为flters(或卷积核)。第一个表示为中间有一条垂直的白线的黑色正方形(除了中间一列外,这是一个充满0的7×7矩阵,除了中央垂直线是1)。 使用这些权重的神经元会忽略他们的局部感受野的一切,除了中央垂直线(因为所有的inputs将得到0乘,除位于中央垂直线的)。第二个卷积核是一个黑色的正方形,中间有一条水平的白线。 再一次,使用这些权重的神经元将忽略除了中心水平线之外的局部感受野中的一切。

现在,如果一个图层中的所有神经元都使用相同的垂直线滤波器(以及相同的偏置项),并且将网络输入到图13-5(底部图像)中所示的输入图像,则该图层将输出左上图像。 请注意,垂直的白线得到增强,其余的变得模糊。 类似地,如果所有的神经元都使用水平线滤波器,右上角的图像就是你所得到的。 注意到水平的白线得到增强,其余的则被模糊了。因此,使用相同滤波器的一个充满神经元的图层将为您提供一个特征图,该特征图突出显示图像中与滤波器最相似的区域。 在训练过程中,CNN为其任务找到最有用的过滤器,并学习将它们组合成更复杂的模式(例如,交叉是图像中垂直过滤器和水平过滤器都活动的区域)。


Stacking Multiple Feature Maps(叠加的多个特征图)


到目前为止,为了简单起见,我们已经将每个卷积层表示为一个薄的二维层,但是实际上它是由几个相同大小的特征图组成的,所以它在3D中被更精确地表示(见图13-6)。 在一个特征映射中,所有神经元共享相同的参数(权值共享)(权重和偏置),但是不同的特征映射可能具有不同的参数。 神经元的感受野与前面描述的相同,但是它延伸到所有先前的层的特征图。 简而言之,卷积层同时对其输入应用多个滤波器,使其能够检测输入中的任何位置的多个特征。

事实上,特征地图中的所有神经元共享相同的参数会显着减少模型中的参数数量,但最重要的是,一旦CNN学会识别一个位置的模式,就可以在任何其他位置识别它。 相比之下,一旦一个常规DNN学会识别一个位置的模式,它只能在该特定位置识别它。

而且,输入图像也由多个子图层组成:每个颜色通道一个。 通常有三种:红色,绿色和蓝色(RGB)。 灰度图像只有一个通道,但是一些图像可能更多 - 例如捕捉额外光频(如红外线)的卫星图像。

具体地,位于给定卷积层L中的特征映射k的i行,j列中的神经元连接到前一层(L-1)位于行,列的神经元的输出.请注意,位于同一行第i列和第j列但位于不同特征映射中的所有神经元都连接到上一层中完全相同神经元的输出。

公式13-1在一个总结前面解释的大的数学公式:它展示了如何计算卷积层中给定神经元的输出。它是计算所有投入的加权总并且加上偏置。



  • 是卷积层(L层)特征映射k中位于第i行第j列的神经元的输出.
  • 如前所述,是垂直和水平的步幅,是感受野的高度和宽度,是前一层(第l - 1层)的特征图的数量。
  • 是位于层L-1,i'行,j'列,特征图k'(或者如果前一层是输入层的通道k')的神经元的输出。
  • 是特征映射k的偏置项(在L层中)。 您可以将其视为调整特征映射k的整体亮度的旋钮。
  • 是层L的特征映射k中的任何神经元与位于行u,列v(相对于神经元的感受野)的输入之间的连接权重,以及特征映射k'。

TensorFlow Implementation (TensorFlow实现)
在张量流中,3D张量的每个输入图像通常被表示为形状。 一个小批量被表示为四维张量的形状。 卷积层的权重表示为形状的四维张量。 卷积层的偏差项简单地表示为一维形状的张量

我们来看一个简单的例子。 下面的代码使用Scikit-Learn的load_sample_images()(加载两个彩色图像,一个华人庙宇,另一个是一朵花)加载两个样本图像。 然后创建两个7×7的卷积核(一个中间是垂直的白线,另一个是水平的白线),并将他们应用到两张图形中,使用TensorFlow的conv2d()函数构建的卷积图层(使用零填充 且步幅为2)。 最后,绘制其中一个结果特征图(类似于图13-5中的右上图)。

from sklearn.datasets import load_sample_imageimport matplotlib.pyplot as pltimport numpy as npimport tensorflow as tfif __name__ == '__main__':    # Load sample images    china = load_sample_image("china.jpg")    flower = load_sample_image("flower.jpg")    dataset = np.array([china, flower], dtype=np.float32)    batch_size, height, width, channels = dataset.shape    # Create 2 filters    filters = np.zeros(shape=(7, 7, channels, 2), dtype=np.float32)    filters[:, 3, :, 0] = 1  # vertical line    filters[3, :, :, 1] = 1  # horizontal line    # Create a graph with input X plus a convolutional layer applying the 2 filters    X = tf.placeholder(tf.float32, shape=(None, height, width, channels))    convolution = tf.nn.conv2d(X, filters, strides=[1,2,2,1], padding="SAME")    with tf.Session() as sess:        output = sess.run(convolution, feed_dict={X: dataset})    plt.imshow(output[0, :, :, 1], cmap="gray") # plot 1st image's 2nd feature map    plt.show()
大部分代码是不言而喻的,但conv2d()行值得解释一下: 
  • X是输入最小批量(4D张量,如前所述)
  • 卷积核是应用的一组卷积核(也是一个4D张量,如前所述)。
  • 步幅是一个四元素的一维数组,其中两个中心元素是垂直和水平的步幅(sh和sw)。 第一个和最后一个元素现在必须等于1.他们可能有一天会被用来指定批量步长(跳过一些实例)和频道步幅(跳过上一层的特征映射或通道)。
  • padding必须是“VALID”或“SAME”:
- 如果设置为“VALID”,卷积层不使用零填充,并且可能会忽略输入图像底部和右侧的某些行和列,具体取决于步幅,如图13-7所示(为简单起见, 这里只显示水平尺寸,当然,垂直尺寸也适用相同的逻辑)
- 如果设置为“SAME”,则卷积层在必要时使用零填充。 在这种情况下,输出神经元的数量等于输入神经元的数量除以该步幅,向上舍入(在这个例子中,ceil(13/5)= 3)。 然后在输入周围尽可能均匀地添加零。

不幸的是,卷积图层有很多超参数:你必须选择卷积核的数量,高度和宽度,步幅和填充类型。 与往常一样,您可以使用交叉验证来查找正确的超参数值,但这非常耗时。 稍后我们将讨论常见的CNN体系结构,以便让您了解超参数值在实践中的最佳工作方式。


Memory Requirements (内存需求)
CNN的另一个问题是卷积层需要大量的RAM,特别是在训练期间,因为反向传播的反向传递需要在正向传递期间计算的所有中间值。
例如,考虑具有5×5滤波器的卷积层,输出200个尺寸为150×100的特征图,步长为1,使用SAME padding。 如果输入是150×100 RGB图像(三个通道),则参数的数量是(5×5×3 + 1)×200 = 15,200(+1对应于偏置项),这跟全连接层比较是相当小的.(具有150×100神经元的全连接层,每个连接到所有150×100×3输入,将具有150 ^ 2×100 ^ 2×3 = 675,000,000个参数!)然而,200个特征图中的每一个包含150×100个神经元,并且这些神经元中的每一个都需要计算其5×5×3 = 75个输入的权重和:总共2.25亿次浮点乘法。不像完全连接的层那么糟糕,但仍然是计算密集型的。 而且,如果使用32位浮点数来表示特征映射,则卷积层的输出将占用RAM的200×150×100×32 = 9600万位(大约11.4MB)。 这只是一个例子! 如果培训批次包含100个实例,则该层将占用超过1 GB的RAM!
在推理过程中(即对新实例进行预测时),一旦下一层计算完毕,一层所占用的RAM就可以被释放,因此只需要两个连续层所需的RAM数量。 但是在训练期间,在正向传递期间计算的所有内容都需要被保留用于反向传递,所以所需的RAM量(至少)是所有层所需的RAM总量。
如果由于内存不足错误导致培训崩溃,则可以尝试减少小批量大小。 或者,您可以尝试使用步幅降低维度,或者删除几个图层。 或者你可以尝试使用16位浮点数而不是32位浮点数。 或者你可以在多个设备上分发CNN。

Pooling Layer (池化层)
一旦你理解了卷积层是如何工作的,池化层很容易掌握。 他们的目标是对输入图像进行二次抽样(即收缩)以减少计算负担,内存使用量和参数数量(从而限制过度拟合的风险)。 减少输入图像的大小也使得神经网络容忍一点点的图像移位(位置不变)。
就像在卷积图层中一样,池化层中的每个神经元都连接到前一层中有限数量的神经元的输出,位于一个小的矩形感受域内。 您必须像以前一样定义其大小,跨度和填充类型。 但是,汇集的神经元没有权重; 它所做的只是使用聚合函数(如最大值或平均值)来聚合输入。 图13-8显示了最大池层,这是最常见的池化类型。 在这个例子中,我们使用一个2×2的内核,步幅为2,没有填充。 请注意,只有每个内核中的最大输入值才会进入下一层。 其他输入被丢弃。

这显然是一个非常具有破坏性的层次:即使只有一个2×2的内核和一个2的步幅,输出在两个方向上都会减小两倍(所以它的面积将减少四倍),一下减少了75%的输入值。
池化层通常独立于每个输入通道工作,因此输出深度与输入深度相同。 接下来可以看到,在这种情况下,图像的空间维度(高度和宽度)保持不变,但是通道数目可以减少。
在TensorFlow中实现一个最大池层是非常容易的。 以下代码使用2×2内核创建最大池化层,跨度为2,没有填充,然后将其应用于数据集中的所有图像:

import numpy as npfrom sklearn.datasets import load_sample_imageimport tensorflow as tfimport matplotlib.pyplot as pltchina = load_sample_image("china.jpg")flower = load_sample_image("flower.jpg")dataset = np.array([china, flower], dtype=np.float32)batch_size, height, width, channels = dataset.shape# Create 2 filtersfilters = np.zeros(shape=(7, 7, channels, 2), dtype=np.float32)filters[:, 3, :, 0] = 1  # vertical linefilters[3, :, :, 1] = 1  # horizontal lineX = tf.placeholder(tf.float32, shape=(None, height, width, channels))max_pool = tf.nn.max_pool(X, ksize=[1,2,2,1], strides=[1,2,2,1],padding="VALID")with tf.Session() as sess:    output = sess.run(max_pool, feed_dict={X: dataset})plt.imshow(output[0].astype(np.uint8))  # plot the output for the 1st imageplt.show()

ksize参数包含沿输入张量的所有四个维度的内核形状:[批量大小,高度,宽度,通道]。 TensorFlow目前不支持在多个实例上合并,因此ksize的第一个元素必须等于1.此外,它不支持在空间维度(高度和宽度)和深度维度上合并,因此ksize [1] 和ksize [2]都必须等于1,否则ksize [3]必须等于1。
要创建一个平均池层,只需使用avg_pool()函数而不是max_pool()。
现在你知道所有的构建模块来创建一个卷积神经网络。 我们来看看如何组装它们。


CNN Architectures

典型的CNN体系结构将一些卷积层(每一个通常跟着一个ReLU层),然后是一个合并层,然后是另外几个卷积层(+ ReLU),然后是另一个池化层,等等。 随着网络的进展,图像变得越来越小,但是由于卷积层的缘故,图像通常也会越来越深(即更多的特征图)(见图13-9)。 在堆栈的顶部,添加由几个完全连接的层(+ ReLU)组成的常规前馈神经网络,并且最终层输出预测(例如,输出估计类别概率的softmax层)。

一个常见的错误是使用太大的卷积内核。 通常可以通过将两个3×3内核堆叠在一起来获得与9×9内核相同的效果,计算量更少。
多年来,这种基础架构的变体已经被开发出来,导致了该领域的惊人进步。 这种进步的一个很好的衡量标准是比赛中的错误率,比如ILSVRC ImageNet的挑战。 在这个比赛中,图像分类的五大误差率在五年内从26%下降到仅仅3%以上。 前五位错误率是系统前5位预测未包含正确答案的测试图像的数量。 图像很大(256像素高),有1000个类,其中一些非常微妙(尝试区分120个品种)。 查看获奖作品的演变是了解CNN如何工作的好方法。
我们先来看看经典的LeNet-5架构(1998年),然后是ILSVRC挑战赛的三名获胜者AlexNet(2012),GoogLeNet(2014)和ResNet(2015)

其他视觉任务
在其他视觉任务中,如物体检测和定位以及图像分割,也取得了惊人的进展。 在物体检测和定位中,神经网络通常输出图像中各种物体周围的一系列边界框。 例如,参见Maxine Oquab等人的2015年论文,该论文为每个客体类别输出热图,或者Russell Stewart等人的2015年论文,该论文结合使用CNN来检测人脸,并使用递归神经网络来输出 围绕它们的一系列边界框。 在图像分割中,网络输出图像(通常与输入大小相同),其中每个像素指示相应输入像素所属的对象的类别。 例如,查看Evan Shelhamer等人的2016年论文。

LeNet-5
LeNet-5架构也许是最广为人知的CNN架构。 如前所述,它是由Yann LeCun于1998年创建的,广泛用于手写数字识别(MNIST)。 它由表13-1所示的层组成。

这里有一些额外的细节要注意:
  • MNIST图像是28×28像素,但是它们被补零到32×32像素,并且在被喂到网络之前被归一化。 网络的其余部分不使用任何填充,这就是为什么随着图像在网络中的进展,大小不断缩小。
  • 平均池化层比平常稍微复杂一些:每个神经元计算输入的平均值,然后将结果乘以一个可学习的系数(每个特征图一个),并添加一个可学习的偏差项(每个特征图一个),然后最后应用激活函数。
  • C3地图中的大多数神经元仅在三个或四个S2地图(而不是全部六个S2地图)中连接到神经元。 有关详细信息,请参阅原始纸张中的表1。
  • 输出层有点特殊:每个神经元不是计算输入和权向量的点积,而是输出其输入向量和其权向量之间的欧几里德距离的平方。 每个输出测量图像属于特定数字类别的多少。 交叉熵损失函数现在是首选,因为它更多地惩罚不好的预测,产生更大的梯度,从而更快地收敛。
Yann LeCun的网站(“LENET”部分)展示了LeNet-5分类数字的很好的演示。

AlexNet 
AlexNet CNN架构赢得了2012年的ImageNet ILSVRC挑战赛:它实现了前5%的17%的错误率,而且后一位错误率有26%! 它由Alex Krizhevsky(因此而得名),Ilya Sutskever和Geoffrey Hinton开发。 它与LeNet-5非常相似,只是更大更深,它是第一个将卷积层直接堆叠在一起,而不是在每个卷积层顶部堆叠一个池化层。 表13-2介绍了这种架构。

为了减少过拟合,作者使用了前面章节中讨论的两种正则化技术:首先他们在训练期间将丢失率(dropout率为50%)应用于层F8和F9的输出。其次,他们通过随机移动训练图像的各种偏移,水平翻转和改变照明条件来执行数据增强。
AlexNet还在层C1和C3的ReLU步骤之后立即使用竞争标准化步骤,称为局部响应标准化。 这种归一化形式使得在相同的位置的神经元被最强烈的激活但是在相邻的特征图中抑制神经元(在生物神经元中观察到了这种竞争激活)。 这鼓励不同的特征映射专业化,推它们分开,并迫使他们探索更广泛的功能,最终提升泛化能力。 公式13-2显示了如何应用LRN。

  • 是位于特征映射i的神经元的标准化输出,在某行u和列v(注意,在这个等式中我们只考虑位于这个行和列的神经元,所以u和v没有显示)。
  • 是在ReLU步骤之后,但在归一化之前的那个神经元的激活。
  • k,α,β和r是超参数。 k称为偏置,r称为深度半径。
  • 是特征图的数量。
例如,如果r = 2且神经元具有强激活,则将抑制位于其上下的特征图中的神经元的激活。
在AlexNet中,超参数设置如下:r = 2,α= 0.00002,β= 0.75,k = 1。这个步骤可以使用TensorFlow的local_response_normalization()操作来实现。
AlexNet的一个名为ZF Net的变体由Matthew Zeiler和Rob Fergus开发,赢得了2013年ILSVRC的挑战。 它基本上是AlexNet的一些调整的超参数(特征映射的数量,内核大小,步幅等)。

GoogLeNet 
GoogLeNet架构是由Christian Szegedy等人开发的。 来自Google Research,通过低于前5名7%的错误率,赢得了ILSVRC 2014的挑战赛。 这个伟大的表现很大程度上来自《盗梦空间》模块,它是比以前CNN更深的网络(见图13-11)。 这是通过称为初始模块的子网络实现的,这使得GoogLeNet比以前的架构更有效地使用参数:实际上,GoogLeNet的参数比AlexNet少了10倍(约600万而不是6000万)。

盗梦空间模块的架构如图13-10所示。
启动模块的架构如图13-10所示。 符号“3×3 + 2(S)”表示该层使用3×3内核,步幅2和相同填充。 输入信号首先被复制并馈送到四个不同的层。 所有卷积层都使用ReLU激活功能。 请注意,第二组卷积层使用不同的内核大小(1×1,3×3和5×5),允许它们以不同的比例捕获图案。 还要注意,每一层都使用1和SAME填充的跨度(即使是最大的池化层),所以它们的输出全都具有与其输入相同的高度和宽度。 这使得有可能连接最终深度连续层中沿着深度维度的所有输出(即,堆叠来自所有四个顶部卷积层的特征映射)。 这个连接层可以在TensorFlow中使用concat()操作实现,其中axis = 3(axis 3是深度)。
您可能想知道为什么初始模块具有1×1内核的卷积层。 当然这些图层不能捕获任何功能,因为他们一次只能看一个像素? 实际上,这些层次有两个目的:
首先,它们被配置为输出比输入少得多的特征图,所以它们作为瓶颈层,意味着它们降低了维度。 在3×3和5×5卷积之前,这是特别有用的,因为这些在计算上是非常耗费内存的层。
简而言之,您可以将整个“盗梦空间”模块视为类固醇卷积层,能够输出捕捉各种尺度复杂模式的特征映射。
每个卷积层的卷积核的数量是一个超参数。 不幸的是,这意味着你有六个超参数来调整你添加的每个初始层。



现在让我们来看看GoogLeNet CNN的架构(见图13-11)。 它非常深,我们不得不将它分成三列,但是GoogLeNet实际上是一个高堆栈,包括九个“盗梦空间”模块(带有旋转顶端的框),每个模块实际上包含三层。 在内核大小之前显示每个卷积层和每个池化层输出的特征映射的数量。 “盗梦空间”模块中的六个数字表示模块中每个卷积层输出的特征映射的数量(与图13-10中的顺序相同)。 请注意,所有的卷积层都使用ReLU激活功能。
让我们来过一遍这个网络:
  • 前两层将图像的高度和宽度除以4(使其面积除以16),以减少计算负担。
  • 然后,局部响应规范化层确保前面的层学习各种各样的功能(如前所述)
  • 接下来是两个卷积层,其中第一个像瓶颈层一样。 正如前面所解释的,你可以把这一对看作是一个单一的更智能的卷积层。
  • 再次,局部响应标准化层确保了先前的层捕捉各种各样的模式。
  • 接下来,最大池化层将图像高度和宽度减少2,再次加快计算速度。
  • 然后是九个“盗梦空间”模块的高堆栈,与几个最大池层交织,以降低维度并加速网络。
  • 接下来,平均池化层使用具有VALID填充的特征映射的大小的内核,输出1×1特征映射:这种令人惊讶的策略被称为全局平均共享。 它有效地强制以前的图层产生特征图,这些特征图实际上是每个目标类的置信图(因为其他类型的功能将被平均步骤破坏)。 这样就不必在CNN的顶部有几个完全连接的层(如AlexNet),大大减少了网络中的参数数量,并限制了过度拟合的风险。
  • 最后一层是不言自明的:正则化drop out,然后是具有softmax激活函数的完全连接层来输出估计类的概率。
这个图略有简化:原来的GoogLeNet架构还包括两个插在第三和第六个启动模块之上的辅助分类器。 它们都由一个平均池层,一个卷积层,两个完全连接的层和一个softmax激活层组成。 在训练期间,他们的损失(缩小了70%)加在了整体损失上。 我们的目标是解决消失梯度问题,规范网络。 但是,结果显示其效果相对较小。

ResNet
最后但并非最不重要的是,2015年ILSVRC挑战赛的赢家Kaiming He等人开发的剩余网络(或ResNet),该网络的打败前5错误率低到3.6%,它使用了一个非常深的CNN,由152层组成。 能够训练如此深的网络的关键是使用跳过连接(也称为快捷连接):喂到一个层的信号也被添加到位于比堆栈高一点的层的输出。 让我们看看为什么这是有用的.
当训练一个神经网络时,目标是使其模拟一个目标函数h(x)。 如果将输入x添加到网络的输出中(即添加跳过连接),那么网络将被迫模拟f(x)= h(x) - x而不是h(x)。 这被称为残留学习(见图13-12)。

当你初始化一个规则的神经网络时,它的权重接近于零,所以网络只输出接近零的值。 如果添加跳过连接,则生成的网络只输出其输入的副本; 换句话说,它最初对身份函数进行建模。 如果目标函数与身份函数非常接近(常常是这种情况),这将大大加快训练速度。
而且,如果添加了许多跳转连接,即使几个层还没有开始学习,网络也可以开始进行(见图13-13)。 由于跳过连接,信号可以很容易地通过整个网络。 深度剩余网络可以看作是一堆剩余单位,其中每个剩余单位是一个有跳过连接的小型神经网络。

现在让我们看看ResNet的架构(见图13-14)。 这实际上是令人惊讶的简单。 它的开始和结束与GoogLeNet完全一样(除了没有dropout层),而在两者之间只是一堆很简单的残余单位。 每个残差单元由两个卷积层组成,使用3×3的内核和保存空间维度(步幅1,SAME填充),批量归一化(BN)和ReLU激活。


需要注意的是特征图的数量每隔几个残差单位会加倍,同时它们的高度和宽度减半(使用步幅2卷积层)。 发生这种情况时,输入不能直接添加到剩余单元的输出中,因为它们不具有相同的形状(例如,此问题影响图13-14中的虚线箭头表示的跳过连接)。 为了解决这个问题,输入通过一个1×1卷积层,步长2和右侧数量的输出特征映射(见图13-15)。


ResNet-34是具有34个层(仅计算卷积层和完全连接层)的ResNet,包含3个剩余单元输出64个特征图,4个剩余单元输出128个特征图,6个剩余单元输出256个特征图,3个剩余单元输出512个特征图
ResNet比ResNet-152更深,使用稍微不同的剩余单位。 他们使用三个卷积层,而不是两个3×3的卷积层(比如说),它们使用三个卷积层:第一个卷积层只有64个特征映射(少4倍),这是一个瓶颈层(已经讨论过) ,然后是具有64个特征图的3×3层,最后是具有256个特征图(4×64)的另一个1×1卷积层,以恢复原始深度。 ResNet-152包含三个这样的RU,输出256个地图,然后是8个RU,512个地图,高达36 RU,1024个地图,最后是3个RU,共2048个地图。
正如你所看到的,这个领域正在迅速发展,每年都会有各种各样的架构出现。 一个明显的趋势是CNN越来越深入。 他们也越来越轻,需要越来越少的参数。 目前,ResNet架构既是最强大的,也是最简单的,所以它现在应该是你应该使用的,但是每年都要继续关注ILSVRC的挑战。 2016年获奖者是来自中国的Trimps-Soushen团队,他们的出错率惊人的缩减到2.99%。 为了达到这个目标,他们训练了以前模型的组合,并将它们合并为一个整体。 根据任务的不同,降低的错误率可能会或可能不值得额外的复杂性。还有其他一些架构可供您参考,特别是VGGNet13(2014年ILSVRC挑战赛的亚军)和Inception-v414(将GoGoLeNet和ResNet的思想融合在一起,实现了接近3%的5大误差 ImageNet分类率)。
实施我们刚刚讨论的各种CNN架构真的没什么特别的。 我们之前看到如何构建所有的独立构建模块,所以现在您只需要组装它们来创建所需的构架。 我们将在即将开始的练习中构建ResNet-34,您将在Jupyter笔记本中找到完整的工作代码。

TensorFlow Convolution Operations
TensorFlow还提供了一些其他类型的卷积层:
  • conv1d()为1D输入创建一个卷积层。 例如,在自然语言处理中这是有用的,其中句子可以表示为一维单词阵列,并且接受场覆盖一些邻近单词。
  • conv3d()创建一个3D输入的卷积层,如3D PET扫描。
  • atrous_conv2d()创建了一个有趣的卷积层(“àtrous”是法语“with holes”)。 这相当于使用具有通过插入行和列(即,孔)而扩大的滤波器的规则卷积层。 例如,等于[[1,2,3]]的1×3滤波器可以以4的扩张率扩张,导致扩张的滤波器[[1,0,0,0,2,0,0,0,3]]。 这使得卷积层在没有计算价格的情况下具有更大的局部感受野,并且不使用额外的参数。
  • conv2d_transpose()创建了一个转置卷积层,有时称为去卷积层,它对图像进行上采样(这个名称是非常具有误导性的,因为这个层并不执行去卷积,这是一个定义良好的数学运算(卷积的逆)) 。这是通过在输入之间插入零来实现的,所以你可以把它看作是一个使用分数步长的规则卷积层。例如,在图像分割中,上采样是有用的:在典型的CNN中,特征映射越来越小当通过网络时,所以如果你想输出一个与输入大小相同的图像,你需要一个上采样层。
  • depthwise_conv2d()创建一个深度卷积层,将每个滤波器独立应用于每个单独的输入通道。 因此,如果有fn滤波器和fn'输入通道,那么这将输出fn×fn'特征映射。
  • separable_conv2d()创建一个可分离的卷积层,首先像深度卷积层一样工作,然后将1×1卷积层应用于结果特征映射。 这使得可以将滤波器应用于任意的输入通道组。















原创粉丝点击