Keras深度学习——构建 CNN 模型识别 MNIST 手写数字

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情

任务与模型分析

卷积神经网络(Convolutional Neural Network, CNN)基础中,我们了解了传统神经网络的问题以及 CNN 的工作原理。在本节中,我们将构建 CNN 模型用来识别 MNIST 手写数字。我们采用的以下策略构建 CNN 模型:

  • 输入形状为 28 x 28 x 1,使用的卷积核尺寸为 3 x 3 x 1
    • 需要注意的是,卷积核的大小可以更改,但是通道数不能更改,需要与输入通道数相同
    • 使用 10 个卷积核
  • 输入图像经过卷积层后,使用池化层:
    • 输出的图像尺寸减半
    • 展平池化后获得的输出
  • 展平层连接到一个具有 1000 个单位的隐藏层
  • 最后,将隐藏层连接到输出层,输出层中有 10 类(包括数字 0-9 )

建立模型后,我们使用所有标签为 1 的图像生成均值图像,并平移 1 个像素,然后在平移后的图像上测试 CNN 模型的性能;在第 1 节中,我们已经知道,全连接神经网络无法争取预测该均值图像的类别。

CNN 模型构建与训练

接下来,使用 Keras 实现上述定义的 CNN 架构,以了解如何在 MNIST数据上使用 CNN 模型。

  1. 加载并预处理数据:
from keras.layers import Dense,Conv2D,MaxPool2D,Flatten
from keras.models import Sequential
from keras.datasets import mnist
from keras.utils import np_utils
import numpy as np

(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(x_train.shape[0], x_train.shape[1], x_train.shape[1], 1)
x_test = x_test.reshape(x_test.shape[0], x_test.shape[1], x_test.shape[1], 1)
x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.
y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)
num_classes = y_test.shape[1]
复制代码

预处理步骤与我们在《构建深度前馈神经网络》中使用的方法完全相同。

  1. 建立并编译模型:
model = Sequential()
model.add(Conv2D(10, (3, 3), input_shape=(28, 28, 1), activation='relu'))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(512, activation='relu'))
model.add(Dense(num_classes, activation='softmax'))
model.summary()

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['acc'])
复制代码

可以获取我们在前面的代码中初始化的模型的简要架构信息:

model.summary()
复制代码

输出该模型的简要架构信息如下:

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 26, 26, 10)        100       
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 13, 13, 10)        0         
_________________________________________________________________
flatten (Flatten)            (None, 1690)              0         
_________________________________________________________________
dense (Dense)                (None, 512)               865792    
_________________________________________________________________
dense_1 (Dense)              (None, 10)                5130      
=================================================================
Total params: 871,022
Trainable params: 871,022
Non-trainable params: 0
_________________________________________________________________
复制代码

卷积层中总共有 100 个参数,因为卷积层中有 103 x 3 x 1 的卷积核,因此总共有 90 个权重参数和 10 个偏置项(每个卷积核中 1 个),共 100 个参数。最大池化层没有任何参数,因为它只需要计算每个大小为 2 x 2 的池化核中的最大值。可以看到使用 CNN 模型可以大幅降低网络参数量。

  1. 最后,拟合模型:
model.fit(x_train, y_train,
            validation_data=(x_test, y_test),
            epochs=10,
            batch_size=1024,
            verbose=1)
复制代码

以上模型在 10epoch 训练后,可以达到 98% 的准确率:

模型训练过程监测

  1. 接下来,使用所有标签为 1 的图像生成均值图像,并平移 1 个像素:
# 获取标签为1的所有图像输入
x_test1 = x_test[y_test[:, 1]==1]
# 利用所有标签为1的图像生成均值图像
pic = np.zeros((x_test.shape[1], x_test.shape[2]))
pic2 = np.copy(pic)
for i in range(x_test1.shape[0]):
    pic2 = x_test1[i, :, :, 0]
pic = pic + pic2
pic = (pic / x_test1.shape[0])
# 将均值图像中的每个像素向左平移一个像素
for i in range(pic.shape[0]):
    if i < 21:
        pic[:, i] = pic[:, i+1]
# 对平移后的图像进行预测
p = model.predict(pic.reshape(1, x_test.shape[1], x_test.shape[2], 1))
print(p)
c = np.argmax(p)
print('CNN预测结果:', c)
复制代码

得到的模型输出结果如下所示:

扫描二维码关注公众号,回复: 14218464 查看本文章
[[1.3430370e-05 9.9989212e-01 2.0535077e-05 2.6301734e-07 4.3278211e-05
  5.9122913e-06 1.5874346e-05 6.2533190e-06 2.0079199e-06 4.1732173e-07]]
CNN预测结果: 1
复制代码

看以看到,与深度前馈神经网络模型的情况相比,使用 CNN 架构得到的预测结果能够以更大的输出概率将平移后的图像预测为 1

相关链接

卷积神经网络基本概念详解

使用 Keras 构建卷积神经网络

猜你喜欢

转载自juejin.im/post/7103728382965186573