使用 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 加速训练过程。希望这篇博客对你有所帮助!

相关推荐
不去幼儿园1 分钟前
【启发式算法】Dijkstra算法详细介绍(Python)
人工智能·python·算法·机器学习·启发式算法·图搜索算法
McQueen_LT7 分钟前
聊天室Python脚本——ChatGPT,好用
开发语言·python·chatgpt
云卓SKYDROID11 分钟前
无人机投屏技术解码过程详解!
人工智能·5g·音视频·无人机·科普·高科技·云卓科技
zy_destiny18 分钟前
【YOLOv12改进trick】三重注意力TripletAttention引入YOLOv12中,实现遮挡目标检测涨点,含创新点Python代码,方便发论文
网络·人工智能·python·深度学习·yolo·计算机视觉·三重注意力
自由的晚风20 分钟前
深度学习在SSVEP信号分类中的应用分析
人工智能·深度学习·分类
大数据追光猿20 分钟前
【大模型技术】LlamaFactory 的原理解析与应用
人工智能·python·机器学习·docker·语言模型·github·transformer
Start_Present32 分钟前
Pytorch 第七回:卷积神经网络——VGG模型
pytorch·python·神经网络·cnn·分类算法
朴拙数科32 分钟前
1:1精准还原!用Python+Adobe Acrobat DC实现PDF转Word全自动化
python·pdf·word
supermodule33 分钟前
基于flask的一个数据展示网页
后端·python·flask
范哥来了33 分钟前
python文本处理pdfminer库安装与使用
linux·开发语言·python