Pytroch实现minist手写数字识别(全链接模型)


前言

希望接下来能好好研究深度学习的相关知识

一、代码及运行结果

1.引入库

import torch
import numpy as np
from matplotlib import pyplot as plt
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision import datasets
import torch.nn.functional as F

2.数据集

网址:Mnist数据集

训练集、训练集标签

3.数据加载

# 定义数据转换,将图像转换为张量
transformation = transforms.Compose([
    transforms.ToTensor(),
])

# 创建训练数据集对象,指定数据存储路径、训练标志、数据转换和下载标志
train_ds = datasets.MNIST(
    r'./raw',
    train=True,
    transform=transformation,
    download=True
)

# 创建测试数据集对象,指定数据存储路径、训练标志、数据转换和下载标志
test_ds = datasets.MNIST(
    r'./raw',
    train=False,
    transform=transformation,
    download=True
)

# 创建训练数据加载器,指定训练数据集和批量大小,启用数据打乱
train_dl = torch.utils.data.DataLoader(train_ds, batch_size=64, shuffle=True)

# 创建测试数据加载器,指定测试数据集和批量大小
test_dl = torch.utils.data.DataLoader(test_ds, batch_size=256)

# 从训练数据加载器中获取一个批次的图像和标签
imgs, labels = next(iter(train_dl))

代码解析

  1. transforms.Compose 创建了一个数据转换对象,将图像转换为张量的形式。
  2. datasets.MNIST 创建了训练和测试数据集的对象,指定了数据存储路径、训练标志、数据转换和下载标志。
  3. torch.utils.data.DataLoader
    创建了训练和测试数据的加载器,指定了数据集和批量大小。在训练数据加载器中,还启用了数据打乱。
  4. next(iter(train_dl)) 从训练数据加载器中获取一个批次的图像和标签,用于模型训练。
    总结:这段代码是为了加载MNIST数据集,并准备用于模型的训练和测试。

4.构建模型

# 定义神经网络模型类,继承自nn.Module
class Model(nn.Module):
    # 构造函数,定义网络结构的层
    def __init__(self):
        super().__init__()
        # 定义第一层线性层,输入大小为28*28,输出大小为120
        self.liner_1 = nn.Linear(28*28, 120)
        # 定义第二层线性层,输入大小为120,输出大小为84
        self.liner_2 = nn.Linear(120, 84)
        # 定义第三层线性层,输入大小为84,输出大小为10
        self.liner_3 = nn.Linear(84, 10)

    # 定义前向传播函数
    def forward(self, input):
        # 将输入的图像数据展平为一维向量,大小为28*28
        x = input.view(-1, 28*28)
        # 经过第一层线性层,并应用ReLU激活函数
        x = F.relu(self.liner_1(x))
        # 经过第二层线性层,并应用ReLU激活函数
        x = F.relu(self.liner_2(x))
        # 经过第三层线性层,得到最终输出
        x = self.liner_3(x)

代码解析

  1. nn.Module 是PyTorch中所有神经网络模型的基类。
  2. init 构造函数中定义了神经网络的结构,包括三个线性层(全连接层)。
  3. forward 函数定义了前向传播过程,其中图像数据经过线性层和 ReLU激活函数的处理,最终得到模型的输出。
  4. nn.Linear 表示线性层,即全连接层,它定义了一个线性变换。
  5. F.relu 是ReLU激活函数,用于引入非线性特性。

总结:输入图像经过线性层和激活函数的处理,逐渐提取和组合特征,最终得到模型的输出。这个模型的输出大小为10,适用于分类问题,例如MNIST手写数字分类。

5.训练模型

# 定义交叉熵损失函数
loss_fn = torch.nn.CrossEntropyLoss()

# 定义训练函数
def fit(epoch, model, trainloader, testloader):
    correct = 0  # 用于记录训练集正确分类的样本数
    total = 0    # 训练集总样本数
    running_loss = 0  # 用于记录训练过程中的损失

    # 遍历训练集
    for x, y in trainloader:
        y_pred = model(x)  # 模型预测
        loss = loss_fn(y_pred, y)  # 计算损失
        optim.zero_grad()  # 梯度清零
        loss.backward()  # 反向传播
        optim.step()  # 更新权重

        with torch.no_grad():
            y_pred = torch.argmax(y_pred, dim=1)
            correct += (y_pred == y).sum().item()  # 统计正确分类的样本数
            total += y.size(0)  # 统计总样本数
            running_loss += loss.item()  # 累计损失值

    epoch_loss = running_loss / len(trainloader.dataset)  # 计算平均损失
    epoch_acc = correct / total  # 计算训练集准确率

    # 在测试集上进行评估
    test_correct = 0
    test_total = 0
    test_running_loss = 0

    with torch.no_grad():
        for x, y in testloader:
            y_pred = model(x)
            loss = loss_fn(y_pred, y)
            y_pred = torch.argmax(y_pred, dim=1)
            test_correct += (y_pred == y).sum().item()
            test_total += y.size(0)
            test_running_loss += loss.item()

    epoch_test_loss = test_running_loss / len(testloader.dataset)  # 计算测试集平均损失
    epoch_test_acc = test_correct / test_total  # 计算测试集准确率

    # 打印训练和测试的指标信息
    print('epoch: ', epoch,
          'loss: ', round(epoch_loss, 3),
          'accuracy:', round(epoch_acc, 3),
          'test_loss: ', round(epoch_test_loss, 3),
          'test_accuracy:', round(epoch_test_acc, 3)
          )

    return epoch_loss, epoch_acc, epoch_test_loss, epoch_test_acc
    
# 定义优化器,使用Adam优化器,学习率为0.001,优化模型的参数
optim = torch.optim.Adam(model.parameters(), lr=0.001)

# 定义训练的总轮数
epochs = 10

# 用于存储每个epoch的训练和测试指标
train_loss = []
train_acc = []
test_loss = []
test_acc = []

# 循环训练模型,迭代指定的轮数
for epoch in range(epochs):
    # 调用fit函数进行模型训练和评估
    epoch_loss, epoch_acc, epoch_test_loss, epoch_test_acc = fit(epoch,
                                                                 model,
                                                                 train_dl,
                                                                 test_dl)
    
    # 记录训练和测试的损失和准确率
    train_loss.append(epoch_loss)
    train_acc.append(epoch_acc)
    test_loss.append(epoch_test_loss)
    test_acc.append(epoch_test_acc)

代码解析

  1. torch.nn.CrossEntropyLoss() 创建了交叉熵损失函数,适用于多类别分类问题。
  2. fit 函数是训练模型的函数,其中包含了训练和测试过程。
  3. 在训练过程中,通过前向传播得到预测结果,计算损失,进行反向传播更新模型权重。
  4. 记录训练过程中的损失、正确分类的样本数和总样本数,用于计算训练集准确率 。
  5. 在测试集上进行评估,同样记录测试过程中的损失、正确分类的样本数和总样本数,用于计算测试集准确率。
  6. 打印每个epoch的训练和测试指标信息,包括损失和准确率。
  7. torch.optim.Adam 创建了Adam优化器,用于调整模型参数以最小化损失。
  8. epochs 定义了总的训练轮数。每个epoch结束后,将训练和测试的损失、准确率记录到相应的列表中。
  9. 最终得到四个列表 train_loss, train_acc, test_loss,
    test_acc,它们分别记录了每个epoch的训练损失、训练准确率、测试损失和测试准确率。这些列表可用于绘制训练曲线和测试曲线,以便更好地了解模型的性能。
    在这里插入图片描述

二、总结

  1. 上述操作采用全链接模型,未涉及到卷积、池化等,后续会逐步完善。
  2. Transforms.ToTensor的作用:①将数据集转化为一个tensor;②归一化处理
  3. 在pytorch里面图片的表示形式: 【batch, channel, hight, width】
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值