使用 Keras 和 MNIST 构建简单的数字分类神经网络
目录
- 数字分类神经网络简介
- 了解 MNIST 数据集
- 环境设置
- 加载和探索 MNIST 数据集
- 数据预处理:重塑和独热编码
- 使用 Keras 构建神经网络模型
- 编译模型:损失函数和优化器
- 训练模型:拟合和验证
- 评估模型:准确率和预测
- 可视化神经网络结构
- 优化训练:利用 GPU
- 结论
数字分类神经网络简介
神经网络彻底改变了机器解读和分析数据的方式,特别是在图像识别领域。数字分类的目标是准确识别手写数字,是初学者掌握神经网络基础的典型例子。通过利用流行的库如 Keras 和数据集如 MNIST,构建一个有效的数字分类器变得既容易又具有教育意义。
了解 MNIST 数据集
MNIST(修改后的国家标准与技术研究院)数据集是机器学习社区的基石。它包含70,000张手写数字(0-9)的灰度图像,每张图像的尺寸为28×28像素。数据集分为60,000张训练图像和10,000张测试图像,非常适合用于训练和验证机器学习模型。
MNIST 的主要特征:
- 大小:70,000张图像(60k训练,10k测试)
- 图像尺寸:28×28像素
- 类别:10类(数字0到9)
- 灰度:每个像素值范围从0(黑色)到255(白色)
环境设置
在深入模型构建过程之前,设置开发环境是至关重要的。确保已安装 Python,并考虑使用 Anaconda 等环境来无缝管理包和依赖项。
所需库:
- NumPy:用于数值运算
- Matplotlib:用于数据可视化
- Keras:用于构建和训练神经网络
- Scikit-learn:用于预处理工具
- Pandas:用于数据操作
安装命令:
1 |
pip install numpy matplotlib keras scikit-learn pandas |
加载和探索 MNIST 数据集
Keras 通过其 datasets
模块简化了访问 MNIST 数据集的过程。以下是如何加载和检查数据:
1 2 3 4 5 6 7 8 9 |
import numpy as np import matplotlib.pyplot as plt from keras.datasets import mnist # 加载 MNIST 手写数字数据 (X_train, y_train), (X_test, y_test) = mnist.load_data() print(X_train.shape) # 输出: (60000, 28, 28) print(X_test.shape) # 输出: (10000, 28, 28) |
输出:
1 2 |
(60000, 28, 28) (10000, 28, 28) |
这表明有60,000张训练图像和10,000张测试图像,每张图像的尺寸为28×28像素。
可视化样本图像
为了更好地了解数据,让我们可视化一张样本图像:
1 2 3 4 |
img = X_train[250].reshape(28,28) plt.imshow(img, cmap="gray") plt.title(f"Sample Digit Label: {y_train[250]}") plt.show() |
输出:

注意:实际图像将显示与标签对应的手写数字。
数据预处理:重塑和独热编码
数据预处理是机器学习工作流程中的关键步骤。对于神经网络,适当地格式化数据和编码标签是必不可少的。
重塑数据
神经网络需要特定形状的输入数据。对于 MNIST 数据集,我们将28×28像素的图像展平成包含784个元素的一维数组。
1 2 3 4 5 |
from keras.utils import to_categorical # 重塑和归一化图像数据 X_train = X_train.reshape(60000, 28, 28).astype('float32') / 255 X_test = X_test.reshape(10000, 28, 28).astype('float32') / 255 |
标签的独热编码
独热编码将分类标签转换为二进制矩阵,这更适合于训练。
1 2 3 4 5 6 |
# 对标签进行独热编码 y_train = to_categorical(y_train, num_classes=10) y_test = to_categorical(y_test, num_classes=10) print(y_train.shape) # 输出: (60000, 10) print(y_test.shape) # 输出: (10000, 10) |
输出:
1 2 |
(60000, 10) (10000, 10) |
这表明每个标签现在表示为10维二进制向量。
使用 Keras 构建神经网络模型
Keras 提供了一个用户友好的 API 来构建和训练神经网络。我们将构建一个简单的 Sequential 模型,包含多个全连接层。
模型架构
以下是模型结构的高级概述:
- Flatten 层:将二维图像数据转换为一维数组。
- 全连接层 1:100 个神经元,使用 sigmoid 激活函数。
- 全连接层 2:144 个神经元,使用 sigmoid 激活函数。
- 输出层:10 个神经元(每个数字一个),使用 softmax 激活函数。
层解释
- Flatten 层:将输入数据从二维矩阵(28×28)转换为一维向量(784),以输入到全连接层。
- 全连接层:这些是完全连接的层,每个神经元接收来自前一层所有神经元的输入。激活函数引入非线性:
- Sigmoid 激活:输出值在0到1之间,适用于二分类问题,但在多分类问题的隐藏层中较少使用。
- Softmax 激活:将最终层的输出转换为10个类别的概率分布。
构建模型:
1 2 3 4 5 6 7 8 9 |
from keras.models import Sequential from keras.layers import Dense, Flatten # 创建一个简单的神经网络模型 model = Sequential() model.add(Flatten(input_shape=(28,28))) model.add(Dense(100, activation='sigmoid')) model.add(Dense(144, activation='sigmoid')) model.add(Dense(10, activation='softmax')) |
模型摘要
可视化模型结构和参数:
1 |
model.summary() |
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Model: "sequential_1" _______________________________________________________________ Layer (type) Output Shape Param # ============================================================== flatten_1 (Flatten) (None, 784) 0 _______________________________________________________________ dense_3 (Dense) (None, 100) 78500 _______________________________________________________________ dense_4 (Dense) (None, 144) 14444 _______________________________________________________________ dense_5 (Dense) (None, 10) 1450 ============================================================== Total params: 94,494 Trainable params: 94,494 Non-trainable params: 0 _______________________________________________________________ |
该摘要提供了每层的输出形状以及需要训练的参数数量的见解。
编译模型:损失函数和优化器
在训练之前,需要使用指定的损失函数和优化器来编译模型。
- 损失函数:衡量模型的预测与实际标签的匹配程度。
- 类别交叉熵:适用于多分类问题。
- 优化器:更新模型的权重以最小化损失函数。
- Adam 优化器:一种高效的随机梯度下降方法,能够自适应调整学习率。
编译模型:
1 |
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['acc']) |
训练模型:拟合和验证
训练包括向模型提供数据并允许其通过多个周期学习模式。
- 周期(Epochs):整个数据集通过网络的次数。
- 验证数据:用于在每个周期后评估模型在未见过的数据上的性能。
训练过程:
1 |
history = model.fit(X_train, y_train, epochs=10, validation_data=(X_test, y_test)) |
示例输出:
1 2 3 4 5 |
Epoch 1/10 1875/1875 [==============================] - 4s 2ms/step - loss: 0.9009 - acc: 0.7596 - val_loss: 0.3685 - val_acc: 0.8892 ... Epoch 10/10 1875/1875 [==============================] - 4s 2ms/step - loss: 0.2251 - acc: 0.9314 - val_loss: 0.2267 - val_acc: 0.9303 |
经过10个周期后,模型在训练集和验证集上分别达到大约93% 的准确率,表明模型性能良好。
评估模型:准确率和预测
在训练之后,评估模型的性能并对新数据进行预测是至关重要的。
进行预测
1 2 |
# 对测试集进行预测 predictions = model.predict(X_test) |
每个预测包含对10个类别的概率分布。要确定预测的类别:
1 2 3 4 5 |
import numpy as np # 将概率转换为类别标签 predicted_classes = np.argmax(predictions, axis=1) true_classes = np.argmax(y_test, axis=1) |
可视化预测结果
让我们可视化一些测试图像及其预测和真实标签:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import matplotlib.pyplot as plt def plot_prediction(index): img = X_test[index].reshape(28,28) plt.imshow(img, cmap="gray") plt.title(f"True Label: {true_classes[index]} | Predicted: {predicted_classes[index]}") plt.show() # 绘制第一张测试图像 plot_prediction(0) # 绘制另一个样本 plot_prediction(25) |
输出:
显示带有标题的图像,指示真实标签和模型的预测。
模型准确率
模型在验证集上达到了93%的准确率,展示了其在未见过数据上的良好泛化能力。为了提升性能,可以进一步调优和探索更复杂的架构。
可视化神经网络结构
了解神经网络的架构有助于理解数据流动和转换的方式。以下是构建的神经网络的视觉表示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
import matplotlib.pyplot as plt def draw_neural_net(ax, left, right, bottom, top, layer_sizes): ''' 绘制神经网络图。 :param ax: Matplotlib 坐标轴对象 :param left: 左边界 :param right: 右边界 :param bottom: 底部边界 :param top: 顶部边界 :param layer_sizes: 包含每层神经元数的列表 ''' n_layers = len(layer_sizes) v_spacing = (top - bottom)/float(max(layer_sizes)) h_spacing = (right - left)/float(n_layers - 1) # 绘制神经元 for n, layer_size in enumerate(layer_sizes): layer_top = v_spacing*(layer_size - 1)/2. + (top + bottom)/2. for m in range(layer_size): circle = plt.Circle((n*h_spacing + left, layer_top - m*v_spacing), v_spacing/4., color='w', ec='k', zorder=4) ax.add_artist(circle) # 绘制连接线 for n, (layer_size_a, layer_size_b) in enumerate(zip(layer_sizes[:-1], layer_sizes[1:])): layer_top_a = v_spacing*(layer_size_a - 1)/2. + (top + bottom)/2. layer_top_b = v_spacing*(layer_size_b - 1)/2. + (top + bottom)/2. for m in range(layer_size_a): for o in range(layer_size_b): line = plt.Line2D([n*h_spacing + left, (n + 1)*h_spacing + left], [layer_top_a - m*v_spacing, layer_top_b - o*v_spacing], c='k') ax.add_artist(line) # 绘制神经网络 fig = plt.figure(figsize=(12, 12)) ax = fig.gca() ax.axis('off') draw_neural_net(ax, .1, .9, .1, .9, [784, 100, 144, 10]) plt.show() |
输出:

此图展示了从输入神经元(784)通过隐藏层到输出神经元(10)的数据流动。
优化训练:利用 GPU
训练神经网络,尤其是深度神经网络,可能在计算上非常密集且耗时。利用图形处理单元(GPU)可以显著加快训练过程。以下是如何使用 Keras 利用 GPU:
- 确保 GPU 兼容性:
- 安装 NVIDIA CUDA 工具包和 cuDNN。
- 验证您的 GPU 是否与 TensorFlow(Keras 的后端)兼容。
- 安装支持 GPU 的 TensorFlow:
1pip install tensorflow-gpu
- 配置 TensorFlow 以使用 GPU:
TensorFlow 会自动检测并使用 GPU。然而,如果需要,可以明确指定 GPU 设置。
12345678910import tensorflow as tfgpus = tf.config.list_physical_devices('GPU')if gpus:try:# 限制 TensorFlow 仅使用第一个 GPUtf.config.set_visible_devices(gpus[0], 'GPU')tf.config.experimental.set_memory_growth(gpus[0], True)except RuntimeError as e:print(e)
使用 GPU 的好处:
- 并行处理:GPU 可以同时处理多个计算,适合神经网络中的矩阵运算。
- 更快的训练速度:模型训练显著更快,允许更多的实验和更快的迭代。
注意:优化 GPU 使用可能需要根据具体系统设置进行额外配置。
结论
使用 Keras 和 MNIST 数据集构建一个简单的数字分类神经网络是机器学习和深度学习世界的绝佳入门。通过遵循本指南,您已经学习了如何:
- 理解并预处理 MNIST 数据集。
- 使用 Keras 构建神经网络模型。
- 训练和评估模型的性能。
- 可视化网络架构。
- 利用 GPU 优化训练。
尽管讨论的模型达到了可观的准确率,但仍有很大的改进空间。探索更复杂的架构、尝试不同的激活函数或实施正则化技术都可以提升性能。随着您继续机器学习的旅程,建立在这些基础之上将使您能够应对更复杂和有影响力的项目。
编码愉快!