深度学习实战:基于TensorFlow 2和Keras(原书第2版)
上QQ阅读APP看书,第一时间看更新

4.1 深度卷积神经网络

深度卷积神经网络(Deep Convolutional Neural Network,DCNN)由许多神经网络层组成。卷积层和池化层(即二次采样)这两种不同类型的层通常会交替使用。网络中每个过滤器的深度从左到右增加。最后一级通常由一个或多个全连接层组成。如图4-1所示。

104-01

图4-1 DCNN示例

卷积网络有三个关键的基础概念:局部感受野、共享权重和池化。让我们一起回顾一下。

4.1.1 局部感受野

如果我们要保留图像或其他形式数据的空间信息,则使用像素矩阵表示每个图像会很方便。鉴于此,编码局部结构的一种简单方法是将相邻输入神经元的子矩阵连接到属于下一层的单个隐藏神经元中。单个隐藏的神经元代表一个局部感受野。注意,此操作称为卷积,这是此类网络名称的由来。你可以将卷积视为一个矩阵(称为核)对原矩阵的处理。

当然,我们可以通过重叠子矩阵来编码更多信息。例如,假设每个子矩阵的大小为5×5,并且这些子矩阵与28×28像素的MNIST图像一起使用,则我们将能够在隐藏层中生成24×24的局部感受野神经元。

实际上,在接触到图像边界前,可将子矩阵仅滑动23个位置。在Keras中,核大小就是沿着核或子矩阵的某个边的像素数,而步幅长度是核在卷积的每个步骤中移动的像素数。

让我们定义从一层到另一层的特征图。显然,我们可从每个隐藏层中得到若干个独立学习的特征图。例如,从28×28个输入神经元开始处理MINST图像,然后在下一个隐藏层中生成k个大小为24×24的神经元的特征图(步幅为5×5)。

4.1.2 共享权重和偏差

假设我们想摆脱原始图像中的像素表示,而要获得一种检测某个特征,且独立于其在输入图像中所处位置的能力。一种简单的方法是对隐藏层中的所有神经元使用相同的权重和偏差集。这样,每层将学习到一组位置无关、派生自图像的潜在特征。记住,每层由一组并行的核组成,而每个核仅学习一个特征。

4.1.3 数学示例

一种了解卷积的简单方法是考虑应用于矩阵的滑动窗口函数。在以下示例中,给定输入矩阵I和核K,我们得到卷积输出。将3×3核K(有时称为过滤器或特征检测器)与输入矩阵逐元素相乘,以在输出矩阵中获得一个像元。通过在I上滑动窗口可得到所有其他像元,如图4-2所示。

105-01

图4-2 输入矩阵I和核K产生卷积输出

在示例中,我们决定在触抵I的边界时立即停止滑动窗口(因此输出为3×3)。或者,我们可以选择对输入进行零填充(因此输出为5×5)。该决定与应用的填充选择有关。注意,核深度等于输入深度(通道)。

另一个选择是关于每一步滑动窗口的滑动距离。这被称为步进。较大的步进将生成较少的核应用和较小的输出大小,而较小的步进将生成更多输出并保留更多信息。

过滤器的大小、步进和填充类型是超参数,可以在网络训练期间进行微调。

4.1.4 TensorFlow 2.x中的ConvNets

在TensorFlow 2.x中,如果我们要添加一个具有32个并行特征和3×3过滤器的卷积层,可以这样写:

105-02

这意味着我们在28×28的单输入通道(或输入过滤器)图像上应用3×3卷积,从而得到32个输出通道(或输出过滤器)。

图4-3提供了一个卷积示例。

106-01

图4-3 卷积示例

4.1.5 池化层

假设我们要总结特征图的输出。同样地,我们可以用从单个特征图中生成的输出的空间连续性,并将子矩阵的值聚合为一个单输出值,综合描述与该物理区域关联的“意义”。

1. 最大池化

一种简单而常见的选择是最大池化运算符,它简单地输出该观察区域中的最大激活值。在Keras中,如果要定义大小为2×2的最大池化层,可写成:

106-02

图4-4给出了最大池化操作的示例。

106-03

图4-4 最大池化示例

2. 平均池化

另一个选择是平均池化,它简单地将某区域聚合为该观察区域中激活值的平均值。

注意,Keras实现了大量的池化层,完整的列表可在线获得(https://keras.io/layers/pooling/)。简而言之,所有池化的操作不过是对给定区域的汇总运算。

3. ConvNets小结

到目前为止,我们已经描述了ConvNets的基本概念。CNN对单维的(时间)音频和文本数据、对二维的(高度×宽度)图像数据、对三维的(高度×宽度×时间)视频数据,都应用了卷积和池化操作。对于图像,在输入矩阵上滑动过滤器会生成一个特征图,该特征图提供每个空间位置的过滤器响应。

换句话说,CNN具有多个堆叠的过滤器,这些过滤器学习独立地从其图像位置上识别特定的视觉特征。在网络初始层中,这些视觉特征很简单,而在深层网络中变得越来越复杂。CNN的训练需要为每个过滤器标识正确的值,从而当输入经多个隐藏层时能激活末层的特定神经元,并正确预测值。