PyTorch手写数字识别

Python 手写数字识别的实现(pytorch框架) 超详细版本-jupyter notebook 本文详细介绍了如何构建LeNet-5神经网络用于手写数字识别。 文中大量的代码解释包含在代码行后的注释中,请注意查看。 下面的代码在谷歌云盘的colab上运行,也可以在jupyter notebook上运行 阅读详情

1. MNIST数据集简介

        包含了6W训练样本和1W条测试样本,共10类(0-9),每张图片都做了尺寸归一化,都是28*28大小的灰度图。其中颜色通道为1,表示灰度;每个像素值的范围是0-255(0:黑色;255:白色)

2. 数据加载与探索

1. 数据加载

def load_data(data_path, batch_size):
    # 1.构建transform,对图像做处理
    transform = transforms.Compose([
        transforms.ToTensor(),  # 将图片转换成tensor
        transforms.Normalize((0.1307,), (0.3081,))  # 正则化,降低模型复杂度
    ])
    # 2.下载数据集
    train_set = datasets.MNIST(data_path, train=True, download=True, transform=transform)
    test_set = datasets.MNIST(data_path, train=False, download=True, transform=transform)
    # 3.批量加载数据
    train_loder = DataLoader(train_set, batch_size=batch_size, shuffle=True, pin_memory=True)
    test_loder = DataLoader(test_set, batch_size=batch_size, shuffle=True, pin_memory=True)

    return train_loder, test_loder

2. 数据探索

# 查看类别    
print(train_set.classes)
# ['0 - zero', '1 - one', '2 - two', '3 - three', '4 - four', '5 - five', '6 - six', '7 - seven', '8 - eight', '9 - nine']

# 数据集大小
print(train_set.data.shape)
# torch.Size([60000, 28, 28])

3. 搭建网络模型

3.1 官网实现

from torch.optim.lr_scheduler import StepLR

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 32, 3, 1)
        self.conv2 = nn.Conv2d(32, 64, 3, 1)
        self.dropout1 = nn.Dropout2d(0.25)
        self.dropout2 = nn.Dropout2d(0.5)
        self.fc1 = nn.Linear(9216, 128)
        self.fc2 = nn.Linear(128, 10)

    def forward(self, x):
        x = F.relu(self.conv1(x))
        x = F.relu(self.conv2(x))
        x = F.max_pool2d(x, 2)
        x = self.dropout1(x)
        x = torch.flatten(x, 1)

        x = F.relu(self.fc1(x))
        x = self.fc2(self.dropout2(x))
        output = F.log_softmax(x, dim=1)
        return output

3.2 自定义实现

能达到和官网相似的准确率99%,但运行时间减少一大半!!!

class Digit(nn.Module):
    def __init__(self):
        super(Digit, self).__init__()
        self.conv1 = nn.Conv2d(1, 10, 5)    # 1: 灰度图片的通道;10:输出通道;5:kernel
        self.conv2 = nn.Conv2d(10, 20, 3)   # 10:输入通道;20:输出通道;3:kernel
        self.fc1 = nn.Linear(20*10*10, 500)
        self.fc2 = nn.Linear(500, 10)

    def forward(self, x):
        input_size = x.size(0)     # batch_size
        x = F.relu(self.conv1(x))  # batch*1*28*28 --> batch*10*24*24  (28-5+1=24)
        x = F.max_pool2d(x, 2, 2)  # 24*24*10 --> 12*12*10

        x = F.relu(self.conv2(x))   # 12*12*10 --> 10*10*20  (12-3+1=10)
        x = x.view(-1, 10*10*20)    # 拉平?
        # x = x.view(input_size, -1)  # 拉平,-1 自动计算维度,这里应为20*10*10=2000

        x = F.relu(self.fc1(x))     # 2000 --> 500
        pred = F.log_softmax(self.fc2(x), dim=1)  # 计算分类后,每个数字的概率值  500 --> 10
        return pred

3.3 自定义RNN实现

1. RNN模型定义

class RNNModel(nn.Module):
    # layer_dim: RNN的层数
    def __init__(self, input_dim, hidden_dim, layer_dim, output_dim):
        super(RNNModel, self).__init__()
        self.hidden_dim = hidden_dim
        self.layer_dim = layer_dim
        self.rnn = nn.RNN(input_dim, hidden_dim, layer_dim,
                          batch_first=True, nonlinearity='relu')
        self.fc = nn.Linear(hidden_dim, output_dim)

    def forward(self, x):
        # (layer_dim, batch_size, hidden_dim)
        h0 = torch.zeros(self.layer_dim, x.size(0), self.hidden_dim).requires_grad_()
        # h0 = torch.zeros(self.layer_dim, x.size(0), self.hidden_dim).requires_grad()
        # 分离隐藏状态,避免梯度爆炸
        out, hn = self.rnn(x, h0.detach())
        out = self.fc(out[:, -1, :])
        return out

2. 相关模型参数

input_dim = 28     # 输入维度
hidden_dim = 100   # 隐藏层的维度
layer_dim = 2      # 2层RNN
output_dim = 10    # 输出维度

model = RNNModel(input_dim, hidden_dim, layer_dim, output_dim)
criterion = nn.CrossEntropyLoss()
lr = 0.01
optimizer = torch.optim.SGD(model.parameters(), lr=lr)

# 输出模型参数个数
print(len(list(model.parameters())))
# 10

# 输出模型各个参数大小
for param in list(model.parameters()):
print(param.size())

11

torch.Size([100, 28])
torch.Size([100, 100])
torch.Size([100])
torch.Size([100])
torch.Size([100, 100])
torch.Size([100, 100])
torch.Size([100])
torch.Size([100])
torch.Size([10, 100])
torch.Size([10])

3.4 自定义LSTM实现

class LSTMModel(nn.Module):
    # layer_dim: LSTM的层数
    def __init__(self, input_dim, hidden_dim, layer_dim, output_dim):
        super(LSTMModel, self).__init__()
        self.hidden_dim = hidden_dim
        self.layer_dim = layer_dim
        self.lstm = nn.LSTM(input_dim, hidden_dim, layer_dim, batch_first=True)
        self.fc = nn.Linear(hidden_dim, output_dim)

    def forward(self, x):
        # (layer_dim, batch_size, hidden_dim)
        # 初始化隐藏层状态全为0
        h0 = torch.zeros(self.layer_dim, x.size(0), self.hidden_dim).requires_grad_()
        # 初始化cell state
        c0 = torch.zeros(self.layer_dim, x.size(0), self.hidden_dim).requires_grad_()
        # 分离隐藏状态,避免梯度爆炸
        out, (hn, cn) = self.lstm(x, (h0.detach(), c0.detach()))
        # 只需最后一层的隐藏层状态
        out = self.fc(out[:, -1, :])
        return out

4. 模型训练

4.1 官网及Digit模型训练

1. 模型训练

def train(model, train_loader, test_loader, optimizer, epochs):
    for epoch in range(epochs):
        train_loss = train_epoch(model, train_loader, optimizer)
        test_loss, test_correct = test_epoch(model, test_loader)
        print("Epoch: {0}  Train loss: {1:.4f}  Test loss: {2:.4f}, Accuracy: {3:.4f}"
              .format(epoch, train_loss, test_loss, test_correct * 100.0))

2. 单轮训练

def train_epoch(model, train_loader, optimizer):
    model.train()
    train_loss = 0.0
    for batch_id, (data, target) in enumerate(train_loader):
        optimizer.zero_grad()  # 梯度清零,防止不断累加
        output = model(data)
        loss = F.cross_entropy(output, target)
        loss.backward()
        optimizer.step()
        train_loss += loss.item()

    train_loss /= len(train_loader.dataset)
    return train_loss

亦可用其他损失函数,如:

loss = F.nll_loss(output, target)  
test_loss += F.nll_loss(output, target, reduction='sum').item()

3. 单轮验证

def test_epoch(model, test_loader):
    model.eval()
    test_correct = 0.0
    test_loss = 0.0
    with torch.no_grad():  # 不进行梯度计算,也不会进行梯度传播
        for data, target in test_loader:
            output = model(data)
            test_loss += F.cross_entropy(output, target).item()  # 交叉熵损失,用于多分类
            # 找到概率值最大的下标
            pred = output.argmax(dim=1, keepdim=True)
            # 累计正确的值
            test_correct += pred.eq(target.view_as(pred)).sum().item()

    test_loss /= len(test_loader.dataset)
    test_correct /= len(test_loader.dataset)
    return test_loss, test_correct

 找到概率值最大的下标,亦可使用如下方法:

pred = torch.max(output, dim=1)
pred = output.argmax(dim=1)
pred = output.argmax(dim=1, keepdim=True)

4.2 RNN&LSTM模型训练

1. 模型训练

def train(model, train_loader, test_loader, optimizer, criterion, epochs, sequence_dim, input_dim):
    for epoch in range(epochs):
        train_loss = train_epoch(model, train_loader, optimizer, criterion, sequence_dim, input_dim)
        test_loss, test_correct = test_epoch(model, test_loader, criterion, sequence_dim, input_dim)
        print("Epoch: {0}  Train loss: {1:.4f}  Test loss: {2:.4f}, Accuracy: {3:.4f}"
              .format(epoch, train_loss, test_loss, test_correct * 100.0))

2. 单轮训练

def train_epoch(model, train_loader, optimizer, criterion, sequence_dim, input_dim):
    model.train()
    train_loss = 0.0
    for batch_id, (data, target) in enumerate(train_loader):
        data = data.view(-1, sequence_dim, input_dim).requires_grad_()   # to(device)
        optimizer.zero_grad()
        output = model(data)
        loss = criterion(output, target)
        loss.backward()
        optimizer.step()
        train_loss += loss.item()
    train_loss /= len(train_loader.dataset)
    return train_loss

3. 单轮测试

# 定义测试方法
def test_epoch(model, test_loader, criterion, sequence_dim, input_dim):
    model.eval()
    test_correct = 0.0
    test_loss = 0.0
    with torch.no_grad():
        for data, target in test_loader:
            data = data.view(-1, sequence_dim, input_dim).requires_grad_()  
            output = model(data)
            test_loss += criterion(output, target).item()

            pred = output.argmax(dim=1, keepdim=True)
            test_correct += pred.eq(target.view_as(pred)).sum().item()
    test_loss /= len(test_loader.dataset)
    test_correct /= len(test_loader.dataset)
    print(len(test_loader.dataset))
    return test_loss, test_correct

5. 模型调用

5.1 官网&Digit调用

def main():
    EPOCHS = 3
    BATCH_SIZE = 8
    DATA_PATH = '../data/'
    MODEL_PATH = '../model/'
    model = Digit()
    optimizer = optim.Adam(model.parameters())

    train_loader, test_loader = load_data(DATA_PATH, BATCH_SIZE)
    train(model, train_loader, test_loader, optimizer, EPOCHS)

自定义Digit效果:

5.2 RNN&LSTM调用

def main():
    EPOCHS = 10
    BATCH_SIZE = 8
    DATA_PATH = '../data/'
    MODEL_PATH = '../model/'

    # 模型参数定义
    input_dim = 28     # 输入维度
    hidden_dim = 100   # 隐藏层的维度
    layer_dim = 2      # 2层RNN
    output_dim = 10    # 输出维度
    sequence_dim = 28  # 序列长度

    model = RNNModel(input_dim, hidden_dim, layer_dim, output_dim)
    criterion = nn.CrossEntropyLoss()
    lr = 0.01  # 注意学习率设置太大(比如0.1),会导致损失函数为Non
    optimizer = SGD(model.parameters(), lr=lr)

    train_loader, test_loader = load_data(DATA_PATH, BATCH_SIZE)
    train(model, train_loader, test_loader, optimizer, criterion, EPOCHS, sequence_dim, input_dim)

RNN效果:

 LSTM效果:

1层的lstm比2、3层效果更好,但不如Digit(),可继续优化。

layer_dim = 1 

Pytorch实现手写数字识别【基于全连接神经网络】 构建全连接神经网络模型,使用pytroch实现手写数字识别 阅读详情

相关推荐

【机器学习入门】使用pytorch实现手写数字识别

今天学习的内容是以手写数字识别任务为例,展示了使用PyTorch框架构建和训练一个简单的神经网络模型的完整流程。数据预处理:定义了数据转换操作,包括将图像转换为张量和归一化处理。下载并加载了MNIST数据集,分为训练集和测试集。创建了数据加载器,用于批量加载数据并在每个epoch开始时打乱数据顺序。模型定义:使用MnistNet类定义了一个神经网络模型,该类继承自nn.Module。MnistNet类中包含了两个卷积层和两个全连接层,以及前向传播逻辑。

m0_53294028的博客 4549

PyTorch——手写数字识别

目录PyTorch 学习 —— 手写数字识别Ⅰ. 数据读取器1. 训练集2. 验证集和测试集Ⅱ. 搭建网络Ⅲ. 模型训练1. 开始训练2. 模型验证Ⅲ. 模型测试Ⅳ. 绘制图像Ⅴ. 完整代码 PyTorch 学习 —— 手写数字识别   MNIST 数据集,其包含70000 个28×28 的手写数字的数据集,其中又分为60000 个训练样本与10000 个测试样本。 Ⅰ. 数据读取器 import torch from torch import nn from torch import optim fro

原谅我这一生不羁放纵爱自由 2万+

Pytorch+CNN 识别自己手写的数字

Pytorch+CNN 识别自己手写的数字 看了网上很多的手写数字识别的例子,发现都没有一个可以识别自己手写的例子,正好现在需要写一个例子,于是自己研究了一下,写出了 一个能识别自己手写的例子供大家参考。转载请注明出处。如果想看原理的话,可以从网上查,有很多讲解手写数字识别原理的博客都很不错。 训练和测试数据集使用MNIST,在代码中可以下载。事先在电脑自带的画图软件上画出几个数字,尽量写的小一点...

大白的技术成长之路 6591

NLP笔记(5)——Pytorch实现手写数字识别

文末附完整代码!!!

小嘤熊的博客 2483

CNN实现手写数字识别(Pytorch)

CNN(卷积神经网络)主要包括卷积层、池化层和全连接层。输入数据经过多个卷积层和池化层提取图片信息后,最后经过若干个全连接层获得最终的输出。以下基于Pytorch框架搭建一个CNN神经网络实现手写数字识别。

weixin_46599926的博客 1万+

CNN01:Pytorch实现LeNet的Mnist手写数字识别

CNN01:Pytorch实现LeNet的Mnist手写数字识别 1、LeNet的网络结构和原理

xiaoheizi_du的博客 1万+

Pytorch入门——手把手教你MNIST手写数字识别

MNIST手写数字识别教程 要开始带组内的小朋友了,特意出一个Pytorch教程来指导一下 [!] 这里是实战教程,默认读者已经学会了部分深度学习原理,若有不懂的地方可以先停下来查查资料 目录MNIST手写数字识别教程1 什么是MNIST?2 使用Pytorch实现手写数字识别2.1 任务目的2.2 开发环境2.3 实现流程3 具体代码实现3.1 数据预处理部分3.1.1 初始化全局变量3.1.2 构建数据集3.2 训练部分3.2.1 构建模型3.2.2 构建迭代器与损失函数3.2.3 构建训练循环3.2

Elwin的博客 9万+

Pytorch之实战手写数字识别

本文代码是**唐进民的《深度学习之Pytorch实战计算机视觉》**中的6.4节“实战手写数字识别” 我把书中代码敲到pycharm上时,可能由于版本之间的差异,出现了不同的问题。然后对几处代码进行了修改,使其能正常运行,并得出结果。 写本文的目的,就是希望自己通过学习这个案例,能对pytorch和cnn有一个基础的理解。 代码框架1.导入必要的包2.数据类型转换3.数据集(训练集和测试集)的下载4.数据装载5.数据预览6.CNN模型搭建7.损失函数和优化函数8.CNN模型训练和参数优化9.用训练好的模型进

m0_52314880的博客 2751

PyTorch手写数字识别(MNIST数据集)

MNIST 手写数字识别是一个比较简单的入门项目,相当于深度学习中的 Hello World,可以让我们快速了解构建神经网络的大致过程。虽然网上的案例比较多,但还是要自己实现一遍。代码采用 PyTorch 1.0 编写并运行...

Steven的博客 3万+

从零开始用 PyTorch 搭建 CNN 手写数字识别模型(MNIST 实战教程)

本篇文章将带你从零开始,使用 PyTorch 搭建一个卷积神经网络(CNN)模型,实现对手写数字的识别。我们将以经典的 MNIST 数据集为例,深入讲解数据加载、模型构建、训练与评估的全过程,并最终实现自定义手写图片的本地识别测试。 通过理论结合实战,读者不仅能够掌握 PyTorch 的基础用法,还能理解 CNN 在图像处理中的应用原理。本教程适合深度学习初学者以及希望通过实战提升技能的开发者,配有完整源码和注释,助你轻松入门 AI 世界。 📌关键词:PyTorch、CNN、MNIST、手写数字识别、

博客虽小,世界尽在其中 4502

PyTorch: CNN实战MNIST手写数字识别

PyTorch: CNN实战MNIST手写数字识别cnn导包加载数据构造CNN训练并计算损失结果 cnn 卷积神经网络CNN的结构一般包含这几个层: 输入层:用于数据的输入 卷积层:使用卷积核进行特征提取和特征映射 激励层:由于卷积也是一种线性运算,因此需要增加非线性映射 池化层:进行下采样,对特征图稀疏处理,减少数据运算量。 全连接层:通常在CNN的尾部进行重新拟合,减少特征信息的损失...

devcy的博客 3187

用PyTorch实现MNIST手写数字识别(最新,非常详细)

1 MNIST数据集(提取码: zm7q )

qq_45588019的博客 13万+

pytorch深度学习:手写数字识别(实战项目一)

经过前边基础知识的铺垫,已经足够完成深度学习中的"hello world"项目:手写数字识别。这节课就是利用pytorch完成这个实战任务,它的本质上是个10分类问题。 1.MNIST数据集 mnist手写字数据集是机器学习领域经典的数据集,这里就不详细介绍了。它的每个样本都是(28,28)的矩阵构成,每个数据点代表这个点的灰度值,标签则是0-9这十个数字。 数据集又分为训练集和测试集,训练集由60000个样本组成,测试集由10000个样本组成。我们使用批数据处理将数据打包为训练集和测试集,Batch_si

qq_37333048的博客 6391

使用Pytorch实现手写数字识别

使用Pytorch实现手写数字识别 1. 思路和流程分析 流程: 准备数据,这些需要准备DataLoader 构建模型,这里可以使用torch构造一个深层的神经网络 模型的训练 模型的保存,保存模型,后续持续使用 模型的评估,使用测试集,观察模型的好坏 2. 准备训练集和测试集 准备数据集的方法前面已经说过,但是通过前面的内容可知,调用MNIST返回的结果中图形数据是一个Image对象,需要对其进行处理 为了进行数据的处理,接下来学习torchvis

IT之一小佬的博客 3741

用PyTorch来实现手写体数字识别

手写体数字识别

King 3189

Pytorch实战:手写数字识别

Pytorch实战:手写数字识别 1、数据导入 #实战手写数字识别 #************************************************************导入包********************************************************************* import torch , torchvision #该句中torchvision可省略,torchvision可实现数据的处理、导入和预览等 imp

weixin_46141961的博客 1578

【图像识别小项目】Pytorch+Flask识别手写数字

D

十二月未央未眠 2713

蓝牙Mesh安全机制全解析:如何防止你的智能门锁被黑客控制?

本文深入解析蓝牙Mesh安全机制,重点探讨如何保护智能门锁免受黑客攻击。详细介绍了蓝牙Mesh的多层次安全架构,包括密钥管理体系、设备入网流程及实战防护策略,帮助用户构建更安全的智能家居网络。

h3i4j的博客 732

用PyTorch实现MNIST手写数字识别(非常详细)

hello大家好!我又来搬文章了!我就不信还有比这更详细的?! MNIST可以说是机器学习入门的hello word了!导师一般第一个就让你研究MNIST,研究透了,也算基本入门了。好的,今天就来扯一扯学一学。 在本文中,我们将在PyTorch中构建一个简单的卷积神经网络,并使用MNIST数据集训练它识别手写数字。在MNIST数据集上训练分类器可以看作是......

xfxuezhang.cn 16万+

Ubuntu下用QEMU模拟运行OpenBMC

在调试过程中,安装了很多依赖库,具体没有记录。关于kvm,也没理清具体有什么作用。本文仅记录,用QEMU成功的将OpenBMC跑起来的过程,做备忘,也供大家参考。

Sunny的博客 1205

Matlab 曲面平滑与点云处理

曲面平滑是一种常见的数学和计算机图形学技术,可以用来消除噪声、填补数据间隙,以及改善曲面的外观。在点云处理中,曲面平滑也被广泛应用于重建、拟合和可视化等领域。本文将介绍如何使用 Matlab 进行曲面平滑和点云处理,并提供相应的源代码。通过以上步骤,我们可以使用 Matlab 进行曲面平滑和点云处理。你可以根据具体需求调整参数和算法,以获得理想的曲面平滑效果。接下来,我们可以使用平滑算法对三角化的网格进行曲面平滑。以上代码将绘制原始点云和重建后的点云,并在图形中显示坐标轴和图例。表示平滑的迭代次数。

QfcaLinux的博客 753
上一篇: Mysql 数据库常用操作
下一篇: 肺部感染识别
MusicDancing
博客等级 码龄7年 2684粉丝 314原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值