首页 > 其他分享 >Pytorch搭建MyNet实现MNIST手写数字识别

Pytorch搭建MyNet实现MNIST手写数字识别

时间:2024-06-19 22:24:01浏览次数:28  
标签:plt torch device Pytorch train test MyNet model MNIST

视频:https://www.bilibili.com/video/BV1Wf421B74f/?spm_id_from=333.880.my_history.page.click

1.1 Model类

import torch
import torch.nn as nn


# 改进的三层神经网络
class MyNet(nn.Module):
    def __init__(self):
        super().__init__()
        # 定义全连接层
        self.fc1 = nn.Linear(28 * 28, 256)  # 输入层 输入是28*28的灰度图像,输出是256个神经元
        self.fc2 = nn.Linear(256, 128)  # 第二层,全连接层,输入256个神经元,输出128个神经元
        self.fc3 = nn.Linear(128, 64)  # 第三层,全连接层,输入128个神经元,输出64个神经元
        self.fc4 = nn.Linear(64, 10)  # 第四层,全连接层,输入64个神经元,输出10个类别

    def forward(self, x):
        x = torch.flatten(x, start_dim=1)  # 展平数据,方便进行全连接
        x = torch.relu(self.fc1(x))  # 第一层+ReLU激活
        x = torch.relu(self.fc2(x))  # 第二层+ReLU激活
        x = torch.relu(self.fc3(x))  # 第三层+ReLU激活
        x = self.fc4(x)  # 第四层 输出层 不需要激活函数
        return x

2 train.py创建

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
from .model import MyNet

# 设置随机种子
torch.manual_seed(21)

# 检查是否有可用的GPU
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"Using device:{device}")

transform = transforms.Compose([
    transforms.ToTensor(),  # 将图像转为张量
    transforms.Normalize((0.5,), (0.5,))  # 标准化图像数据,对于灰度图像,只需要一个通道的标准化
])

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

# 创建数据加载器
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)

# 初始化模型并将模型移到GPU上
model = MyNet().to(device)

# 定义损失函数和优化器
lr = 0.001  # 学习率为0.001
criterion = nn.CrossEntropyLoss()  # 交叉熵
optimizer = optim.Adam(model.parameters(), lr=lr)  # 使用Adam优化器

# 保存训练过程中的损失和准确率
train_losses = []
train_accuracies = []
test_accuracies = []

epochs = 10
best_accuracy = 0.0  # 记录最佳验证集准确率
best_model_path = 'best_mnist_model.pth'

# 训练10个epoch
for epoch in range(epochs):
    running_loss = 0.0
    corrct_train = 0  # 正确预测的数量
    total_train = 0  # 样本总数

    # 训练过程
    model.train()  # 设定模型为训练模式
    for inputs, labels in train_loader:
        inputs, labels = inputs.to(device), labels.to(device)  # 将数据移动到GPU上
        optimizer.zero_grad()  # 梯度清零
        outputs = model(inputs)  # 前向传播
        loss = criterion(outputs, labels)  # 计算损失
        loss.backward()  # 反向传播
        optimizer.step()  # 更新参数
        running_loss += loss.item()  # 累加损失

        # 计算训练集上的准确率
        _, predicted = torch.max(outputs, 1)  # 获取预测结果
        total_train += labels.size(0)  # 累加样本数量
        corrct_train += (predicted == labels).sum().item()  # 累加正确预测的数量

    # 计算训练集上的准确率
    train_accuracy = corrct_train / total_train
    train_losses.append(running_loss / len(train_loader))  # 记录每个 epoch 的平均损失,len(train_loader)为批次数,一个epoch结束后
    train_accuracies.append(train_accuracy)  # 记录每个 epoch 的训练集准确率
    print(
        f"Epoch: {epoch + 1}/{epochs}, Loss: {running_loss / len(train_loader):.4f}, Train Accuracy: {train_accuracy:.2%}")

    # 在测试集上评估模型
    model.eval()  # 设定模型为评估模式
    correct = 0  # 正确的预测数量
    total = 0  # 样本总数

    with torch.no_grad():  # 关闭梯度计算
        for inputs, labels in test_loader:
            inputs, labels = inputs.to(device), labels.to(device)  # 将数据移动到GPU上
            outputs = model(inputs)  # 前向传播
            _, predicted = torch.max(outputs, 1)  # 获取预测结果
            total += labels.size(0)  # 累加样本数量
            correct += (predicted == labels).sum().item()  # 累加正确预测的数量

    # 计算测试集上的准确率
    test_accuracy = correct / total  # 记录每个 epoch 的测试集准确率
    test_accuracies.append(test_accuracy)
    print(f"Epoch: {epoch + 1}/{epochs},Test Accuracy: {test_accuracy:.2%}")

    # 如果测试集准确率提高,保存当前模型的权重
    if test_accuracy > best_accuracy:
        best_accuracy = test_accuracy
        torch.save(model.state_dict(), best_model_path)
        print(f"Best model saved with accuracy: {best_accuracy:.2%}")

print(f"Best Accuracy on test set: {best_accuracy:.2%}")

# 绘制并保存损失和准确率曲线
plt.figure(figsize=(12, 5))

# 绘制损失曲线
plt.subplot(1, 2, 1)  # 选择第一个子图
plt.plot(train_losses, label='Training Loss')  # 传入数据、设置标签为Training Loss
plt.xlabel('Epoch')  # x轴数据
plt.ylabel('Loss')
plt.title('Training Loss over Epochs')  # 设置标题
plt.legend()  # 添加图例
plt.grid(True)  # 添加网格

# 绘制训练集和测试集准确率曲线
plt.subplot(1, 2, 2)
plt.plot(train_accuracies, label='Train Accuracy')
plt.plot(test_accuracies, label='Test Accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.title('Train and Test Accuracy over Epochs')
plt.legend()
plt.grid(True)

# 保存图像
plt.tight_layout()
plt.savefig('loss_and_accuracy.png')
plt.show()

3 predict.py 创建

import torch
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
from .model import MyNet

# 设置随机种子
torch.manual_seed(21)

# 检查是否有可用的GPU
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"Using device:{device}")

# 定义数据预处理
transform = transforms.Compose([
    transforms.ToTensor(),  # 将图像转为张量
    transforms.Normalize((0.5,), (0.5,))  # 标准化图像数据,对于灰度图像,只需要一个通道的标准化
])

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

# 创建数据加载器
batch_size = 10
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)

# 初始化模型并将模型移到GPU上
model = MyNet().to(device)

# 加载保存的权重
best_model_path = 'best_mnist_model.pth'
model.load_state_dict(torch.load(best_model_path))

# 设置模型为评估模式
model.eval()

# 从测试集中取10张图片
examples = enumerate(test_loader)  # 从 test loader 中获取一个带索引的迭代器
# #使用 next()函数从迭代器中获取下一个批次的数据。
# next()返回一个元组,第一个元素是批次的索引(batch idx),
# #第二个元素是一个包含输入数据和目标标签的元组(example_data,example_targets)
batch_idx, (example_data, example_targets) = next(examples)
# 将数据移动到指定的设备上(例如,CPU或GPU),
# 以便利用设备的计算能力进行进一步的操作(如模型推理或训练)
example_data, example_targets = example_data.to(device), example_targets.to(device)

# 进行推理
with torch.no_grad():  # 使用 torch.no_grad()上下文管理器,表示在此上下文中不计算梯度。
    outputs = model(example_data)  # 使用模型对 example_data 进行前向传播,获取输出结果。
    # 使用 torch.max()函数,获取 outputs 张量中每行的最大值及其索引。
    # 1 表示在第一个维度上(通常是类别维度)寻找最大值。
    _, predicted = torch.max(outputs, 1)

# 可视化并显示预测结果
fig, axes = plt.subplots(1, 10, figsize=(15, 2))  # 创建一个包含1行10列的子图(subplots)的图形,并指定每个子图的大小
for i in range(10):
    axes[i].imshow(example_data[i].cpu().squeeze(), cmap='gray')  # 在指定的子图(axes[i])中显示图像
    axes[i].set_title(f"Pred:{predicted[i].item()}")  # 在每个子图(axes[i])上设置标题,标题内容显示模型对该样本的预测结果
    axes[i].axis('off')  # 关闭第 i个子图(axes[i])的坐标轴显示

plt.show()
# 输出批次中部分样本的真实标签和模型的预测标签
print(f"True labels: {example_targets.cpu().numpy()}")
print(f"Predicted labels: {predicted.cpu().numpy()}")

标签:plt,torch,device,Pytorch,train,test,MyNet,model,MNIST
From: https://www.cnblogs.com/smalldong/p/18257582

相关文章

  • Pytorch:合并分割
    1前言记录一下Pytorch中对tensor合并分割的方法2合并Pytorch中对tensor合并的方法有两种:torch.cat()torch.stack()其中,torch.cat()直接将两个变量进行拼接,不会产生新的维度而torch.stack()则会将tensor堆叠,产生新的维度tensor1=torch.randn(2,3)tensor2=torch.rand......
  • Win11+Miniconda3+python3.9安装pyspark+pytorch
    Win11+Miniconda3+python3.9安装pyspark+pytorch步骤1:安装Miniconda3,具体可以百度或者google步骤2:安装好Miniconda3之后,要创建虚拟环境,类似于虚拟机的样子,然后在虚拟环境安装各种python包已经装好了pytorch,具体步骤可以参考网上的一些教程,很多时候要综合多个教程,比如说先建立......
  • Pytorch数据加载与使用
    前言在训练的时候通常使用Dataset来处理数据集。Dataset的作用提供一个方式获取数据内容和标签(label)。实战fromtorch.utils.dataimportDatasetfromPILimportImageimportosclassget_data(Dataset):def__init__(self,root_dir,label_dir):self.r......
  • Pytorch入门(一):MNIST-手写数字识别-搭建网络模型
    前言作为刚入门深度学习的一位初学者来说,各种各样的学习资料、视频让我看得头昏眼花。明明本来是想了解Pytorch使用方法,莫名其妙看了一个多小时的算法推理,原理逻辑,让人很是苦恼。于是在自己学习了一段时间后,打算做出这个pytorch的系列教程,就是想让大家基于项目进行实战,更......
  • PyTorch与TensorFlow模型互转指南
    在深度学习的领域中,PyTorch和TensorFlow是两大广泛使用的框架。每个框架都有其独特的优势和特性,因此在不同的项目中选择使用哪一个框架可能会有所不同。然而,有时我们可能需要在这两个框架之间进行模型的转换,以便于在不同的环境中部署或利用两者的优势。本文将详细介绍如何......
  • pytorch使用交叉熵训练模型学习笔记
    python代码:importtorchimporttorch.nnasnnimporttorch.optimasoptim#定义一个简单的神经网络模型classSimpleModel(nn.Module):def__init__(self):super(SimpleModel,self).__init__()self.fc=nn.Linear(3,2)#输入3维,输出2类......
  • 手把手教NLP小白如何用PyTorch构建和训练一个简单的情感分类神经网络
        在当今的深度学习领域,神经网络已经成为解决各种复杂问题的强大工具。本文将通过一个实际案例——对Yelp餐厅评论进行情感分类,来介绍如何使用PyTorch构建和训练一个简单的神经网络模型。我们将逐步讲解神经网络的基础概念,如激活函数、损失函数和优化器,并最终实现一......
  • GPU版PyTorch安装、GPU版TensorFlow安装(详细教程)
    目录一、介绍PyTorch、TensorFlow 1. PyTorch2.TensorFlow二、GPU版PyTorch安装1.确定CUDA版本2.确定python版本3.安装PyTorch3.1使用官网命令安装(速度慢)3.2本地安装(速度快)4.检验是否安装成功三、GPU版TensorFlow安装1.确定CUDA版本2.确定TensorFlow版本3.安......
  • PyTorch 动态量化模型
    PyTorch动态量化模型简介PyTorch动态量化是一种模型优化技术,可以将模型参数和激活从浮点数转换为定点数,从而显著降低模型大小和提高推理速度。与静态量化不同,动态量化是在推理时进行量化,无需预先收集校准数据。动态量化工作原理动态量化主要包含以下步骤:观察:在模型推理过......
  • pytorch动态量化函数
    PyTorch动态量化APIPyTorch提供了丰富的动态量化API,可以帮助开发者轻松地将模型转换为动态量化模型。主要API包括:torch.quantization.quantize_dynamic:将模型转换为动态量化模型。torch.quantization.QuantStub:观察模型层的输入和输出分布。torch.quantization.Observer......