深度学习(12)--Mnist分类任务

一.Mnist分类任务流程详解

1.1.引入数据集

Mnist数据集是官方的数据集,比较特殊,可以直接通过%matplotlib inline自动下载,博主此处已经完成下载,从本地文件中引入数据集。

设置数据路径

from pathlib import Path# 设置数据路径
# PATH = Path("data/minst")
DATA_PATH = Path("data")
PATH = DATA_PATH / "mnist"# PATH.mkdir(parents=True, exist_ok=True)  # 父目录不存在时创建父目录'''
parents:如果父目录不存在,是否创建父目录。
exist_ok:只有在目录不存在时创建目录,目录已存在时不会抛出异常。
'''

读取数据

import pickle
import gzip# 读取数据
'''
gzip.open的作用是解压gzip文件
with gzip.open(PATH.as_posix(), "rb") as f:((x_train, y_train), (x_valid, y_valid), _) = pickle.load(f, encoding="latin-1")
'''
# rb表示以二进制格式打开一个文件用于只读
# 打开PATH路径的文件用以接下来的操作
# 保存数据的文件类型为pickle,所以用pickle.load打开文件,文件此处设置的别名为f
with open(PATH.as_posix(), "rb") as f:((x_train, y_train), (x_valid, y_valid), _) = pickle.load(f, encoding="latin-1")'''
as.posix()的作用:
#返回使用斜杠(/)分割路径的字符串
#将所有连续的正斜杠、反斜杠,统一修改为单个正斜杠
#相对路径 './' 替换为空,'../' 则保持不变。
'''

测试引入数据集是否成功

from matplotlib import pyplot
import numpy as np# 测试数据集是否导入成功
pyplot.imshow(x_train[0].reshape((28, 28)), cmap="gray")
print(x_train.shape)

1.2.数据类型转换

数据需要转换成tensor类型才能参与后续建模训练

import torch# 通过map映射,将x_train等数据全都转为torch.tensor类型。tensor类型才能参与后续建模训练
x_train, y_train, x_valid, y_valid = map(torch.tensor, (x_train, y_train, x_valid, y_valid)
)

测试数据类型是否转换成功

n, c = x_train.shape
x_train, x_train.shape, y_train.min(), y_train.max()
print(x_train, y_train)
print(x_train.shape)
print(y_train.min(), y_train.max())

数据均为tensor类型,转换成功

1.3.设置损失函数

import torch.nn.functional as F# 设置损失函数,此处使用的损失函数为交叉熵
loss_func = F.cross_entropy 

测试损失函数

手动设置初始权重和偏置值进行测试,真实情况下系统会自动帮我们初始化

bs = 64
xb = x_train[0:bs]  # a mini-batch from x ,xb是x_train中0~64项的数
yb = y_train[0:bs]# 实际操作中模型会自动定义权重参数,不用我们手动设置
# 因为输入数据是784x1个像素点,而最后得到的是十个类别,所以权重矩阵的大小为784x10。
weights = torch.randn([784, 10], dtype = torch.float,  requires_grad = True) 
bs = 64
# bias矩阵的大小取决于最后的类别数量,此处的bias矩阵为10x1
bias = torch.zeros(10, requires_grad=True)def model(xb):return xb.mm(weights) + bias  # .mm()是矩阵相乘 .mul()则是对应位相乘# 损失函数是用来度量模型的预测值f(x)与真实值Y的差异程度的运算函数,此处model(xb)得到的是经过权重计算的预测值,yb是真实值。给损失函数传入的参数即为预测值和真实值。
print(loss_func(model(xb), yb))

1.4.神经网络构造 

此处所选用的是传统神经网络完成Minist分类任务

from torch import nn# 创建一个模型类,注意一定要继承于nn.Module(取决于你要创建的网络类型)
class Mnist_NN(nn.Module):def __init__(self):# 调用父类的构造函数super().__init__()# 创建两个隐层 由784->128->256->10self.hidden1 = nn.Linear(784, 128)self.hidden2 = nn.Linear(128, 256)# 创建输出层,由256->10,即最后输出十个类别self.out  = nn.Linear(256, 10)self.dropout = nn.Dropout(0.5)# torch框架需要自己定义前向传播,反向传播由框架自己实现# 传入的x是一个batch x 特征值def forward(self, x):# x经过第一个隐层x = F.relu(self.hidden1(x))# x经过dropout层x = self.dropout(x)# x经过第二个隐藏x = F.relu(self.hidden2(x))# x经过dropout层x = self.dropout(x)# x经过输出层x = self.out(x)return x

测试构造的神经网络

net = Mnist_NN()
print(net)

查看网络中构建好的权重和偏置项 

for name, parameter in net.named_parameters():print(name, parameter,parameter.size())
 

1.5.使用TensorDataset和DataLoader简化数据 

from torch.utils.data import TensorDataset
from torch.utils.data import DataLoader# TensorDataset获取数据,再由DataLoader打包数据传给GPU(包的大小位batch_size)
# 训练集一般打乱顺序,验证集不打乱顺序
train_ds = TensorDataset(x_train, y_train)
train_dl = DataLoader(train_ds, batch_size=bs, shuffle=True)valid_ds = TensorDataset(x_valid, y_valid)
valid_dl = DataLoader(valid_ds, batch_size=bs * 2)def get_data(train_ds, valid_ds, bs):return (DataLoader(train_ds, batch_size=bs, shuffle=True),DataLoader(valid_ds, batch_size=bs * 2),)

1.6.模型训练

优化器设置

from torch import optim
def get_model():model = Mnist_NN() # 使用先前创建的类构造一个网络return model, optim.SGD(model.parameters(), lr=0.001) # 返回值为模型和优化器# 优化器的设置,optim.SGD(),参数分别为:要优化的参数、学习率def loss_batch(model, loss_func, xb, yb, opt=None):# 计算损失,参数为预测值和真实值loss = loss_func(model.forward(xb), yb)  # 预测值由定义的前向传播过程计算处# 如果存在优化器if opt is not None: loss.backward()  # 反向传播,算出更新的权重参数opt.step()  # 执行backward()计算出的权重参数的更新opt.zero_grad()  # torch会进行迭代的累加,通过zero_grad()将之前的梯度清空(不同的迭代之间应当是没有关系的)return loss.item(), len(xb)

常用优化器:

  • 随机梯度下降(SGD, stochastic gradient descent)
  • SGDM(加入了一阶动量)
  • AdaGrad(加入了二阶动量)
  • RMSProp
  • Adam

模型训练

import numpy as np#epoch和batch的关系,
#eg:有10000个数据,batch=100,则一个1epoch需要训练100个batch(1一个epoch就是训练整个数据一次)
# 定义训练函数,传入的参数分别为:迭代的次数、模型、损失函数、优化器、训练集、验证集
def fit(steps, model, loss_func, opt, train_dl, valid_dl):for step in range(steps):# 训练模式:model.train()  for xb, yb in train_dl:loss_batch(model, loss_func, xb, yb, opt)  # 得到由loss_batch更新的权重值# 验证模式:model.eval()   with torch.no_grad():  # 没有梯度,即不更新权重参数# zip将两个矩阵配对,例如两个一维矩阵配对成一个二维矩阵,下述情况中即为一个losses对应一个nums -> [(losses,nums)]。zip*是解包操作,即将二维矩阵又拆分成一维矩阵,并返回拆分得到的一维矩阵。losses, nums = zip(*[loss_batch(model, loss_func, xb, yb) for xb, yb in valid_dl])val_loss = np.sum(np.multiply(losses, nums)) / np.sum(nums)  # 计算平均损失:对应的损失值和样本数相乘的总和 / 总样本数print('当前step:'+str(step), '验证集损失:'+str(val_loss))

二.完整代码 

from pathlib import Path
import pickle
import gzipfrom matplotlib import pyplot
import numpy as npimport torchimport torch.nn.functional as Ffrom torch import nnfrom torch.utils.data import TensorDataset
from torch.utils.data import DataLoaderfrom torch import optimimport numpy as np# 设置数据路径
DATA_PATH = Path("data")
PATH = DATA_PATH / "mnist.pkl"# PATH.mkdir(parents=True, exist_ok=True)'''
parents:如果父目录不存在,是否创建父目录。
exist_ok:只有在目录不存在时创建目录,目录已存在时不会抛出异常。
'''# 读取数据
'''
gzip.open的作用是解压gzip文件
with gzip.open(PATH.as_posix(), "rb") as f:((x_train, y_train), (x_valid, y_valid), _) = pickle.load(f, encoding="latin-1")
'''
# rb表示以二进制格式打开一个文件用于只读
# 打开PATH路径的文件用以接下来的操作
# 保存数据的文件类型为pickle,所以用pickle.load打开文件,文件此处设置的别名为f
with open(PATH.as_posix(), "rb") as f:((x_train, y_train), (x_valid, y_valid), _) = pickle.load(f, encoding="latin-1")'''
as.posix()的作用:
#返回使用斜杠(/)分割路径的字符串
#将所有连续的正斜杠、反斜杠,统一修改为单个正斜杠
#相对路径 './' 替换为空,'../' 则保持不变。
''''''
# 测试数据集是否导入成功
pyplot.imshow(x_train[0].reshape((28, 28)), cmap="gray")
print(x_train.shape)
'''# 数据类型转换为torch# 通过map映射,将x_train等数据全都转为torch.tensor类型。tensor类型才能参与后续建模训练
x_train, y_train, x_valid, y_valid = map(torch.tensor, (x_train, y_train, x_valid, y_valid)
)# 测试数据类型是否转换成功
'''
n, c = x_train.shape
x_train, x_train.shape, y_train.min(), y_train.max()
print(x_train, y_train)
print(x_train.shape)
print(y_train.min(), y_train.max())
'''# 设置损失函数
loss_func = F.cross_entropybs = 64
xb = x_train[0:bs]  # a mini-batch from x ,xb是x_train中0~64项的数
yb = y_train[0:bs]''' 
# 手动初始化进行测试# 实际操作中模型会自动定义权重参数,不用我们手动设置
# 因为输入数据是784x1个像素点,而最后得到的是十个类别,所以权重矩阵的大小为784x10。
weights = torch.randn([784, 10], dtype = torch.float,  requires_grad = True)
bs = 64
# bias矩阵的大小取决于最后的类别数量,此处的bias矩阵为10x1
bias = torch.zeros(10, requires_grad=True)def model(xb):return xb.mm(weights) + bias  # .mm()是矩阵相乘 .mul()则是对应位相乘# 损失函数是用来度量模型的预测值f(x)与真实值Y的差异程度的运算函数,此处model(xb)得到的是经过权重计算的预测值,yb是真实值。给损失函数传入的参数即为预测值和真实值。
print(loss_func(model(xb), yb))
'''# 创建一个模型类,注意一定要继承于nn.Module(取决于你要创建的网络类型)
class Mnist_NN(nn.Module):def __init__(self):# 调用父类的构造函数super().__init__()# 创建两个隐层 由784->128->256->10self.hidden1 = nn.Linear(784, 128)self.hidden2 = nn.Linear(128, 256)# 创建输出层,由256->10,即最后输出十个类别self.out = nn.Linear(256, 10)self.dropout = nn.Dropout(0.5)# torch框架需要自己定义前向传播,反向传播由框架自己实现# 传入的x是一个batch x 特征值def forward(self, x):# x经过第一个隐层x = F.relu(self.hidden1(x))# x经过dropout层x = self.dropout(x)# x经过第二个隐藏x = F.relu(self.hidden2(x))# x经过dropout层x = self.dropout(x)# x经过输出层x = self.out(x)return x'''
# 测试构造的网络模型
net = Mnist_NN()
print(net)打印权重和偏置项
for name, parameter in net.named_parameters():print(name, parameter,parameter.size())
'''# TensorDataset获取数据,再由DataLoader打包数据传给GPU
# 训练集一般打乱顺序,验证集不打乱顺序
train_ds = TensorDataset(x_train, y_train)
train_dl = DataLoader(train_ds, batch_size=bs, shuffle=True)valid_ds = TensorDataset(x_valid, y_valid)
valid_dl = DataLoader(valid_ds, batch_size=bs * 2)def get_data(train_ds, valid_ds, bs):return (DataLoader(train_ds, batch_size=bs, shuffle=True),DataLoader(valid_ds, batch_size=bs * 2),)# 优化器设置
def get_model():model = Mnist_NN()return model, optim.SGD(model.parameters(), lr=0.001)# 优化器的设置,optim.SGD(),参数分别为:要优化的参数、学习率def loss_batch(model, loss_func, xb, yb, opt=None):# 计算损失,参数为预测值和真实值loss = loss_func(model.forward(xb), yb)  # 预测值由定义的前向传播过程计算处# 如果存在优化器if opt is not None:loss.backward()  # 反向传播,算出更新的权重参数opt.step()  # 执行backward()计算出的权重参数的更新opt.zero_grad()  # torch会进行迭代的累加,通过zero_grad()将之前的梯度清空(不同的迭代之间应当是没有关系的)return loss.item(), len(xb)# 模型训练
# epoch和batch的关系,
# eg:有10000个数据,batch=100,则一个1epoch需要训练100个batch(1一个epoch就是训练整个数据一次)
# 定义训练函数,传入的参数分别为:迭代的次数、模型、损失函数、优化器、训练集、验证集
def fit(steps, model, loss_func, opt, train_dl, valid_dl):for step in range(steps):# 训练模式:model.train()for xb, yb in train_dl:loss_batch(model, loss_func, xb, yb, opt)  # 得到由loss_batch更新的权重值# 验证模式:model.eval()with torch.no_grad():  # 没有梯度,即不更新权重参数# zip将两个矩阵配对,例如两个一维矩阵配对成一个二维矩阵,下述情况中即为一个losses对应一个nums -> [(losses,nums)]。zip*是解包操作,即将二维矩阵又拆分成一维矩阵,并返回拆分得到的一维矩阵。losses, nums = zip(*[loss_batch(model, loss_func, xb, yb) for xb, yb in valid_dl])val_loss = np.sum(np.multiply(losses, nums)) / np.sum(nums)  # 计算平均损失:对应的损失值和样本数相乘的总和 / 总样本数print('当前step:'+str(step), '验证集损失:'+str(val_loss))# 输出
train_dl, valid_dl = get_data(train_ds, valid_ds, bs)
model, opt = get_model()
fit(25, model, loss_func, opt, train_dl, valid_dl)# 准确率的计算
correct = 0
total = 0
for xb,yb in valid_dl:outputs = model(xb)_, predicted = torch.max(outputs.data,1)  # 返回最大的值和对应的列索引(列索引在此处就是对应的类别)    (, 0)则返回行索引total += yb.size(0)  # yb的样本数correct += (predicted == yb).sum().item( ) # .sum()返回验证正确了的样本数,item()从tensor数据类型中取值,方便后续的画图等(tensor数据类型不好画图)print('Accuracy of the network on the 10000 test image: %d %%' %(100*correct/total))

三.输出结果

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

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

相关文章

1E,Jarvis March

四个问题: 一,Jarvis March算法借鉴了什么算法? 二,如何确定初始点 三,如何获取凸包的边? 四,Jarvis March算法的好处在哪里? 首先看第一个问题, 一,Jarvis …

了解UDP发送过快导致的问题和对应解决方案

在当今这个以数据为核心的时代,企业对于数据传输的速度和稳定性有着日益增长的需求。UDP凭借其低延迟和高效率的特性,在实时通信和大规模数据传输领域扮演着关键角色。然而,UDP的无连接特性和缺乏可靠性也给数据传输带来了挑战,尤…

尝试创建若依系统项目(vue3+element-plus+vite) 持续更新...

若依官网:RuoYi 若依官方网站 |后台管理系统|权限管理系统|快速开发框架|企业管理系统|开源框架|微服务框架|前后端分离框架|开源后台系统|RuoYi|RuoYi-Vue|RuoYi-Cloud|RuoYi框架|RuoYi开源|RuoYi视频|若依视频|RuoYi开发文档|若依开发文档|Java开源框架|Java|Spri…

[SWPUCTF 2021 新生赛]easy_md5

用get给name 用post给password 二个值不相等MD5相等 可以通过php的弱类型绕过 $a!$b md5($a)md5($b)找到不同 a 和 a和 a和b,两者的md5值均为0e开头的形式

Open3D 深度图像转点云

目录 一、算法原理1、算法过程2、主要函数3、算法源码二、代码实现三、结果展示1、深度图像2、点云四、测试数据

LSTR: 基于Transformer的车道形状预测

LSTR: 基于Transformer的车道形状预测 项目背景与意义LSTR的特性和功能最新更新即将推出的功能模型资源库数据准备设置环境训练和评估引用许可证贡献致谢 在计算机视觉领域,车道检测是自动驾驶和智能交通系统中的关键技术之一。我们推出了一种名为LSTR的车道形状预测…

mysql 锁知识汇总

目录 一、锁1.1 什么是锁?1.2 全局锁1.2.1 定义1.2.2 应用场景1.2.3 会出现的问题1.2.4 解决方法 1.3 表级锁1.3.1 表锁1.3.2 元数据锁(MDL)1.3.3 意向锁1.3.4 AUTO-INC锁 1.4 行级锁1.4.1 记录锁(Record Lock)1.4.2 间隙锁(Gap Lock)1.4.3 N…

【C++11】包装器

包装器 一、function包装器1、function包装器介绍2、包装示例3、function包装器统一类型4、function包装器简化代码5、function包装器的意义 二、bind包装器1、bind包装器介绍(1)bind包装器(2)调用bind的一般形式 2、bind包装器绑…

vite和vue-cli实现原理和优化及区别

Vite: 1. 实现原理: Vite 是一个基于 ESModule 的构建工具。它利用原生 ESModule 的特性,将每个文件作为一个模块,通过浏览器去解析和执行,而不需要提前将文件打包成一个单独的 bundle。Vite 利用浏览器的原生 ESMod…

LeetCode 热题 100 | 链表(中上)

目录 1 141. 环形链表 1.1 哈希表 1.2 快慢指针 2 142. 环形链表 II 2.1 哈希表 2.2 快慢指针 3 21. 合并两个有序链表 4 2. 两数相加 菜鸟做题第三周,语言是 C 1 141. 环形链表 1.1 哈希表 解题思路:遍历链表,在哈希表中…

Linux下grep命令详解

grep #文件内容过滤显示 #在指定的普通文件中查找并显示含有指定字符串的行,也可与管道符一起使用格式: grep-参数 查找条件 文件名 参数: 示例: [rootnode1 ~]# grep -n "root" /etc/passwd # -n&a…

Vue3学习记录(一)--- 组合式API之基础概念和变量声明

一、组合式API基础 1、简介 ​ 组合式 API (Composition API) 是Vue3和Vue2的v2.7之后版本中的全新特性,是一系列API的的集合(响应式API、生命周期钩子、依赖注入等等),其风格是基于函数的组合,以一种更直观、更灵活…

【Unity3D小技巧】Unity3D中UI控制解决方案

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客 大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 一、前言 在开发中总是会控制UI界面,如何优雅的控制UI界面是…

02-Java抽象工厂模式 ( Abstract Factory Pattern )

抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂 该超级工厂又称为其他工厂的工厂 在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类 每个生成的工厂都能按照工厂模式提供对象 …

CDS view与替代对象

一,简介 替代对象是指用一个CDS view指派给一个透明表或常规数据库视图,使得透明表或常规数据库视图的访问重定向到该CDS view。 替代有诸多要求: 字段数量一致且同名对应,顺序可以不一致对应的字段数据类型长度等必须一致CDS v…

在Linux下搭建自己的私有maven库并部署和发布自定义jar依赖和自定义maven插件(三)开发和发布自己开发的maven插件

系列文章目录 在Linux下搭建自己的私有maven库并部署和发布自定义jar依赖和自定义maven插件(二)发布自己开发的jar包 文章目录 系列文章目录在Linux下搭建自己的私有maven库并部署和发布自定义jar依赖和自定义maven插件(二)发布自己开发的jar包 前言一、插件需求二、maven自定…

前端JavaScript篇之对 rest 参数的理解、ES6中模板语法与字符串处理

目录 对 rest 参数的理解ES6中模板语法与字符串处理 对 rest 参数的理解 rest参数是一种在函数定义中使用的特殊语法,它允许函数接受任意数量的参数,并将它们收集到一个数组中。通俗地说,rest参数就像是一个容器,用来存放函数接收…

帮管客CRM SQL注入漏洞

免责声明:文章来源互联网收集整理,请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失,均由使用者本人负责,所产生的一切不良后果与文章作者无关。该…

2024年美赛B题:寻找潜水器 Searching for Submersibles 思路模型代码解析

2024年美赛B题:寻找潜水器 Searching for Submersibles 思路模型代码解析 【点击最下方群名片,加入群聊,获取更多思路与代码哦~】 问题翻译 海上游轮迷你潜艇(MCMS)是一家位于希腊的公司,专门制造能够将人…

如何在Windows部署GoLand并通过SSH远程连接Linux服务器

文章目录 1. 安装配置GoLand2. 服务器开启SSH服务3. GoLand本地服务器远程连接测试4. 安装cpolar内网穿透远程访问服务器端4.1 服务器端安装cpolar4.2 创建远程连接公网地址 5. 使用固定TCP地址远程开发 本文主要介绍使用GoLand通过SSH远程连接服务器,并结合cpolar内…