pytorch之mnist(手写数字识别)任务

MNIST任务是作为初学者来说, 是一个不错的起点。掌握MNIST任务的实现,以此为后续的CV(计算机视觉)和DL(深度学习)打下良好基础的基础。

目录

1.任务背景

2.任务流程

3.代码实现


1.任务背景

MNIST(Modified National Institute of Standards and Technology)数据集是一个广泛使用的手写数字识别数据集。它包含了从0到9的数字的灰度图像,通常用于训练和测试图像识别算法。MNIST数据集是由纽约大学的Yann LeCun教授及其同事创建的,它是对原始的NIST数据集进行修改和整理后的版本。

MNIST数据集包含60,000个训练样本和10,000个测试样本。每个样本都是一个28x28像素的灰度图像,代表了0到9中的一个数字。这些图像是从不同的手写体、不同的书写风格和不同的字体中提取的,因此包含了大量的变异性。

2.任务流程

为了让大家更能理解mnist的任务实现,这里绘制了流程图:

3.代码实现

为了源码的可读性,给出了每行源码及其注释。

代码已在pytorch框架调试(NVIDIA RTX 3060 12G,anaconda+pycharm),大家可直接拿来使用,正确率可以达到99%以上,如果达不到,可以根据硬件条件,固定随机种子,修改模型超参数,以达到最优。

'''1.加载必要的库'''
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets,transforms
from torch.utils.data import DataLoader
'''2.定义超参数'''
BATCH_SIZE=64   # 每个批次处理的图像
EPOCH=10        # 训练数据集的轮次:数据集的循环运行几轮
DEVICE=torch.device('cuda' if torch.cuda.is_available() else 'cpu') # 判断是否用GPU还是CPU训练
'''3.构建pipeline,对图像做预处理(transform)'''
pipeline=transforms.Compose([
    transforms.ToTensor(),  # 将图片转换成tensor
    transforms.Normalize((0.1307,),(0.3081,)) # 正则化,降低模型复杂度
])
'''4.下载、加载数据集'''
torch.manual_seed(0)  #固定随机种子,大家可以尝试不同的种子测试,择选最好的一次
train_set=datasets.MNIST('data',train=True,download=True,transform=pipeline) # 下载训练集
test_set=datasets.MNIST('data',train=False,download=True,transform=pipeline) # 下载测试集
train_loader=DataLoader(train_set,batch_size=BATCH_SIZE,shuffle=True)   # 加载训练集
test_loader=DataLoader(test_set,batch_size=BATCH_SIZE,shuffle=True)     # 加载测试集 (这里顺序可以不打乱)
'''5.定义网络模型'''
class mnist(nn.Module):     # 构建mnist模型,并继承module类
    def __init__(self):     # 初始化mnist方法
        super().__init__()  # 继承父类的方法
        self.conv1=nn.Conv2d(1,10,5)  # 创建一个卷积模型,1:灰度图通道,10:输出通道,5:卷积核(kernel)大小
        self.conv2=nn.Conv2d(10,20,3) # 创建一个卷积模型,10:输入通道,20:输出通道,3:kernel大小
        self.drop_out=nn.Dropout2d(0.25)
        self.fc1=nn.Linear(20*10*10,500) # 20*10*10:输入通道,500:输出通道
        self.fc2=nn.Linear(500,10)  # # 500:输入通道,10:输出通道
    def forward(self,x):
        input_size=x.size(0) # 取到第0维:batch_size
        x=self.conv1(x) # 输入:batch_size*1*28*28,输出:batch_size*10*24*24(24=28-5+1,padding=0,stride=1)
        x=F.relu(x)     # 保持shape不变,表达能力更强
        x=F.max_pool2d(x,2,2)  #最大池化层,步长是2,24/2=12,结果:batch_size*10*12*12
        x=self.conv2(x)  # 输入:batch_size*10*12*12,输出:batch_size*20*10*10
        x=F.relu(x)
        x=x.reshape(input_size, -1)      # 计算其维度 2000=20*10*10,并将其打平
        x=self.fc1(x)    # 输入:batch_size=2000, 输出:batch_size*500
        x = F.relu(x)
        x=self.fc2(x)    # 输入:batch_size=500, 输出:batch_size*10
        x = F.relu(x)

        output=F.log_softmax(x,dim=1) #计算分类后,每个数字的概率值
        return output
'''6.定义优化器'''
model=mnist().to(DEVICE) # 创建模型,并部署到设备上
optimizer=optim.Adam(model.parameters())  # 优化模型的参数
'''7.定义训练方法'''
def train_model(model,device,train_loader,optimizer,epoch):  # 定义训练方法
    model.train()   #训练模型
    loss_total=0
    for batch_index,(data,target) in enumerate(train_loader):
        data,target=data.to(device),target.to(device)  # 把数据部署到设备上
        optimizer.zero_grad()    # 梯度初始化为0
        output=model(data)       # 前向传播,得到训练后的结果
        loss=F.cross_entropy(output,target)  # 计算损失值
        loss.backward()  # 将损失值进行反向传播
        optimizer.step() # 参数的优化更新
        loss_total+=loss.item()  # 累加一个epoch所有损失值
    loss_epoch=loss_total/len(train_loader)  # 计算机每一个epoch的平均损失值
    print(f'Train epoch:{epoch} \t loss_epoch:{loss_epoch:0.6f}')  # 打印epoch及平均损失值
'''8.定义测试方法'''
def test_model(model,device,test_loader):
    model.eval()  # 设置模型的评估模式
    correct=0.0    # 初始化正确率
    loss_test=0.0   # 初始化损失值
    with torch.no_grad():  # 测试环境,不计算梯度,也不进行反向传播
        for data,target in test_loader:
            data,target=data.to(device),target.to(device) # 将数据移动到设备上
            output=model(data)  # 前向传播
            loss_test+=F.cross_entropy(output,target).item() # 累加当前批次的损失值之和
            pred = output.max(1, keepdim=True)[1]  # 找到概率值最大的下标
            correct+=pred.eq(target.view_as(pred)).sum().item()  # 计算正确的样本数量
        loss_test/=len(test_loader.dataset)   # 计算测试集平均的损失
        Accuracy=100*correct/len(test_loader.dataset)
        print(f'Test_loss:{loss_test:.4f} \t Accuracy:{Accuracy:.3f}\n')
'''9.调用训练和测试的方法'''
for epoch in range(EPOCH):
    train_model(model,DEVICE,train_loader,optimizer,epoch)
    test_model(model,DEVICE,test_loader)

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值