pytroch实现mnist手写数字识别实验

pytroch实现mnist手写数字识别实验

  1. 导入必要的库:torch、torch.nn、torch.optim、torchvision.datasets、torchvision.transforms、torch.utils.data.DataLoader
  2. 定义超参数:
    o batch_size:每个训练批次的样本数
    o num_epochs:训练的总轮数
    o learning_rate:学习率
    o dropout_rate:Dropout层的丢弃率
  3. 数据加载和预处理:
    o 定义数据增强和预处理的转换方法,如transforms.RandomHorizontalFlip()、transforms.RandomRotation()、transforms.ToTensor()等
    o 加载MNIST训练集和测试集,应用数据转换
  4. 创建数据加载器:
    o 创建训练集和测试集的数据加载器,将数据分为批次加载
  5. 定义全连接神经网络模型:
    o 创建一个继承自torch.nn.Module的类,定义模型的结构和前向传播过程。
    o 可以选择合适的激活函数、隐藏层神经元数量等
  6. 将模型移动到设备上:
    o 检查是否有可用的GPU,若有,则将模型和数据加载到GPU上进行运算
  7. 定义损失函数和优化器:
    o 定义损失函数,常用的是交叉熵损失函数torch.nn.CrossEntropyLoss()
    o 定义优化器,常用的是Adam优化器torch.optim.Adam()
  8. 训练模型:
    o 进行num_epochs次的训练循环
    o 在每个epoch中,遍历训练集中的每个批次,进行前向传播、计算损失、反向传播和优化模型的参数
    o 在每个epoch结束后,在测试集上评估模型的性能,计算准确率等指标
    o运行结果
    运行结果
    o 绘制Loss和ACC图:

    在这里插入图片描述
  9. 实验总结:
    o 分析不同参数配置对模型性能的影响,如Batch Size、Epoch、学习率、优化器等
    1.Batch Size: 较小的Batch Size可以加速训练过程,但可能导致模型收敛较慢,较大的Batch Size可以加快收敛速度,但可能会增加内存占用和计算负担。一般而言,较小的Batch Size可用于小型数据集,较大的Batch Size适用于大型数据集。
    2.Epoch:较小的Epoch数可能无法充分训练模型,导致欠拟合。较大的Epoch数可能会过拟合模型,导致对训练集过度拟合。在验证集上的性能不再提高或出现过拟合时,可提前停止训练,避免不必要的计算开销。
    3.学习率:较小的学习率可能导致收敛速度较慢。较大的学习率可能导致训练过程不稳定或错过最优解。可以使用学习率调度器(如torch.optim.lr_scheduler)来动态调整学习率,如学习率衰减或按需调整。
    4.优化器: Adam优化器通常适用于大多数情况,具有自适应学习率机制。SGD优化器可能需要更仔细的参数调整,如动量、学习率衰减等,对模型性能的影响较敏感。
    o 观察采用数据增强、Dropout等方法对模型性能的影响
    1.数据增强:通过数据增强方法(如镜像翻转、随机旋转、平移等)扩充训练集,可以增加模型的泛化能力,提供更多的样本变化,帮助模型更好地学习对不同输入变化的鲁棒性。
  10. Dropout: Dropout层在训练过程中随机丢弃部分神经元,减少过拟合现象。Dropout的丢弃率需要根据具体情况进行选择,通常在0.5左右。
    o 总结实验过程中遇到的问题和解决方法,以及对模型的改进方向
    1.过拟合:如果模型在训练集上的准确率很高,但在测试集上表现较差,可能出现过拟合现象。这时可以通过增加训练集的大小、采用数据增强方法、添加正则化项、使用Dropout等方法来降低过拟合。
  11. 超参数调整:不同的超参数配置可能对模型性能有不同的影响,需要进行调试和优化。可以通过网格搜索、随机搜索、学习曲线分析等方法来选择合适的超参数组合。
    实验完整代码:
import torchvision.datasets as datasets

# 下载并加载训练集
train_dataset = datasets.MNIST(root='../data/', train=True, download=True)

# 下载并加载测试集
test_dataset = datasets.MNIST(root='../data/', train=False, download=True)

# 其他代码...
import numpy as np
import torch
# 导入 pytorch 内置的 mnist 数据
from torchvision.datasets import mnist
# import torchvision
# 导入预处理模块-+
import torchvision.transforms as transforms
from torch.utils.data import DataLoader
# 导入nn及优化器
import torch.nn.functional as F
import torch.optim as optim
from torch import nn
# from torch.utils.tensorboard import SummaryWriter

# 定义一些超参数
train_batch_size = 8
test_batch_size = 8
learning_rate = 0.01
num_epoches = 20

# 定义预处理函数
transform = transforms.Compose([transforms.ToTensor(),
                                transforms.Normalize([0.5],
                                                     [0.5])])
#使用数据增强
# transform = transforms.Compose([
#     transforms.RandomRotation(10),  # 随机旋转10度
#     transforms.RandomHorizontalFlip(),  # 随机水平翻转
#     transforms.ToTensor(),
#     transforms.Normalize([0.5], [0.5])
# ])
# 下载数据,并对数据进行预处理
train_dataset = mnist.MNIST('../data/',
                            train=True,
                            transform=transform,
                            download=False)
test_dataset = mnist.MNIST('../data/',
                           train=False,
                           transform=transform)
# 得到一个生成器
train_loader = DataLoader(train_dataset,
                          batch_size=train_batch_size,
                          shuffle=True)
test_loader = DataLoader(test_dataset,
                         batch_size=test_batch_size,
                         shuffle=False)


class Net(nn.Module):
    """
    使用sequential构建网络,Sequential()函数的功能是将网络的层组合到一起
    """

    def __init__(self, in_dim, n_hidden_1, n_hidden_2, out_dim):
        super(Net, self).__init__()
        self.flatten = nn.Flatten()
        self.layer1 = nn.Sequential(nn.Linear(in_dim, n_hidden_1), nn.BatchNorm1d(n_hidden_1))
        self.layer2 = nn.Sequential(nn.Linear(n_hidden_1, n_hidden_2), nn.BatchNorm1d(n_hidden_2))
        self.out = nn.Sequential(nn.Linear(n_hidden_2, out_dim))

    def forward(self, x):
        x = self.flatten(x)
        x = F.relu(self.layer1(x))
        x = F.relu(self.layer2(x))
        x = F.softmax(self.out(x), dim=1)
        return x

lr = 0.01
momentum = 0.9

# 实例化模型
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model = Net(28 * 28, 300, 100, 10)
model.to(device)

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

# 开始训练
losses = []
acces = []
eval_losses = []
eval_acces = []
for epoch in range(num_epoches):
    train_loss = 0
    train_acc = 0
    model.train()
    # 动态修改参数学习率
    if epoch % 5 == 0:
        optimizer.param_groups[0]['lr'] *= 0.9
        print("学习率:{:.6f}".format(optimizer.param_groups[0]['lr']))

    for img, label in train_loader:
        img = img.to(device)
        label = label.to(device)
        # 正向传播
        out = model(img)
        loss = criterion(out, label)
        # 反向传播
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        # 记录误差
        train_loss += loss.item()
        # 计算分类的准确率
        _, pred = out.max(1)
        num_correct = (pred == label).sum().item()
        acc = num_correct / img.shape[0]
        train_acc += acc

    losses.append(train_loss / len(train_loader))
    acces.append(train_acc / len(train_loader))

    # 在测试集上检验效果
    eval_loss = 0
    eval_acc = 0
    # net.eval() # 将模型改为预测模式
    model.eval()
    for img, label in test_loader:
        img = img.to(device)
        label = label.to(device)
        img = img.view(img.size(0), -1)
        out = model(img)
        loss = criterion(out, label)
        # 记录误差
        eval_loss += loss.item()
        # 记录准确率
        _, pred = out.max(1)
        num_correct = (pred == label).sum().item()
        acc = num_correct / img.shape[0]
        eval_acc += acc

    eval_losses.append(eval_loss / len(test_loader))
    eval_acces.append(eval_acc / len(test_loader))
    print('epoch: {}, Train Loss: {:.4f}, Train Acc: {:.4f}, Test Loss: {:.4f}, Test Acc: {:.4f}'
          .format(epoch, train_loss / len(train_loader), train_acc / len(train_loader),
                  eval_loss / len(test_loader), eval_acc / len(test_loader)))
import matplotlib.pyplot as plt

# 绘制损失图表
plt.plot(losses, label='Train Loss')
plt.plot(eval_losses, label='Test Loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.title('Training and Testing Loss')
plt.legend()
plt.show()

# 绘制准确率图表
plt.plot(acces, label='Train Accuracy')
plt.plot(eval_acces, label='Test Accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.title('Training and Testing Accuracy')
plt.legend()
plt.show()
  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wangzaojun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值