基于PyTorch的MNIST手写体分类实战

news2024/9/21 11:11:16

第2章对MNIST数据做了介绍,描述了其构成方式及其数据的特征和标签的含义等。了解这些有助于编写合适的程序来对MNIST数据集进行分析和识别。本节将使用同样的数据集完成对其进行分类的任务。

3.1.1  数据图像的获取与标签的说明

MNIST数据集的详细介绍在第2章中已经完成,读者可以使用相同的代码对数据进行获取,代码如下:

import numpy as np
x_train = np.load("./dataset/mnist/x_train.npy")
y_train_label = np.load("./dataset/mnist/y_train_label.npy")

基本数据的获取与第2章类似,这里就不过多阐述了,不过需要注意的是,在第2章介绍数据集时只使用了图像数据,没有对标签进行说明,在这里重点对数据标签,也就是y_train_label进行介绍。

我们可以使用下面语句打印出数据集的前10个标签:

print(y_train_label[:10])

结果如下:

import numpy as np
import torch
x_train = np.load("./dataset/mnist/x_train.npy")
y_train_label = np.load("./dataset/mnist/y_train_label.npy")
x = torch.tensor(y_train_label[:5],dtype=torch.int64)
# 定义一个张量输入,因为此时有 5 个数值,且最大值为9,类别数为10
# 所以我们可以得到 y 的输出结果的形状为 shape=(5,10),即5行12列
y = torch.nn.functional.one_hot(x, 10)  # 一个参数张量x,10为类别数
ptint(y) 

结果如下:

tensor([[0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
        [0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 1]])

可以看到,one_hot的作用是将一个序列转换成以one_hot形式表示的数据集。所有的行或者列都被设置成0,而每个特定的位置都对应一个1来表示,如图3-1所示。

图3-1  one_hot形式表示的数据集

对于MNIST数据集的标签来说,这实际上就是一个60 000幅图片的60 000×10大小的矩阵张量[60 000,10]。前面的数指的是数据集中图片的个数为60 000个,后面的10指的是10个列向量。

下面使用PyTorch 2.0框架完成手写体的识别。

3.1.2  模型的准备(多层感知机)

在第2章已经讲过了,PyTorch最重要的一项内容是模型的准备与设计,而模型的设计最关键的一点就是了解输出和输入的数据结构类型。

通过第2章有关图像去噪的演示,读者已经了解了我们的输入数据格式是一个[28,28]大小的二维图像。而通过对数据结构的分析,我们可以知道,对于每个图形都有一个确定的分类结果,也就是0~10的一个确定数字。

下面将按这个想法来设计模型。从前面对图像的分析来看,对整体图形进行判别的一个基本想法就是将图像作为一个整体直观地进行判别,因此基于这种解决问题的思路,简单的模型设计就是同时对图像所有参数进行计算,即使用一个多层感知机(Multi-Layer Perceptron,MLP)对图像进行分类。整体的模型设计结构如图3-2所示。

图3-2  整体的模型设计结构

从图3-2可以看到,一个多层感知机模型就是将数据输入后,分散到每个模型的节点(隐藏层),进行数据计算后,再将计算结果输出到对应的输出层中。多层感知机的模型结构如下:

class NeuralNetwork(nn.Module):
    def __init__(self):
        super(NeuralNetwork, self).__init__()
        self.flatten = nn.Flatten()
        self.linear_relu_stack = nn.Sequential(
            nn.Linear(28*28,312),
            nn.ReLU(),
            nn.Linear(312, 256),
            nn.ReLU(),
            nn.Linear(256, 10)
        )
    def forward(self, input):
        x = self.flatten(input)
        logits = self.linear_relu_stack(x)
        return logits

3.1.3  损失函数的表示与计算

第2章使用了MSELoss作为目标图形与预测图形的损失值,而在本例中,我们需要预测的目标是图形的“分类”,而不是图形表示本身,因此我们需要寻找并使用一种新的能够对类别归属进行“计算”的函数。

本例所使用的交叉熵损失函数为torch.nn.CrossEntropyLoss。PyTorch官方网站对其介绍如下:

CLASS torch.nn.CrossEntropyLoss(weight=None, size_average=None, ignore_index=- 100,reduce=None, reduction='mean', label_smoothing=0.0)

该损失函数计算输入值(Input)和目标值(Target)之间的交叉熵损失。交叉熵损失函数CrossEntropyLoss可用于训练单类别或者多类别的分类问题。给定参数weight时,会为传递进来的每个类别的计算数值重新加载一个修正权重。当数据集分布不均衡时,这是很有用的。

同样需要注意的是,因为torch.nn.CrossEntropyLoss内置了Softmax运算,而Softmax的作用是计算分类结果中最大的那个类。从图3-3所示的对PyTorch 2.0中CrossEntropyLoss的实现可以看到,此时CrossEntropyLoss已经在计算的同时实现了Softmax计算,因此在使用torch.nn.CrossEntropyLoss作为损失函数时,不需要在网络的最后添加Softmax层。此外,label应为一个整数,而不是One-Hot编码形式。

图3-3  使用torch.nn.CrossEntropyLoss()作为损失函数

CrossEntropyLoss示例代码如下:

import torch
y = torch.LongTensor([0])
z = torch.Tensor([[0.2,0.1,-0.1]])
criterion = torch.nn.CrossEntropyLoss()
loss = criterion(z,y)
print(loss)	

CrossEntropyLoss的数学公式较为复杂,建议学有余力的读者查阅相关内容进行学习,目前只需要掌握这方面内容即可。

3.1.4  基于PyTorch的手写体识别的实现

下面介绍基于PyTorch的手写体识别的实现。通过前文的介绍,我们还需要定义深度学习的优化器部分,在这里采用Adam优化器,相关代码如下:

model = NeuralNetwork()
optimizer = torch.optim.Adam(model.parameters(), lr=2e-5)   #设定优化函数

在这个实战案例中首先需要定义模型,之后将模型参数传入优化器中,lr是对学习率的设定,根据设定的学习率进行模型计算。完整的手写体识别模型如下:

import os
os.environ['CUDA_VISIBLE_DEVICES'] = '0' #指定GPU编号
import torch
import numpy as np
from tqdm import tqdm
batch_size =320#设定每次训练的批次数
epochs=1024   	#设定训练次数
#device="cpu"	#PyTorch的特性,需要指定计算的硬件,如果没有GPU,就使用CPU进行计算
device="cuda"	#在这里默认使用GPU,如果读者运行出现问题,可以将其改成CPU模式

#设定的多层感知机网络模型
class NeuralNetwork(torch.nn.Module):
    def __init__(self):
        super(NeuralNetwork, self).__init__()
        self.flatten = torch.nn.Flatten()
        self.linear_relu_stack = torch.nn.Sequential(
            torch.nn.Linear(28*28,312),
            torch.nn.ReLU(),
            torch.nn.Linear(312, 256),
            torch.nn.ReLU(),
            torch.nn.Linear(256, 10)
        )

    def forward(self, input):
        x = self.flatten(input)
        logits = self.linear_relu_stack(x)
        return logits

model = NeuralNetwork()
model = model.to(device)                	#将计算模型传入GPU硬件等待计算
model = torch.compile(model)            	#PyTorch 2.0的特性,加速计算速度
loss_fu = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=2e-5)  	#设定优化函数

#载入数据
x_train = np.load("../../dataset/mnist/x_train.npy")
y_train_label = np.load("../../dataset/mnist/y_train_label.npy")
train_num = len(x_train)//batch_size

#开始计算
for epoch in range(20):
    train_loss = 0
    for i in range(train_num):
        start = i * batch_size
        end = (i + 1) * batch_size
        train_batch = torch.tensor(x_train[start:end]).to(device)
        label_batch = torch.tensor(y_train_label[start:end]).to(device)
        pred = model(train_batch)
        loss = loss_fu(pred,label_batch)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        train_loss += loss.item()  # 记录每个批次的损失值

    # 计算并打印损失值
    train_loss /= train_num
    accuracy = (pred.argmax(1) == label_batch).type(torch.float32).sum().item() / batch_size
    print("train_loss:", round(train_loss,2),"accuracy:",round(accuracy,2))

此时模型的训练结果如图3-4所示。

图3-4  模型的训练结果

可以看到随着模型循环次数的增加,模型的损失值在降低,而准确率在增高,具体请读者自行验证测试。

本文节选自《PyTorch 2.0深度学习从零开始学》。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1135176.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于springboot实现就业信息管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现就业信息管理系统演示 摘要 随着信息化时代的到来,管理系统都趋向于智能化、系统化,就业信息管理系统也不例外,但目前国内仍都使用人工管理,市场规模越来越大,同时信息量也越来越庞大,人…

最新Unity DOTS教程之BlobAsset核心机制分析

最近DOTS发布了正式的版本, 我们来分享一下DOTS里面BlobAsset机制,方便大家上手学习掌握Unity DOTS开发。 BlobAsset 概叙 DOTS提供了BlobAsset机制来把数据生成高效的二进制数据。BlobAsset的数据是不可变的。BlobAsset只支持非托管类型数据。支持Burst编译器编译…

计时的vue写法

<el-input type"text" id"timetext" value"00时00分00秒" readonly></el-input> <el-button type"button" click"start()">开始</el-button> <el-button type"button" click"st…

用Visual Studio(VS)开发UNIX/Linux项目

目录 FTP是免不了的 正确设置头文件 组织项目结构 创建何种项目类型 FTP自动上传 大部分具有Windows开发经验的程序员会比较喜欢使用Visual Studio&#xff0c;而大部分Unix/Linux程序员则喜欢使用UltraEdit直接在主机上写代码。 为什么直接在主机上写代码呢&#xff0c;因…

软考系列(系统架构师)- 2015年系统架构师软考案例分析考点

试题一 软件架构&#xff08;质量属性效用树、架构风险、依够点、权衡点&#xff09; 【问题1】&#xff08;12分&#xff09; 在架构评估过程中&#xff0c;质量属性效用树&#xff08;utility tree&#xff09;是对系统质量属性进行识别和优先级排序的重要工具。请给出合适的…

第20章 Netty

20.1 说说IO的交互流程 难度:★ 重点:★ 白话解析 这道题主要是用来帮助理解后面题目的,IO交互主要分为两种:本地IO和网络IO。 1、本地IO:数据在磁盘上,通过系统调用read()方法读取数据到内核空间的缓冲区,然后再读取到 用户空间的缓冲区,这就是IO的交互过程。 2、网…

华为---DHCP中继代理简介及示例配置

DHCP中继代理简介 IP动态获取过程中&#xff0c;客户端&#xff08;DHCP Client&#xff09;总是以广播&#xff08;广播帧及广播IP报文&#xff09;方式来发送DHCPDISCOVER和DHCPREQUEST消息的。如果服务器&#xff08;DHCP Server&#xff09;和 客户端不在同一个二层网络(二…

【100天精通Python】Day71:Python可视化_一文掌握Seaborn库的使用《一》_数据分布可视化,数据关系可视化,示例+代码

目录 1. 数据分布的可视化 1.1 直方图&#xff08;Histograms&#xff09; 1.2 核密度估计图&#xff08;Kernel Density Estimation Plot&#xff09; 1.3 箱线图&#xff08;Box Plot&#xff09; 1.4 小提琴图&#xff08;Violin Plot&#xff09; ​编辑1.5 散点图&am…

蓝桥杯双周赛算法心得——铺地板(质因数)

大家好&#xff0c;我是晴天学长&#xff0c;这是第二周的蓝桥杯的双周赛&#xff0c;题可出的又好又灵活啊&#xff01;真不错&#xff01; 1) .铺地板 2) .算法思路 1.导入java.util包中的Scanner类&#xff0c;以从用户那里读取输入。 2.main方法是程序的入口点。 3.创建一…

单片机仿真设计打包项目

小伙伴们在仿真设计时会遇到各种各样的问题&#xff0c;网上的资料可能不全或者很贵。 这篇也不单纯为了打广告&#xff0c;主要是希望实实在在帮到学单片机的同学&#xff0c;大家不要一有问题就各种找dai zuo&#xff0c;做的好不好是一回事儿&#xff0c;关键是它费&#x…

成都无人机测绘公司 无人机测绘服务 无人机航测作业

无人机测绘是传统航空摄影测量方式的重要补充方式&#xff0c;它具有灵活、高效、适用范围广、生产周期短等优势&#xff0c;在小区域和飞行困难地区获取高分辨率图像具有明显的优势。目前&#xff0c;无人机测绘主要应用于土地监管、灾害应急处理、城市规划管理等方面。那么&a…

el-date-picker如何回显

后端传输过来起止时间&#xff0c;需要回显在 el-date-picker中 未修改前的代码&#xff1a; 问题整改&#xff1a;需要将时间转换为Date类型 修改后的代码 setTime(date){if (date!null){this.value.push(new Date(date.startTime))this.value.push(new Date(date.endTime))c…

一个Entity Framework Core的性能优化案例

概要 本文提供一个EF Core的优化案例&#xff0c;主要介绍一些EF Core常用的优化方法&#xff0c;以及在优化过程中&#xff0c;出现性能反复的时候的解决方法&#xff0c;并澄清一些对优化概念的误解&#xff0c;例如AsNoTracking并不包治百病。 本文使用的是Dotnet 6.0和EF…

前端工作流异常时候 yarn检查异常信息

HDSF中执行异常的原因查询&#xff0c;查看yarn的报错

Kafka - 消息队列的两种模式

文章目录 消息队列的两种模式点对点模式&#xff08;Point-to-Point&#xff0c;P2P&#xff09;发布/订阅模式&#xff08;Publish/Subscribe&#xff0c;Pub/Sub&#xff09; 小结 消息队列的两种模式 消息队列确实可以根据消息传递的模式分为 点对点模式发布/订阅模式 这两…

【Linux】tail命令使用

tail 命令可用于查看文件的内容&#xff0c;有一个常用的参数 -f 常用于查阅正在改变的日志文件。 语法 tail [参数] [文件] tail命令 -Linux手册页 著者 由保罗鲁宾、大卫麦肯齐、伊恩兰斯泰勒和吉姆梅耶林撰写。 命令选项及作用 执行令 tail --help 执行命令结果 参…

数据传输如何做才安全:保障隐私的5大秘诀!

在当今数字时代&#xff0c;数据传输安全和隐私保护变得越来越重要。随着网络攻击和数据泄露事件的增加&#xff0c;保护数据传输安全和隐私已经成为当务之急。以下是保障隐私的五大秘诀&#xff1a; 使用加密技术&#xff1a;加密技术是保护数据传输安全的最常用方法。通过使用…

【设计模式】第1节:UML类图

本系列文章主要参考自B站用户以诺爱编程的《设计模式》系列视频&#xff0c;以及王争的《设计模式之美》系列文章。 本文参考自30分钟学会UML类图。 UML图有很多种&#xff0c;一般只要掌握类图、用例图、时序图就可以完成大部分工作。本文算是学习设计模式的一道前菜&#x…

数字人解决方案——解决ER-NeRF/RAD-NeRF人像分割的问题

一、训练数据人像分割 训练ER-NeRF或者RAD-NeRF时&#xff0c;在数据处理时&#xff0c;其中有一步是要把人像分割出来&#xff0c;而且人像要分成三块&#xff0c;人的头部&#xff0c;人的有脖子&#xff0c;人的身体部分&#xff0c;效果如下&#xff1a; 从上面的分割的结…

【设计模式】第2节:七大设计原则

一、七大设计原则 七大原则提出的目的是降低对象之间的耦合度&#xff0c;提高程序的可复用性、可扩展性和可维护性。 1.单一职责原则 Single Responsibility Principle&#xff0c;SRP原则&#xff1a;一个类只负责一个功能领域中的相应职责。或者可以定义为&#xff1a;就一…