TensorFlow MNIST 手写数字识别

首页 留言系统 文章 联系我们 友情链接

TensorFlow MNIST 手写数字识别教程

本教程将详细介绍如何使用TensorFlow构建和训练一个神经网络模型来识别手写数字。我们将使用经典的MNIST数据集,这是机器学习领域的"Hello World"。

项目概述

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%以上的准确率。您可以将这个基础模型扩展到更复杂的图像识别任务中。

返回文章列表