项目概述
MNIST数据集包含70,000张28x28像素的手写数字灰度图像,其中60,000张用于训练,10,000张用于测试。我们的目标是构建一个神经网络模型,能够准确识别这些手写数字(0-9)。
步骤 1: 导入必要的库
首先导入所需的Python库,并配置TensorFlow日志级别以减少输出干扰。
# 导入必要的库
import os
# 设置TensorFlow日志级别,减少输出干扰
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import font_manager # 用于中文字体配置
步骤 2: 中文字体配置
配置Matplotlib以支持中文显示,确保图表中的中文标签能够正确显示。
def configure_matplotlib_for_chinese():
"""
配置 Matplotlib 以支持中文显示。
它会尝试寻找系统中可用的中文字体并进行设置。
"""
# 定义常见中文字体列表
font_names = ['SimHei', 'Heiti TC', 'Microsoft YaHei', 'PingFang SC']
# 获取系统中的所有字体
font_list = font_manager.findSystemFonts()
found_font = None
for font_name in font_names:
for font_path in font_list:
if font_name.replace(' ', '').lower() in font_path.lower():
found_font = font_path
break
if found_font:
break
if found_font:
# 如果找到了字体,就设置为全局字体
plt.rcParams['font.family'] = ['sans-serif']
plt.rcParams['font.sans-serif'] = [font_manager.FontProperties(fname=found_font).get_name()]
plt.rcParams['axes.unicode_minus'] = False
print(f"中文字体设置成功,使用字体: {found_font}")
else:
print("警告: 未找到指定的中文字体。中文可能无法正常显示。")
# 调用配置函数
configure_matplotlib_for_chinese()
步骤 3: 加载 MNIST 数据集
加载经典的MNIST数据集,包含60,000张训练图像和10,000张测试图像。
# 加载 MNIST 数据集
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
# 探索数据形状
print(f"训练图片集的形状: {x_train.shape}")
print(f"训练标签集的形状: {y_train.shape}")
步骤 4: 探索数据
查看数据集的基本信息,包括图像形状、像素值范围,并可视化一些样本。
# 显示第一张图片
plt.imshow(x_train[0], cmap='gray_r')
plt.title(f"第一张图片的标签是: {y_train[0]}")
plt.show()
# 查看像素值范围
print(f"像素值的最大值: {np.max(x_train[0])}")
print(f"像素值的最小值: {np.min(x_train[0])}")
步骤 5: 数据预处理
将像素值从0-255归一化到0-1范围,这有助于提高模型的训练效果和收敛速度。
# 数据归一化
x_train_normalized = x_train / 255.0
x_test_normalized = x_test / 255.0
# 验证归一化结果
print("\n--- 数据归一化后 ---")
print(f"归一化后像素值的最大值: {np.max(x_train_normalized[0])}")
print(f"归一化后像素值的最小值: {np.min(x_train_normalized[0])}")
构建神经网络模型
我们将构建一个包含输入层、隐藏层和输出层的神经网络模型。这个模型将学习如何从28x28像素的图像中识别出手写数字。
输入
784个神经元
隐藏
128个神经元
输出
10个神经元
# 构建模型
model = tf.keras.models.Sequential([
# Flatten层:将28x28图像压平为784个像素的一维数组
tf.keras.layers.Flatten(input_shape=(28, 28)),
# Dense层(全连接层):128个神经元,使用ReLU激活函数
tf.keras.layers.Dense(128, activation='relu'),
# Dropout层:防止过拟合,随机忽略20%的神经元
tf.keras.layers.Dropout(0.2),
# 输出层:10个神经元(对应0-9数字),使用Softmax激活函数
tf.keras.layers.Dense(10, activation='softmax')
])
编译和训练模型
配置模型的优化器、损失函数和评估指标,然后使用训练数据训练模型。
# 编译模型
model.compile(
optimizer='adam', # 自适应学习率优化器
loss='sparse_categorical_crossentropy', # 损失函数
metrics=['accuracy'] # 评估指标
)
# 打印模型结构
model.summary()
# 训练模型
history = model.fit(
x_train_normalized, # 训练数据
y_train, # 训练标签
epochs=5, # 训练轮次
validation_split=0.2 # 验证集比例
)
评估模型性能
使用测试集评估训练好的模型性能,查看模型在未见过的数据上的表现。
# 评估模型
print("\n--- 在测试集上评估模型 ---")
test_loss, test_accuracy = model.evaluate(x_test_normalized, y_test, verbose=2)
print(f"测试集准确率: {test_accuracy * 100:.2f}%")
~98%
训练准确率
~97%
测试准确率
5
训练轮次
使用模型进行预测
使用训练好的模型对新的手写数字图像进行预测,验证模型的识别能力。
# 使用模型进行预测
predictions = model.predict(np.expand_dims(x_test_normalized[0], axis=0))
# 预测结果是一个包含10个概率值的列表
print(f"\n对第一张测试图片的预测概率分布: \n{predictions}")
# 获取预测结果
predicted_label = np.argmax(predictions)
print(f"模型预测的数字是: {predicted_label}")
# 显示图片验证预测结果
plt.imshow(x_test[0], cmap='gray_r')
plt.title(f"真实标签是: {y_test[0]}")
plt.show()
通过这个教程,您已经学会了如何使用TensorFlow构建和训练一个手写数字识别模型。这个简单的神经网络模型在MNIST数据集上可以达到97%以上的准确率。您可以将这个基础模型扩展到更复杂的图像识别任务中。