当前位置: 首页 > article >正文

Pytorch_P1 Pytorch实现mnist手写数字识别

目录

一、前言

二、前期准备

1、设置GPU

 2、导入数据

3、数据可视化 

三、创建CNN网络

 1、实例化模型,并设置参数

2、训练函数 

3、测试函数

4、正式训练

5、可视化


一、前言

  •   🍨 本文为🔗365天深度学习训练营中的学习记录博客
  • 🍖 原作者:K同学啊

二、前期准备

1、设置GPU

#构建和训练神经网络
import torch
#PyTorch的神经网络模块,提供构建网络所需的类和函数
import torch.nn as nn
import matplotlib.pyplot as plt
#用于处理图像数据集的库
import torchvision
import numpy as np
#提供激活函数的库
import torch.nn.functional as F
import warnings

函数原型:

torchvision.datasets.MNIST(root, train=True, transform=None, target_transform=None, download=False)

参数说明:

  • root (string) :数据地址
  • train (string) :True-训练集,False-测试集
  • download (bool,optional) : 如果为True,从互联网上下载数据集,并把数据集放在root目录下。
  • transform (callable, optional ):这里的参数选择一个你想要的数据转化函数,直接完成数据转化
  • target_transform (callable,optional) :接受目标并对其进行转换的函数/转换。

 2、导入数据

train_data = torchvision.datasets.MNIST("data",
                                        train=True,
                                        transform = torchvision.transforms.ToTensor(),
                                        download=True)
test_data = torchvision.datasets.MNIST("data",
                                       train=False,
                                       transform=torchvision.transforms.ToTensor(),
                                       download=True)
batch_size = 32

处理导入的数据 

#是一个 PyTorch 数据加载器(DataLoader),用于加载训练数据集。通常情况下,数据加载器会将数据集分成小批量(batches)进行处理
train_d = torch.utils.data.DataLoader(train_data,
                                      batch_size = batch_size,
                                      shuffle = True)
test_d = torch.utils.data.DataLoader(test_data,
                                      batch_size = batch_size)
#iter(train_dl) 将数据加载器转换为一个迭代器(iterator),使得我们可以使用 Python 的 next() 函数来逐个访问数据加载器中的元素。
#next() 函数用于获取迭代器中的下一个元素。在这里,它被用来获取 train_dl 中的下一个批量数据。
#它将从 next() 函数返回的元素中提取出两个变量:imgs 和 labels
imgs, labels = next(iter(train_d))
"""imgs 变量将包含一个批量的图像数据,而 labels 变量将包含相应的标签数据。"""

3、数据可视化 

#指定图片大小,图像大小为20宽、5高的绘图(单位为英寸inch)
plt.figure(figsize=(20, 5))
for i, imgs in enumerate(imgs[:20]):
    #squeeze()函数的功能是从矩阵shape中,去掉维度为1的,实现维度缩减
    nping = np.squeeze(imgs.numpy())
    # 将整个figure分成2行10列,绘制第i+1个子图
    plt.subplot(2, 10, i+1)
    plt.imshow(nping ,cmap=plt.cm.binary)
    #去掉坐标轴
    plt.axis("off")
#plt.show()

执行结果如下:

三、创建CNN网络

# 设置图片的类别数,因为有十个数就有十个类别
num_classes = 10
class Model(nn.Module):
    def __init__(self):
        super().__init__()
        #提取特征网络
        # 第一层卷积,卷积核大小为3*3
        self.conv1 = nn.Conv2d(1, 32, kernel_size=3)
        # 设置池化层,池化核大小为2*2
        self.pool1 = nn.MaxPool2d(2)
        # 第二层卷积,卷积核大小为3*3
        self.conv2 = nn.Conv2d(32, 64, kernel_size=3)
        # 设置池化层,池化核大小为2*2
        self.pool2 = nn.MaxPool2d(2)

        #分类网络
        #降维,从 1600 维降到 64 维
        self.fc1 = nn.Linear(1600, 64)
        #再降维
        self.fc2 = nn.Linear(64, num_classes)

        #前向传播
    def forward(self, x):
        #通过卷积层提取图像特征,然后通过激活函数增加非线性,最后通过池化层降低特征的空间维度
        x = self.pool1(F.relu(self.conv1(x)))
        x = self.pool2(F.relu(self.conv2(x)))
        #其实就是把长和宽组成的二维数组拉直成一维的
        x = torch.flatten(x, start_dim=1)

        x = F.relu(self.fc1(x))
        x = self.fc2(x)

        return x

 1、实例化模型,并设置参数

#实例化Model
model = Model()
#设置损失函数,损失函数为交叉熵损失函数
loss_fn = nn.CrossEntropyLoss()
#设置学习率
learn_rate = 1e-2
opt = torch.optim.SGD(model.parameters(), lr=learn_rate)

2、训练函数 

# 训练循环
def train(dataloader, model, loss_fn, optimizer):
    # 查看训练集的大小,一共60000张图片
    size = len(dataloader.dataset)
    # 批次数目,1875(60000/32)
    num_batches = len(dataloader)
    # 初始化训练损失和正确率
    train_loss, train_acc = 0, 0
    # 获取图片及其标签
    for X, y in dataloader:
        X, y = X, y

        # 计算预测误差
        # 设置网络输出
        pred = model(X)
        # 计算网络输出和真实值之间的差距,targets为真实值,计算二者差值即为损失
        loss = loss_fn(pred, y)

        # 反向传播
        optimizer.zero_grad()  # grad属性归零
        loss.backward()  # 反向传播
        optimizer.step()  # 每一步自动更新

        # 记录acc与loss
        #返回数组 pred 在第一个轴(即行)上最大值所在的索引。这通常用于多类分类问题中,其中 pred 是一个包含预测概率的二维数组,每行表示一个样本的预测概率分布。
        #是将布尔数组的数据类型转换为浮点数类型,即将 True 转换为 1.0,将 False 转换为 0.0
        #将求和结果转换为标量值
        train_acc += (pred.argmax(1) == y).type(torch.float).sum().item()
        train_loss += loss.item()

    train_acc /= size
    train_loss /= num_batches

    return train_acc, train_loss

3、测试函数

def test(dataloader, model, loss_fn):
    size = len(dataloader.dataset)  # 测试集的大小,一共10000张图片
    num_batches = len(dataloader)  # 批次数目,313(10000/32=312.5,向上取整)
    test_loss, test_acc = 0, 0

    # 当不进行训练时,停止梯度更新,节省计算内存消耗
    with torch.no_grad():
        for imgs, target in dataloader:
            imgs, target = imgs, target

            # 计算loss
            target_pred = model(imgs)
            loss = loss_fn(target_pred, target)

            test_loss += loss.item()
            test_acc += (target_pred.argmax(1) == target).type(torch.float).sum().item()

    test_acc /= size
    test_loss /= num_batches

    return test_acc, test_loss

4、正式训练

#设置训练批次
epochs = 5
#将每批训练的结果保存下来
train_loss = []
train_acc = []
test_loss = []
test_acc = []

for epoch in range(epochs):
    model.train()
    epoch_train_acc, epoch_train_loss = train(train_d, model, loss_fn, opt)

    model.eval()
    epoch_test_acc, epoch_test_loss = test(test_d, model, loss_fn)

    train_acc.append(epoch_train_acc)
    train_loss.append(epoch_train_loss)
    test_acc.append(epoch_test_acc)
    test_loss.append(epoch_test_loss)

    template = ('Epoch:{:2d}, Train_acc:{:.1f}%, Train_loss:{:.3f}, Test_acc:{:.1f}%,Test_loss:{:.3f}')
    print(template.format(epoch + 1, epoch_train_acc * 100, epoch_train_loss, epoch_test_acc * 100, epoch_test_loss))
#运行完有一个结束显示
print('Done')

执行结果如下:

5、可视化

#忽略警告信息
warnings.filterwarnings("ignore")
# 用来正常显示中文标签
plt.rcParams['font.sans-serif']    = ['SimHei']
# 用来正常显示负号
plt.rcParams['axes.unicode_minus'] = False
#设置分辨率
plt.rcParams['figure.dpi']         = 100

epochs_range = range(epochs)
#画图展示
plt.figure(figsize=(12, 3))
plt.subplot(1, 2, 1)

plt.plot(epochs_range, train_acc, label='Training Accuracy')
plt.plot(epochs_range, test_acc, label='Test Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')

plt.subplot(1, 2, 2)
plt.plot(epochs_range, train_loss, label='Training Loss')
plt.plot(epochs_range, test_loss, label='Test Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()


👏觉得文章对自己有用的宝子可以收藏文章并给小编点个赞!

👏想了解更多统计学、数据分析、数据开发、机器学习算法、深度学习等有关知识的宝子们,可以关注小编,希望以后我们一起成长!


http://www.kler.cn/a/463864.html

相关文章:

  • Go语言性能优化-字符串格式化优化
  • NCCL源码解读3.1:double binary tree双二叉树构建算法,相比ring环算法的优势
  • C语言带参数的宏定义的相关知识汇总(最常用的形式、带标记分隔符##的形式...)
  • Pytorch的自动求导模块
  • 软考教材重点内容 信息安全工程师 第 12 章网络安全审计技术原理与应用
  • “善弈者”也需妙手,Oclean欧可林:差异化不是说说而已
  • 自然语言处理:第八十三章 Prompt格式到底多重要?
  • IP5385为智能手机提供快充方案的30W到100W大功率电源管理芯片
  • 阿里云CDN与腾讯云CDN的全面对比
  • MySQL索引优化:提升查询性能的秘诀
  • 8086汇编(16位汇编)学习笔记08.函数
  • llama.cpp与PyTorch、TensorFlow
  • 镜舟科技荣获 IT168 2024年度创新产品奖
  • 使用flask-caching扩展心得
  • 【机器人】机器人的数学模型:符号表示、位形空间、状态空间、工作空间
  • 开源表单设计器form-create-designer如何保存设计器的规则和回显
  • logback之pattern详解以及源码分析
  • 安卓入门二 Kotlin基础
  • [原创](Modern C++)现代C++的关键性概念: 通俗易懂的解释“折叠表达式(Fold expressions)“
  • javaEE-多线程进阶-JUC的常见类
  • 利用Java Swing图形组件和JDBC实现简易的ATM存取款机系统。
  • Go 语言:Jank 简客博客系统
  • 基于单片机的电子安全密码锁的设计初探
  • Linux硬盘分区 --- fdisk命令MBR分区、添加硬盘、lsblk命令
  • 电商项目-数据同步解决方案(四)商品下架同步更新ES索引库数据
  • 小程序发版后,强制更新为最新版本