3.3 实现卷积神经网络
在第2章中你创建了一个神经网络来识别图片。下面是完整的代码:
为了将这个网络转化为卷积神经网络,我们仅需要在模型定义中使用卷积层。我们还会加入池化层。
为了实现一个卷积层,你将使用tf.keras.layers.Conv2D
类型。这个类型接受以下参数:每一层使用的卷积的数量、卷积的大小、激活函数等。
例如,这是一个卷积层作为一个神经网络的输入层:
在这种情况下,我们希望这一层学习64个卷积。它会随机初始化这些卷积,并会随着时间的推移学习滤波器的值来最佳地匹配输入值到它们的标签。这里(3
,3
)表示滤波器的大小。3×3滤波器是最常用的滤波器,你可以根据需求来改变它,但是你通常会看到轴是奇数的,例如5×5或者7×7,这是由于滤波器移除图像边界像素的方法,之后你就会看到。
参数activation
和input_shape
与之前一样。因为我们在这个例子中使用的是Fashion MNIST,形状仍是28×28。但是值得注意的是,因为Conv2D
层在设计时使用的是彩色图像,我们把第三个维度指定为1,因此输入的形状是28×28×1。彩色图像通常会使用3作为第三个参数,因为它们存储的是R、G和B的值。
这里展示了如何在神经网络中使用池化层。你通常会在卷积层之后马上进行池化:
在图3-4的例子中,我们将图像分成了2×2的池,并选择每个池中的最大值。这个操作可以用于定义池大小的参数。那些就是你可以看到的参数—这里的(2
,2
)指池的大小是2×2。
现在让我们看一下使用CNN的Fashion MNIST数据集的完整代码:
这里有几个值得注意的地方。如前所述,输入图像的形状必须与Conv2D
层所期待的匹配,于是我们把图像更新为28×28×1吗?数据同样不得不据此被重新调整形状。28×28是图像中像素的个数,1是颜色通道的个数。你通常会发现1被用于灰度图像,3被用于彩色图像,因为彩色图像有3个颜色通道(红、绿和蓝),每个数字表示的是对应颜色的强度。
因此,在归一化图像之前,我们需要改变每个数组的形状来添加额外的维度。下面的代码改变了训练数据集,将大小为28×28的60 000张图像(因此是一个60 000×28×28的数组)变为大小为28×28×1的60 000张图像:
我们接下来对测试数据集做同样的事情。
同样值得注意的是,在原始的深度神经网络(DNN)中,在把输入传入第一个Dense
层之前,我们使用的是Flatten
层。我们在这里丢掉了输入层,取而代之的是只指定输入的形状。注意在传入Dense
层之前,在卷积和池化之后,数据会被展平。
像第2章展示的网络一样,在相同的数据上同样使用50个回合来训练该网络,我们可以看到准确率有了很好的提升。之前的例子在50个回合之后,在测试数据上达到了89%的准确率,而这一次会达到99%且只需一半的回合数(24或25个回合)。因此我们可以看到,在神经网络中添加卷积绝对可以提升它分类图像的能力。接下来让我们看一看一张图像在网络中的旅程,这样我们可以稍微理解这样做为什么可以成功。