【深度学习框架】|PyTorch|完成一个手写体识别任务

本文介绍如何使用PyTorch实现手写体数字识别任务,包括安装配置、数据集准备、模型构建、训练及预测过程。通过构建一个多层感知机模型完成MNIST数据集上的手写数字分类。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

💖作者简介:大家好,我是车神哥,府学路18号的车神🥇
⚡About—>车神:从寝室实验室快3分钟,最慢3分半(那半分钟其实是等绿
📝个人主页:车手只需要车和手,压力来自论文_府学路18号车神_CSDN博客
🥇 官方认证:人工智能领域优质创作者
🎉点赞评论收藏 == 养成习惯一键三连)😋

⚡希望大家多多支持🤗~一起加油 😁

从深度学习的简单任务开始,我们将从不同的深度学习框架来实现一个手写体识别任务,这个任务在深度学习领域可以说是和学习编程语言的第一步“Hello World”差不多。

主要的目的是为了可以直观的对比出不同深度学习框架下实现代码的差异性。我们均通过构建一个多层感知机模型来完成这个任务。

🎉PyTorch

老规矩,关于Pytorch之前也讲过了。

它是一个基于Python的科学计算包,好处也很多,如速度快,方便灵活~

⚡PyTorch安装

简单粗暴版

用conda创建环境来安装不同版本的pytorch

  • conda create -n pytorch python=3.6.0

注意后面可以选择不同的版本哦~

进入环境

  • activate base

  • activate pytorch

🎉手写体识别任务

这里我们用到的一个开放的手写体识别数据集:MNIST数据集。

目前应用相当的广泛,在许多论文和基础教程中都应用到了。

MNIST数据集来自美国国家标准与技术研究所。

数据集由250个不同的人手写的数字构成,其中50%来自高中生,50%来自人口普查局的工作人员。具体由如下4个部分组成:

  1. 训练图片集(training set images):train-images-idx3-ubyte.gz (包含60,000个样本)
  2. 训练图片标签(training set labels):train-labels-idxl-ubyte.gz (包含60,000个标签)
  3. 测试图片集(test set images):t10k-images-idx3-ubyte.gz (包含10,000 个样本)
  4. 测试图片标签(test set labels):t10k-labels-idxl-ubyte.gz (包含10,000个标签)

样例如下图所示:

请添加图片描述

🎉多层感知机

对于上面这样的数据集,我们构建一个三层神经网络模型,分别为输入层隐含层输出层。这是一个非常普通简单的神经网络模型,俗称为多层感知机(Mult-Layer Perceptron, MLP)

整个模型如下图所示:
请添加图片描述
该神经网络包含三层,第一层(输入层)有784个神经元(每张手写体识别图像素均为28像素*28像素的图像),第二层(隐藏层)有200个神经元,最终层(输出层)有10个神经元(有数字0~9共有10个类别)。我们使用Sigmoid函数作为激活函数,将均方误差作为损失函数,使用Adam优化器,Learning Rate=0.01.

🎉PyTorch代码

所有框架下的步骤均一致:

  1. 设置参数并加载数据集(大多数框架都有架子标准数据集的方法,如MNIST)
  2. 创建多层感知机(MLP)神经网络
  3. 定义训练函数,包括模型训练和模型存储
  4. 定义预测函数,包括模型导入和测试数据预测
  5. 创建main函数,让用户使用训练数据集进行训练,然后使用测试数据集进行测试

在下列代码中,将其整理为相同的格式以便比较,每份代码包含五部分:

  • 设置参数并加载数据集
  • 定义神经网络
  • 定义训练函数
  • 定义预测函数
  • main函数

⚡*main函数

其中的main函数不变:

import argparse

if __name__=="__main__":

    parser = argparse.ArgumentParser()
    parser.add_argument("--action", type=str, default="predict")
    FLAGS, unparsed = parser.parse_known_args()
    if FLAGS.action == "train":
        train()

    if FLAGS.action == "predict":
        predict()

运行代码的方法:

1. 训练:python MNIST.py --action train
2. 预测:python MNIST.py -- action predict

1. ⚡设置参数并加载数据集

import torch
import argparse
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.autograd import Variable
from torch.utils.data import DataLoader

# 定义参数
inputs, hiddens, outputs = 784, 200, 10
learning_rate = 0.01
epochs = 50
batch_size = 64

trainsformation = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])
train_set = datasets.MNIST('mnist/', train=True, transform=trainsformation, download=True)
train_loader = DataLoader(dataset=train_set, batch_size=batch_size, shuffle=True)
test_set = datasets.MNIST('mnist/', train=False, transform=trainsformation, download=True)
test_loader = DataLoader(dataset=test_set, batch_size=batch_size, shuffle=False)

2. ⚡定义神经网络

# 定义神经网络
class mlp(nn.Module):
    def __init__(self):
        super(mlp, self).__init__()
        self.sigmoid = nn.Sigmoid()
        self.hidden_layer = nn.Linear(inputs, hiddens)
        self.output_layer = nn.Linear(hiddens, outputs)

    def forward(self, x):
        out = self.sigmoid(self.hidden_layer(x))
        out = self.sigmoid(self.output_layer(out))
        return out

    def name(self):
        return "mlp"

3. ⚡定义训练函数

# 定义训练函数
def train():
    model = mlp()
    loss = nn.MSELoss(reduction='sum')
    optimizer = optim.Adam(model.parameters(), lr=learning_rate)
    for epoch in range(epochs):
        avg_error = 0
        for i, (images, labels) in enumerate(train_loader):
            images = Variable(images.view(-1, inputs))
            # 将类别标签转换成One-hot编码
            one_hot = torch.FloatTensor(labels.size(0), 10).zero_()
            target = one_hot.scatter_(1, labels.view((labels.size(0), 1)), 1)
            target = Variable(target)
            # 计算损失函数和梯度
            optimizer.zero_grad()
            out = model(images)

            error = loss(out, target)
            error.backward()
            optimizer.step()
            avg_error += error.item()

            avg_error /= train_loader.dataset.train_data.shape[0]
            print('Epoch [%d/%d], error:%.4f' % (epoch+1, epochs, avg_error))
            torch.save(model.state_dict(), "model.pkl")

4. ⚡定义预测函数

# 定义预测函数
def predict():
    model = mlp()
    model.load_state_dict(torch.load("model.pkl"))
    correct, total = 0, 0
    for images, labels in test_loader:
        images = Variable(images.view(-1, inputs))
        out = model(images)
        _, predicted = torch.max(out.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum()
    print("accuracy: %0.2f %%" % (100.0 * correct / total))

🤗代码汇总

到此我们已经构建完了所有的模型结构,让我们运行起来~

训练开始(在Terminal输入):

python MNIST.py --action train

预测开始:

python MNIST.py -action predict

# -- coding: utf-8 --
# @Time : 2022/5/26 19:07
# @Author : 府学路18号车神
# @File : PyTorch.py
# @Software: PyCharm

import torch
import argparse
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.autograd import Variable
from torch.utils.data import DataLoader

# 定义参数
inputs, hiddens, outputs = 784, 200, 10
learning_rate = 0.01
epochs = 50
batch_size = 64

trainsformation = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])
train_set = datasets.MNIST('mnist/', train=True, transform=trainsformation, download=True)
train_loader = DataLoader(dataset=train_set, batch_size=batch_size, shuffle=True)
test_set = datasets.MNIST('mnist/', train=False, transform=trainsformation, download=True)
test_loader = DataLoader(dataset=test_set, batch_size=batch_size, shuffle=False)

# 定义神经网络
class mlp(nn.Module):
    def __init__(self):
        super(mlp, self).__init__()
        self.sigmoid = nn.Sigmoid()
        self.hidden_layer = nn.Linear(inputs, hiddens)
        self.output_layer = nn.Linear(hiddens, outputs)

    def forward(self, x):
        out = self.sigmoid(self.hidden_layer(x))
        out = self.sigmoid(self.output_layer(out))
        return out

    def name(self):
        return "mlp"

# 定义训练函数
def train():
    model = mlp()
    loss = nn.MSELoss(reduction='sum')
    optimizer = optim.Adam(model.parameters(), lr=learning_rate)
    for epoch in range(epochs):
        avg_error = 0
        for i, (images, labels) in enumerate(train_loader):
            images = Variable(images.view(-1, inputs))
            # 将类别标签转换成One-hot编码
            one_hot = torch.FloatTensor(labels.size(0), 10).zero_()
            target = one_hot.scatter_(1, labels.view((labels.size(0), 1)), 1)
            target = Variable(target)
            # 计算损失函数和梯度
            optimizer.zero_grad()
            out = model(images)

            error = loss(out, target)
            error.backward()
            optimizer.step()
            avg_error += error.item()

            avg_error /= train_loader.dataset.train_data.shape[0]
            print('Epoch [%d/%d], error:%.4f' % (epoch+1, epochs, avg_error))
            torch.save(model.state_dict(), "model.pkl")

# 定义预测函数
def predict():
    model = mlp()
    model.load_state_dict(torch.load("model.pkl"))
    correct, total = 0, 0
    for images, labels in test_loader:
        images = Variable(images.view(-1, inputs))
        out = model(images)
        _, predicted = torch.max(out.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum()
    print("accuracy: %0.2f %%" % (100.0 * correct / total))


# main
if __name__=="__main__":

    parser = argparse.ArgumentParser()
    parser.add_argument("--action", type=str, default="predict")
    FLAGS, unparsed = parser.parse_known_args()
    if FLAGS.action == "train":
        train()

    if FLAGS.action == "predict":
        predict()

📝总结

PyTorch的关键特性是命令式编程,所见即所得,输入什么执行什么。完全契合Python的语法风格,和之前的Tensorflow与Keras的符号式编程大不相同。

很大一个好处就是,我们面对不同的API时,如果遇到不懂的,可以直接运行查看结果是否满足要求~

🥇 往期框架

框架Blog
TensorFlow【深度学习框架】|TensorFlow|完成一个手写体识别任务
Keras【深度学习框架】|Keras|完成一个手写体识别任务

好了,第三个框架下实现手写体识别的任务就到这了,下次在换Pytorch框架来实现一下,下期再见哦~


❤坚持读Paper,坚持做笔记,坚持学习,坚持刷力扣LeetCode❤!!!
坚持刷题!!!
To Be No.1

⚡⚡


创作不易⚡,过路能❤关注收藏点个赞三连就最好不过了

ღ( ´・ᴗ・` )

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

府学路18号车神

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

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

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

打赏作者

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

抵扣说明:

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

余额充值