1
Python深度学习实战:手把手教你用Keras搭建CNN识别手写数字

2024-10-21

你好,Python深度学习爱好者们!今天我们要一起来探索一个非常有趣的主题 - 如何用Keras构建卷积神经网络(CNN)来识别手写数字。这个项目不仅能让你对深度学习有更直观的认识,还能帮助你掌握一些实用的技能。那么,让我们开始这段奇妙的旅程吧!

准备工作

在开始之前,我们需要做一些准备工作。首先,确保你已经安装了TensorFlow和Keras。如果还没有安装,可以使用以下命令:

pip install tensorflow

Keras已经集成在TensorFlow中,所以不需要单独安装。

接下来,我们需要导入必要的库:

import tensorflow as tf
from tensorflow.keras import layers, models
import numpy as np
import matplotlib.pyplot as plt

这里我们导入了TensorFlow、Keras的一些模块,以及NumPy和Matplotlib。NumPy用于数据处理,Matplotlib用于可视化。

数据加载与预处理

我们要使用的是MNIST数据集,这是一个经典的手写数字数据集。让我们来加载并预处理数据:

mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()


x_train = x_train.reshape((60000, 28, 28, 1)).astype('float32') / 255
x_test = x_test.reshape((10000, 28, 28, 1)).astype('float32') / 255

这里我们做了两件事: 1. 加载MNIST数据集,它自动分为训练集和测试集。 2. 对数据进行预处理 - 调整形状并将像素值缩放到0-1之间。

你可能会问,为什么要除以255呢?这是因为原始图像的像素值范围是0-255,除以255后就变成了0-1之间的小数,这样可以加速模型的训练过程。

模型构建

现在到了激动人心的时刻 - 构建我们的CNN模型!我们将使用Keras的Sequential API来构建模型:

model = models.Sequential([
    layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
    layers.MaxPooling2D((2, 2)),
    layers.Conv2D(64, (3, 3), activation='relu'),
    layers.MaxPooling2D((2, 2)),
    layers.Conv2D(64, (3, 3), activation='relu'),
    layers.Flatten(),
    layers.Dense(64, activation='relu'),
    layers.Dense(10, activation='softmax')
])

这个模型看起来有点复杂,对吧?别担心,让我们一层一层地解析它:

  1. 第一层是一个卷积层,有32个3x3的卷积核。这一层的作用是提取图像的基本特征,如边缘或简单形状。
  2. 接着是一个最大池化层,它的作用是减少特征图的大小,提高计算效率。
  3. 然后是两个更深的卷积层,它们可以提取更复杂的特征。
  4. Flatten层将2D特征图转换为1D向量。
  5. 最后两层是全连接层,用于最终的分类。

你看,每一层都有它特定的作用,就像一个精密的机器,每个零件都不可或缺。

模型编译

构建完模型后,我们需要编译它:

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

这里我们选择了Adam优化器和稀疏分类交叉熵损失函数。为什么选择这些?Adam是一个自适应学习率的优化器,在实践中表现很好。而稀疏分类交叉熵适用于我们这种多类别分类问题。

模型训练

现在,让我们开始训练模型:

history = model.fit(x_train, y_train, epochs=5, 
                    validation_data=(x_test, y_test))

这里我们训练了5个epoch。你可能会问,为什么只训练5个epoch?这是因为MNIST是一个相对简单的数据集,5个epoch通常就足够了。但是,你可以尝试增加epoch数,看看会有什么变化。

模型评估

训练完成后,我们来评估一下模型的性能:

test_loss, test_acc = model.evaluate(x_test, y_test, verbose=2)
print(f'
Test accuracy: {test_acc}')

你会发现,即使只训练了5个epoch,我们的模型在测试集上的准确率也能达到99%左右!这说明我们的模型学习得很好。

可视化训练过程

为了更直观地了解模型的训练过程,我们可以绘制训练和验证的准确率曲线:

plt.plot(history.history['accuracy'], label='accuracy')
plt.plot(history.history['val_accuracy'], label = 'val_accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.ylim([0.5, 1])
plt.legend(loc='lower right')
plt.show()

通过这个图,你可以清楚地看到模型的学习过程。如果你发现验证准确率在某个点开始下降,而训练准确率继续上升,那可能意味着模型开始过拟合了。

模型预测

最后,让我们用训练好的模型来预测一些图像:

num_test_images = 5
test_images = x_test[:num_test_images]
predictions = model.predict(test_images)


for i in range(num_test_images):
    plt.subplot(1, num_test_images, i+1)
    plt.imshow(test_images[i].reshape(28, 28), cmap='gray')
    plt.title(f"Predicted: {np.argmax(predictions[i])}")
    plt.axis('off')
plt.show()

这段代码会显示5个测试图像,并在每个图像上方显示模型的预测结果。你会发现,模型的预测通常是非常准确的!

总结

恭喜你!你已经成功地构建了一个CNN模型来识别手写数字。让我们回顾一下我们学到了什么:

  1. 如何加载和预处理MNIST数据集
  2. 如何使用Keras构建CNN模型
  3. 如何编译和训练模型
  4. 如何评估模型性能
  5. 如何可视化训练过程
  6. 如何使用模型进行预测

这只是深度学习的冰山一角,但已经足以让你对这个领域有一个初步的了解。你觉得这个过程有趣吗?你有没有想到可以将这个模型应用到其他类似的问题上?

记住,实践是学习的最好方式。我鼓励你尝试修改模型结构,调整参数,或者尝试在其他数据集上应用类似的方法。每一次尝试都会让你对深度学习有更深入的理解。

如果你在实践中遇到任何问题,或者有任何想法想要分享,欢迎在评论区留言。让我们一起在这个激动人心的领域中探索和成长!