使用 PyTorch 构建 MNIST 手写数字识别模型

引言

MNIST 数据集是一个经典的机器学习数据集,包含了 70,000 张手写数字图像,其中 60,000 张用于训练,10,000 张用于测试。每张图像都是 28x28 像素的灰度图像,并且已经被居中处理以减少预处理步骤。本文将介绍如何使用 PyTorch 构建一个简单的神经网络来识别 MNIST 数据集中的手写数字。

环境准备

首先确保你已经安装了 PyTorch 库。可以通过以下命令安装:

python 复制代码
pip install torch torchvision
数据加载与预处理
导入必要的库
python 复制代码
import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets
from torchvision.transforms import ToTensor
下载训练数据集
python 复制代码
training_data = datasets.MNIST(
    root="data",
    train=True,
    download=True,
    transform=ToTensor()
)
下载测试数据集
python 复制代码
test_data = datasets.MNIST(
    root="data",
    train=False,
    download=True,
    transform=ToTensor()
)

解释:

  • 使用 datasets.MNIST 下载 MNIST 数据集,并将其保存在 "data" 目录下。
  • train=True 表示下载训练集,train=False 表示下载测试集。
  • download=True 表示如果数据集不存在,则下载数据集。
  • transform=ToTensor() 将图像数据转换为 PyTorch 张量。
  1. 展示部分手写数字图像

    python 复制代码
    from matplotlib import pyplot as plt
    
    figure = plt.figure()
    for i in range(9):
        img, label = training_data[i + 59000]
        figure.add_subplot(3, 3, i + 1)
        plt.title(label)
        plt.axis("off")
        plt.imshow(img.squeeze(), cmap="gray")
    plt.show()

    解释:

    • 使用 matplotlib 库展示一些手写数字图像。
数据加载器
创建数据加载器
python 复制代码
train_dataloader = DataLoader(training_data, batch_size=64)
test_dataloader = DataLoader(test_data, batch_size=64)

解释:

  • 使用 DataLoader 将数据打包成批次,batch_size=64 表示每次迭代返回 64 个样本。
检查数据形状
python 复制代码
for X, y in test_dataloader:
    print(f"Shape of X [N,C,H,W]: {X.shape}")
    print(f"Shape of y: {y.shape} {y.dtype}")
    break

解释:

  • 查看数据的形状,确保数据已经被正确打包。
模型定义
定义神经网络模型
python 复制代码
class NeuralNetwork(nn.Module):
    def __init__(self):
        super().__init__()
        self.flatten = nn.Flatten()
        self.hidden1 = nn.Linear(28 * 28, 128)
        self.hidden2 = nn.Linear(128, 256)
        self.hidden3 = nn.Linear(256, 128)
        self.hidden4 = nn.Linear(128, 256)
        self.hidden5 = nn.Linear(256, 128)
        self.out = nn.Linear(128, 10)

    def forward(self, x):
        x = self.flatten(x)
        x = self.hidden1(x)
        x = torch.sigmoid(x)
        x = self.hidden2(x)
        x = torch.sigmoid(x)
        x = self.hidden3(x)
        x = torch.sigmoid(x)
        x = self.hidden4(x)
        x = torch.sigmoid(x)
        x = self.hidden5(x)
        x = torch.sigmoid(x)
        x = self.out(x)
        return x

解释:

  • 定义一个简单的多层感知器模型。
  • 使用 nn.Flatten 展平输入图像。
  • 多个全连接层 (nn.Linear) 和激活函数 (torch.sigmoid)。
实例化模型并移动到 GPU
python 复制代码
device = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else 'cpu'
print(f"Using {device} device")

model = NeuralNetwork().to(device)
print(model)

解释:

  • 检查是否有可用的 GPU 并将模型移动到 GPU 上。
训练与测试
定义损失函数和优化器
python 复制代码
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
定义训练函数
python 复制代码
def train(dataloader, model, loss_fn, optimizer):
    model.train()
    batch_size_num = 1
    for X, y in dataloader:
        X, y = X.to(device), y.to(device)
        pred = model(X)
        loss = loss_fn(pred, y)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        loss_value = loss.item()
        if batch_size_num % 100 == 0:
            print(f"loss: {loss_value:>7f} [number: {batch_size_num}]")
        batch_size_num += 1

解释:

  • 训练模型并计算损失。
  • 使用梯度下降更新权重。
  1. 定义测试函数

    python 复制代码
    def test(dataloader, model, loss_fn):
        size = len(dataloader.dataset)
        num_batches = len(dataloader)
        model.eval()
        test_loss, correct = 0, 0
        with torch.no_grad():
            for X, y in dataloader:
                X, y = X.to(device), y.to(device)
                pred = model(X)
                test_loss += loss_fn(pred, y).item()
                correct += (pred.argmax(1) == y).type(torch.float).sum().item()
            test_loss /= num_batches
            correct /= size
            print(f"Test result: \n Accuracy: {(100 * correct):>0.1f}%, Avg loss: {test_loss:>8f}")

    解释:

    • 测试模型并计算准确率和平均损失。
训练和测试模型
python 复制代码
epochs = 10
for t in range(epochs):
    print(f"Epoch {t + 1}\n--------------------------")
    train(train_dataloader, model, loss_fn, optimizer)
print("Done!")
test(test_dataloader, model, loss_fn)

解释:

  • 进行多次训练周期(epoch)。
  • 最后测试模型。
结果








总结

通过上述步骤,我们构建了一个简单的神经网络模型来识别 MNIST 数据集中的手写数字。使用 PyTorch 可以轻松地处理数据、定义模型、训练和测试模型。这个项目不仅展示了如何使用 PyTorch 进行图像识别,还介绍了如何利用 GPU 加速训练过程。希望这篇博客对你有所帮助!

相关推荐
DavidSoCool几秒前
Spring AI Alibaba ReactAgent 调用Tool 实现多轮对话
java·人工智能·spring·多轮对话·reactagent
Tassel_YUE1 分钟前
小米 MiMo 百万亿 Token 活动怎么申请?逐步填写指南 + 高额度申请思路
人工智能·ai
imbackneverdie3 分钟前
分享我读博时常用的几款科研绘图软件
人工智能·信息可视化·ai作画·科研绘图·博士·ai工具·科研工具
2301_781571423 分钟前
JavaScript中Object-getOwnPropertySymbols获取方法
jvm·数据库·python
zzzzzz31017 分钟前
深度解析 AgentMemory:让 AI 编码助手拥有「永久记忆」的工程实践
人工智能
大模型推理20 分钟前
Nano-vLLM 源码解读 - 2. Sequence 状态机与请求生命周期
人工智能
cxr82824 分钟前
从多目标定义到闭环实验验证的系统工程
人工智能·智能体·逆向合成·材料设计合成
刀法如飞29 分钟前
Rust数组去重的20种实现方式,AI时代用不同思路解决问题
人工智能·算法·ai编程
code_pgf31 分钟前
OpenClaw的tools与skills详解
人工智能
user803952795254332 分钟前
Codex 新人上手——从需求到上线的完整工作流
人工智能