在卷积网络基本原理的基础上,本节用基于MNIST数据集的例子来展示一下CNN是如何逐层进行学习的。MNIST数据集是Yann Lecun构建的一个研究深度学习的手写数字数据集。MNIST数据集由70000张不同人手写的0~9十个数字的灰度图组成,0~9这10个数字展示如图5.6所示。
图5.6 MNIST数据集
若是从特征角度来看这些数字图片,如数字1和7的图片中存在着大量的垂直边缘特征,对于卷积网络来说,检测并识别出它们非常容易。图5.7所示是MNIST数据集中数字8的像素点分布。
图5.7 MNIST数据集中数字8的像素点分布
下面就基于Keras来搭建一个多层CNN模型对MNIST图像识别过程进行可视化展示,来看看每一层卷积到底都“学”到了什么。Keras是TensorFlow的一个高级API,可以方便我们快速地进行深度学习实验。
基本做法如下:首先对输入图像进行shape重塑,然后添加第一层卷积,接着紧跟着一层池化,之后添加第二层卷积,最后是两层全连接层。这是很常规的CNN架构,Keras网络搭建如代码5.1所示。
Keras CNN模型结构和参数数量如图5.8所示。
对该模型执行编译和训练,如代码5.2所示。
图5.8 Keras CNN模型结构和参数数量
做10次循环迭代计算,如图5.9所示。
图5.9 Keras CNN模型训练过程
从图5.9中可以看出,10轮训练后的模型准确率达到了0.9955,可以说是一个相当高的准确率了。下面就来看一下输入图像经过第一层卷积和第二层卷积之后结果的可视化展示。
首先定义一个绘制卷积层输出结果的绘图函数,以卷积核的平方根数量为绘图的格点,即
绘制一个 的图矩阵;然后对卷积层输出结果进行遍历绘图,采用最近邻插值法,颜色映射为binary,如代码5.3所示。
首先把模型的第一层卷积的相关层找出来,模型输入就是网络的第一层,第一层卷积就是模型的第二层,如代码5.4所示。
输出结果如下。
然后通过Keras提供的后端函数定义第一层卷积的输出结果函数,传入输入和输出,如代码5.5所示。
输出结果如下。
这里取一张图片作为展示示例,第一层卷积后图像输出结果大小为24*24*16,符合之前对于模型第一层卷积结构的定义。
最后执行前面定义的卷积层绘图函数,第一层卷积后的可视化结果如图5.10所示。
可以看到,MNIST数据集经过一层卷积之后可视化的结果就已经相当清晰了,足以达到识别的效果,能够看出是“9”这个数字。按照同样的方法,对第二层卷积进行同样的展示,第二层卷积后的可视化结果如图5.11所示。
图5.10 第一层卷积后的可视化结果
图5.11 第二层卷积后的可视化结果
从可视化结果来看,相较于第一层卷积后的结果,经过第二层卷积之后,卷积可视化展示出的结果反而不如第一层卷积后那样清晰,这似乎并不是我们期待的结果,CNN图像学习不应该是经过多层卷积特征提取之后,可视化结果越来越清晰吗?实际上,这个结果与本节之前的阐述并不冲突。一方面,MNIST图像数据特征过于简单,一层卷积就足以提取出全部数字特征,可能并不足以展现图像特征学习的层次特点;另一方面,CNN图像分类是一个不断提取语义信息,也就是提取图像类别信息的过程,这也是分类任务为什么要使用全连接层对卷积层输出进行聚合的原因。对CNN可视化感兴趣的读者可以更换更加复杂的数据进行尝试,看看是否能够展现CNN图像学习的特征层级。
尝试使用CIFAR-10数据集来复现本讲所展示的CNN可视化过程。