PyTorch手写数字识别实战:从环境配置到CNN模型实现

引言:开启深度学习之旅

        手写数字识别是计算机视觉领域的"Hello World",也是理解深度学习核心概念的最佳起点。本文将带您使用PyTorch框架,在Anaconda环境中实现一个强大的手写数字识别系统。通过Jupyter Notebook的交互式体验,您将从零开始构建神经网络模型,并见证AI如何学会识别数字。

一、环境配置:Anaconda+PyTorch GPU环境搭建

1. 安装Anaconda

前往Anaconda官网下载并安装适合您操作系统的版本

==> 看我出的Anaconda教学 <==

2. Anaconda Prompt中创建虚拟环境

conda create -n pytorch27 python=3.9
conda activate pytorch27

3. 安装PyTorch 2.7版本及相关库

==> 看我出的PyTorch的GPU环境安装教程 <==

4. 安装Jupyter Notebook

可以直接使用pip下载

pip install jupyter notebook

5. 下载python所需的内核

pip install ipykernel

6. 在Jupyter中注册内核

python -m ipykernel install --user --name=myenv --display-name="ipykernel_name"

`--user` —— 表示安装时针对当前用户;

`--name` —— 指定了内核的名称,应与你创建Conda的虚拟环境名称一致;

`--displey-name="ipykernel_name"` —— 设置在Jupyter Notebook的中显示的内核名称

7. 修改Jupyter Notebook启动默认路径

1)找到Jupyter Notebook快捷方式

2)右键快捷方式,点击属性

3)找到目标里的引号内容,将引号内容改为你自己喜欢的路径

7. 启动Jupyter Notebook

jupyter notebook

8. 验证安装

右键新建一个Notebook,右上角选择你创建的内核,在Jupyter Notebook中运行:

import torch
print(f"PyTorch版本: {torch.__version__}")
print(f"GPU可用: {torch.cuda.is_available()}")
print(f"设备名称: {torch.cuda.get_device_name(0)}")

显示以下内容就证明GPU环境配置成功啦!!!

二、数据准备:MNIST数据集揭秘

数据集介绍

MNIST包含70,000张28x28像素的手写数字灰度图像:

  • 60,000张训练图像

  • 10,000张测试图像

  • 10个类别(0-9)

加载与预处理

import torch
import torchvision
from torchvision import transforms
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt

# 定义数据预处理
transform = transforms.Compose([
    transforms.ToTensor(),  # 转为Tensor,并归一化到[0,1]
    transforms.Normalize((0.1307,), (0.3081,))  # MNIST均值和标准差
])

# 加载数据集
train_dataset = torchvision.datasets.MNIST(
    root='./data', train=True, download=True, transform=transform
)
test_dataset = torchvision.datasets.MNIST(
    root='./data', train=False, download=True, transform=transform
)

# 创建DataLoader
batch_size = 64
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)

可视化样本数据

# 可视化样本
def show_images(images, labels, n=6):
    plt.figure(figsize=(10, 5))
    for i in range(n):
        plt.subplot(2, 3, i+1)
        plt.imshow(images[i].squeeze(), cmap='gray')
        plt.title(f"Label: {labels[i]}")
        plt.axis('off')
    plt.tight_layout()
    plt.show()

# 获取一批数据
images, labels = next(iter(train_loader))
show_images(images, labels)

三、模型构建:从全连接到卷积神经网络

1. 全连接神经网络(FCN)

import torch.nn as nn

class NeuralNetwork(nn.Module):
    def __init__(self):
        super(NeuralNetwork, self).__init__()
        self.flatten = nn.Flatten()
        self.layers = nn.Sequential(
            nn.Linear(28*28, 400),  # 输入层784 -> 隐藏层400
            nn.ReLU(),
            nn.Linear(400, 200),    # 隐藏层400 -> 200
            nn.ReLU(),
            nn.Linear(200, 100),    # 隐藏层200 -> 100
            nn.ReLU(),
            nn.Linear(100, 10)      # 隐藏层100 -> 输出层10
        )
    
    def forward(self, x):
        x = self.flatten(x)
        return self.layers(x)

# 实例化模型(CPU)
model = NeuralNetwork()
print(model)

若使用的是GPU,实例化模型如下所示

# 实例化模型并移至GPU
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = NeuralNetwork().to(device)
print(model)

2. 卷积神经网络(CNN) - 更强大的选择

这里我是用的是GPU实例化

class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv_layers = nn.Sequential(
            # 卷积层1: 输入1通道, 输出32通道, 3x3卷积核
            nn.Conv2d(1, 32, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2),  # 池化后尺寸14x14
            
            # 卷积层2: 输入32通道, 输出64通道
            nn.Conv2d(32, 64, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2)   # 池化后尺寸7x7
        )
        self.fc_layers = nn.Sequential(
            nn.Linear(64 * 7 * 7, 128),
            nn.ReLU(),
            nn.Dropout(0.5),  # 添加Dropout防止过拟合
            nn.Linear(128, 10)
        )
    
    def forward(self, x):
        x = self.conv_layers(x)
        x = x.view(x.size(0), -1)  # 展平
        return self.fc_layers(x)

# 实例化CNN模型
model_cnn = CNN().to(device)
print(model_cnn)

# 使用Adam优化器
optimizer_cnn = optim.Adam(model_cnn.parameters(), lr=0.001)

四、模型训练:让AI学会识别数字

1. 训练准备

import torch.optim as optim

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)

# 训练函数
def train(model, train_loader, criterion, optimizer, epochs=10):
    model.train()
    train_losses = []
    
    for epoch in range(epochs):
        running_loss = 0.0
        for images, labels in train_loader:
            # 数据移至GPU
            images, labels = images.to(device), labels.to(device)
            
            optimizer.zero_grad()
            outputs = model(images)
            loss = criterion(outputs, labels)
            loss.backward()
            optimizer.step()
            running_loss += loss.item()
        
        epoch_loss = running_loss/len(train_loader)
        train_losses.append(epoch_loss)
        print(f"Epoch {epoch+1}/{epochs}, Loss: {epoch_loss:.4f}")
    
    # 绘制损失曲线
    plt.plot(train_losses)
    plt.title('Training Loss')
    plt.xlabel('Epoch')
    plt.ylabel('Loss')
    plt.show()

# 测试函数
def test(model, test_loader):
    model.eval()
    correct = 0
    total = 0
    
    with torch.no_grad():
        for images, labels in test_loader:
            images, labels = images.to(device), labels.to(device)
            outputs = model(images)
            _, predicted = torch.max(outputs.data, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    
    accuracy = 100 * correct / total
    print(f"测试集准确率: {accuracy:.2f}%")
    return accuracy

2. 训练全连接网络

# 训练并测试
train(model, train_loader, criterion, optimizer, epochs=10)
fc_accuracy = test(model, test_loader)

3. 训练卷积神经网络

# 训练CNN模型
train(model_cnn, train_loader, criterion, optimizer_cnn, epochs=10)
cnn_accuracy = test(model_cnn, test_loader)

4. 模型对比

# 模型性能对比
print("\n=== 模型性能对比 ===")
print(f"全连接网络准确率: {fc_accuracy:.2f}%")
print(f"卷积神经网络准确率: {cnn_accuracy:.2f}%")

五、结果分析:CNN为何更强大?

性能对比

模型类型测试准确率训练时间参数量
全连接网络~97%较短~300K
卷积神经网络~99%较长~1.2M

CNN优势解析

  1. 局部感知:卷积核专注于局部特征

  2. 参数共享:相同卷积核检测不同位置特征

  3. 空间不变性:池化操作保持特征不变

  4. 层次结构:底层识别边缘,高层识别复杂模式

可视化预测结果

def visualize_predictions(model, test_loader, n=12):
    model.eval()
    images, labels = next(iter(test_loader))
    images, labels = images.to(device), labels.to(device)
    
    with torch.no_grad():
        outputs = model(images[:n])
        _, preds = torch.max(outputs, 1)
    
    plt.figure(figsize=(12, 6))
    for i in range(n):
        plt.subplot(3, 4, i+1)
        plt.imshow(images[i].cpu().squeeze(), cmap='gray')
        plt.title(f"预测: {preds[i].item()}\n真实: {labels[i].item()}")
        plt.axis('off')
    
    plt.tight_layout()
    plt.show()

# 可视化CNN预测结果
visualize_predictions(model_cnn, test_loader)

六、性能优化技巧

1. 学习率调度

scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.1)

2. 数据增强:

transform_train = transforms.Compose([
    transforms.RandomRotation(10),
    transforms.RandomAffine(0, scale=(0.9, 1.1)),
    transforms.ToTensor(),
    transforms.Normalize((0.1307,), (0.3081,))
])

3. 早停法

best_accuracy = 0
for epoch in range(epochs):
    # 训练代码...
    current_accuracy = test(model, test_loader)
    
    if current_accuracy > best_accuracy:
        best_accuracy = current_accuracy
        torch.save(model.state_dict(), 'best_model.pth')

七、常见问题解答

Q: 为什么我的模型准确率停滞不前?
A: 尝试:

  1. 增加模型复杂度

  2. 调整学习率(尝试0.001-0.0001)

  3. 增加训练轮数

  4. 添加更多数据增强

Q: 如何提高推理速度?
A: 可考虑:

  1. 量化模型:torch.quantization.quantize_dynamic

  2. 使用更轻量级网络(如MobileNet)

  3. 启用半精度训练

Q: 遇到内存不足错误怎么办?
A:

  1. 减小batch size

  2. 使用梯度累积

  3. 启用混合精度训练

八、结语:从数字识别到现实应用

通过本教程,您已经实现了:

  1. PyTorch环境配置

  2. MNIST数据加载与预处理

  3. 全连接网络构建与训练

  4. CNN模型实现与优化

  5. 模型评估与结果可视化

手写数字识别只是计算机视觉的起点,这些技术可扩展到:

  • 人脸识别系统

  • 医学影像分析

  • 自动驾驶感知

  • 工业质检

        到此,整一个PyTorch手写数字识别实战:从环境配置到CNN模型实现就完成啦!!!感谢大家支持!!!ovO

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值