
4.2 DCNN的示例——LeNet
曾经获得图灵奖的Yann LeCun提出了一个名为LeNet的卷积网络系列,该卷积网络经过训练,可以识别MNIST手写字符,对简单的几何变换和变形具有鲁棒性。LeNet的核心思想是使低阶隐藏层交替进行卷积与最大池化操作。卷积操作基于精心选择的局部感受野,并具有针对多个特征图的共享权重。然后,高阶隐藏层基于传统的MLP全连接,并把softmax作为输出层。
4.2.1 TensorFlow 2.0中的LeNet代码
为了在代码中定义LeNet,我们使用卷积2D模块:

其中第一个参数是卷积中输出过滤器的数量,元组是每个过滤器的大小。一个有意思的可选参数是padding
,它有两个选项:padding='valid'
表示仅在输入和过滤器完全重叠且因此输出小于输入的情况下才计算卷积;padding='same'
表示输出与输入大小相同,输入以外的区域用零填充。
注意,
tf.keras.layers.Conv2D
是tf.keras.layers.Convolution2D
的别名,因此两者可以互换使用。见https://www.tensorflow.org/api_docs/python/tf/keras/layers/Conv2D
。
另外,我们使用MaxPooling2D
模块:

其中pool_size=(2,2)
是由两个整数构成的元组,表示图像在垂直和水平方向上的缩小因子。因此,(2, 2)将图像在每个维度上减半,而stride=(2,2)
是步进。
现在,让我们回顾一下代码。导入所需模块:

定义LeNet网络:

我们有了第一个卷积阶段,包括ReLU激活及最大池化。我们的网络将学习20个卷积滤波器,每个滤波器的大小为5×5。输出维度与输入形状相同,因此将为28×28。注意,由于Convolution2D
是整个流程的第一阶段,因此还需要定义其input_shape
。最大池化操作实现了一个滑动窗口,该窗口在隐藏层上滑动,并且在垂直和水平方向上步长为2个像素:

然后是具有ReLU激活的第二个卷积阶段,接着的也是最大池化层。在这种情况下,我们将学习的卷积滤波器的数量从之前的20个增加到50个。增加深层滤波器的数量是深度学习中常用的技术:

然后增加一个非常标准的展开(压平)和一个由500个神经元组成的稠密网络,以及一个具有10个分类的softmax
分类器:

恭喜你,你已经定义了你的第一个深度卷积学习网络!它的可视化如图4-5所示。

图4-5 LeNet的可视化图
现在我们需要一些额外的代码来训练网络,代码与我们在第1章中已经见过的非常相似。这次我们还展示了打印损失的代码:

现在运行代码。如你在图4-6中看到的,耗时显著增加,该深度神经网络的每次迭代花费约28秒,而在第1章中定义的网络仅花费了1~2秒。

图4-6 LeNet准确度
但是,准确度达到了训练集99.991%、验证集99.91%和测试集99.15%的新峰值!
让我们看一下20个epoch的完整执行过程,如图4-7所示。

图4-7 20个epoch后的执行模型
通过输出模型准确度和模型损失的变化,可以发现只需10次迭代训练就能达到近似99.1%的准确度,如图4-8所示。

图4-8 10次迭代后的模型准确度
让我们看一些MNIST图像,以了解99.1%的成绩有多好!例如,人们有很多种书写数字9的方式,图4-9中包含了其中的一种。数字3、7、4和5也如此,但图中的数字1难以识别。

图4-9 MNIST手写字符的示例
在图4-10中,我们总结下目前为止在使用不同的模型下所取得的进展。我们的简单网络的准确度从90.71%开始,这意味着大约100个手写字符中的9个不能被正确识别。然后,我们通过使用深度学习框架,准确度提升了8%,达到了99.2%,这意味着每100个字符中少于一个的手写字符会被错误地识别。

图4-10 不同模型和优化器的准确度
4.2.2 理解深度学习的力量
为了更好地理解深度学习和卷积网络,我们可以运行的另一个测试是减少训练集的大小并观察由此导致的性能下降。一种方法是将50 000个实例的训练集分为两个不同的集:
1)用于训练模型的训练集,它将以5900、3000、1800、600和300的实例数逐渐减小。
2)用于估计模型训练水平的验证集,它将由剩余实例组成。测试集的大小是固定的,它包含10 000个示例。
通过此设置,我们将上面定义的深度学习卷积网络与第1章中定义的第一个神经网络示例进行比较。如图4-11所示,当有更多数据可用时,深度网络总是优于简单网络。当包含5900个训练实例时,深度学习网络的准确度为97.23%,而简单网络的准确度为94%。

图4-11 不同数据量的准确度
通常来说,深度网络需要更多可用的训练数据来充分体现其能力(见图4-11)。
MNIST的最新技术成果(比如,可获得的最高性能)列表可线上查看(http://rodri-gob.github.io/are_we_there_yet/build/classification_datasets_results.html
)。截至2019年3月,最佳成果的错误率为0.21%[2]。