Pytorch的讲解及实战·MNIST数据集手写数字识别

目录

一、前言与pytorch的下载

1、前言

2、下载pytorch

①创建虚拟环境

②下载pytorch(cpu版)

③测试pytorch是否下载成功

④使用jupyter notebook 但是使用不了torch的解决方法

二、pytorch的使用

1、Tensor的数据类型

①torch.FloatTensor

②torch.IntTensor

③torch.rand

④torch.randn

⑤torch.range

⑥torch.zeros

⑦torch.ones

2、Tensor的运算

①torch.abs

②torch.add

③torch.clamp

④torch.div

⑤torch.mul

⑥torch.pow

⑦torch.mm

3、tensor的自动梯度

4、torch搭建神经网络层次

①torch.nn.Sequential:

②torch.nn.Conv2d

③ torch.nn.MaxPool2d

④ torch.nn.Dropout

⑤torch.nn.Linear

⑥torch.nn.ReLU

⑦torch.optim

5、损失函数

①torch.nn.MSELoss

②torch.nn.L1Loss

③torch.nn.CrossEntropyLoss

6、torchvision.transforms

①torchvision.transforms.Resize

②torchvision.transforms.Scale

③torchvision.transforms.CenterCrop

④torchvision.transforms.RandomCrop

⑤torchvision.transforms.RandomHorizontalFlip

⑥torchvision.transforms.RandomVerticalFlip

⑦torchvision.transforms.ToTensor

⑧torchvision.transforms.ToPILImage

⑨torchvision.transforms.Normalize

三、实际操作

1、导入库

2、导入pytorch中的mnist数据集

3、展示数据集规模及些许图片

4、构建模型

5、训练

6、测试


一、前言与pytorch的下载

1、前言

对于神经网络的相关知识大家可以先学习学习小编的这篇博客:

数学建模之神经网络相关理论知识_神经网络误差建模-CSDN博客

2、下载pytorch

①创建虚拟环境

打开anaconda prompt,输入以下指令,创建虚拟环境

conda create -n pytorch #虚拟环境名字为pytorch
conda activate pytorch  #激活pytorch环境

②下载pytorch(cpu版)

进入pytorch官网https://pytorch.org/

复制Run this Command右边的这句话,再pytorch环境下运行,不过这样下载太慢了,建议换成清华镜像源或者豆瓣镜像源下载

③测试pytorch是否下载成功

在终端上输入:

python
import torch
torch.__version__

④使用jupyter notebook 但是使用不了torch的解决方法

conda install nb_conda

随后jupyter notebook的目录变成这样了,多一个“conda”

二、pytorch的使用

1、Tensor的数据类型

①torch.FloatTensor

用于生成数据类型为float型的tensor

②torch.IntTensor

torch.IntTensor用于生成数据类型为整型的Tensor

③torch.rand

用于生成数据类型为浮点型且维度指定的随机Tensor,和在NumPy中使用numpy.rand生成随机数的方法类似,随机生成的浮点数据在0~1区间均匀分布。

④torch.randn

用于生成数据类型为浮点型且维度指定的随机Tensor,和在NumPy中使用numpy.randn生成随机数的方法类似,随机生成的浮点数据符合标准正太分布。

⑤torch.range

用于生成数据类型为浮点型且起始范围和结束范围的Tensor,所以传递给torch.range的参数有三个,分别为起始值,结束值,步长,其中步长用于指定从起始值到结束值每步的数据间隔。

⑥torch.zeros

用于生成数据类型为浮点型且维度指定的Tensor,不过这个浮点型的Tensor中的元素值全部为0。

⑦torch.ones

用于生成数据类型为浮点型且维度指定的Tensor,不过这个浮点型的Tensor中的元素值全部为1。

2、Tensor的运算

①torch.abs

将参数传递到torch.abs后返回输入参数的绝对值作为输出,输入参数必须是一个Tensor数据类型的变量。

②torch.add

将参数传递到 torch.add后返回输入参数的求和结 果作为输出,输入参数既可以全部是Tensor数据类型的变量,也可以一 个是Tensor数据类型的变量,另一个是标量。

③torch.clamp

对输入参数按照自定义的范围进行裁剪,最后将参数裁剪的结果作为输出。所以输入参数一共有三个,分别是需要进行裁剪的Tensor数据类型的变量、裁剪的上边界和裁剪的下边界,具体的裁剪过程是:使用变量中的每个元素分别和裁剪的上边界及裁剪的下边界的值进行比较,如果元素的值小于裁剪的下边界的值,该元素就被重写成裁剪的下边界的值;同理,如果元素的值大于裁剪的上边界的值,该元素就被重写成裁剪的上边界。

④torch.div

将参数传递到torch.div后返回输入参数的求商结果作为输出,同样,参与运算的参数可以全部是Tensor数据类型的变量, 也可以是Tensor数据类型的变量和标量的组合。

⑤torch.mul

将参数传递到 torch.mul后返回输入参数求积的结 果作为输出,参与运算的参数可以全部是Tensor数据类型的变量,也可 以是Tensor数据类型的变量和标量的组合。

⑥torch.pow

将参数传递到torch.pow后返回输入参数的求幂结果作为输出,参与运算的参数可以全部是Tensor数据类型的变量,也可以是Tensor数据类型的变量和标量(几次方)的组合。

⑦torch.mm

将参数传递到 torch.mm后返回输入参数的求积结果作为输出,不过这个求积的方式和之前的torch.mul运算方式不太一样,torch.mm运用矩阵之间的乘法规则进行计算,所以被传入的参数会 被当作矩阵进行处理,参数的维度自然也要满足矩阵乘法的前提条件, 即前一个矩阵的行数必须和后一个矩阵的列数相等,否则不能进行计算。

3、tensor的自动梯度

torch.autograd包的主要功能是完成神经网络后向传播中的链式求 导,手动实现链式求导的代码会给我们带来很大的困扰,而 torch.autograd 包中丰富的类减少了这些不必要的麻烦。实现自动梯度功 能的过程大致为:先通过输入的Tensor数据类型的变量在神经网络的前 向传播过程中生成一张计算图,然后根据这个计算图和输出结果准确计 算出每个参数需要更新的梯度,并通过完成后向传播完成对参数的梯度更新。

在实践中完成自动梯度需要用到torch.autograd包中的Variable类对 我们定义的Tensor数据类型变量进行封装,在封装后,计算图中的各个节点就是一个Variable对象,这样才能应用自动梯度的功能。

4、torch搭建神经网络层次

①torch.nn.Sequential:

Sequential类是torch.nn中的一种序列容器,通过在容器中嵌套各种实现神经网络中具体功能相关的类,来完成对神经网络模型的搭建,并且参数会按照我们定义好的序列自动传递下去。我们可以将嵌套在容器中的各个部分看作各种不同的模块,这些模块可以自由组合。模块的加入 般有两种方式 种是 在以上代码中使用的直接嵌套,另种是以Orderdict 有序字典的方式进行传入,这两种方式的唯一的区别是,使用Orderdict搭建的模型的每个模块都有自定义的名字而Sequential默认使用从开始的数字序列作为每个模块的名字。

②torch.nn.Conv2d

用于搭建卷积神经网络的卷积层,主要参数是:输入通道数、输出通道数、卷积核大小、卷积核移动步长和padding的值(用于对边界像素的填充)

③ torch.nn.MaxPool2d

实现卷积神经网络的最大池化层,主要参数是:池化窗口的大小,池化窗口移动步长和padding的值。

④ torch.nn.Dropout

用于防止卷积神经网络在训练过程中发生过拟合,原理是以一定的随机概率将卷积神经网络模型的部分参数归零,以达到减少相邻两层神经连接的目的。

⑤torch.nn.Linear

torch.nn.Linear类用于定义模型的线性层, 即完成前面提到的不同的层之间的线性变换。torch.nn.Linear类接收的参 数有三个,分别是输入特征数、输出特征数和是否使用偏置,设置是否 使用偏置的参数是一个布尔值,默认为True,即使用偏置。在实际使用 的过程中,我们只需将输入的特征数和输出的特征数传递给 torch.nn.Linear类,就会自动生成对应维度的权重参数和偏置,对于生成 的权重参数和偏置,我们的模型默认使用了一种比之前的简单随机方式 更好的参数初始化方法。

⑥torch.nn.ReLU

torch.nn.ReLU类属于非线性激活分类,在定义时默认不需要传入参数。当然,在 torch.nn包中还有许多非线性激活 函数类可供选择,比如之前讲到的PReLU、LeakyReLU、Tanh、 Sigmoid、Softmax等。

⑦torch.optim

pytorch的torch.optim包中提供了非常多的可实现参数自动优化的类,比如SGD、AdaGrad、RMSProp、Adam等, 这些类都可以被直接调用,使用起来也非常方便。(例如:torch.optim.Adam类中输入的是被优化的参数和学习速率的初始值,如果没有输入学习速率的初始值,那么默认使用0.001 这个值。因为我们需要优化的是模型中的全部参数,所以传递给 torch.optim.Adam类的参数是models.parameters)

5、损失函数

没必要弄清楚下面集中损失函数到底是怎么构建的,只需要知道损失函数是什么就行了,可以看这篇博客了解一下:

损失函数(lossfunction)的全面介绍(简单易懂版)-CSDN博客

①torch.nn.MSELoss

torch.nn.MSELoss类使用均方误差函数对损失值进行计算,在定义类的对象时不用传入任何参数,但在使用实例 时需要输入两个维度一样的参数方可进行计算。

②torch.nn.L1Loss

torch.nn.L1Loss类使用平均绝对误差函数对 损失值进行计算,同样,在定义类的对象时不用传入任何参数,但在使 用实例时需要输入两个维度一样的参数进行计算。

③torch.nn.CrossEntropyLoss

torch.nn.CrossEntropyLoss类用 于计算交叉熵,在定义类的对象时不用传入任何参数,在使用实例时需要输入两个满足交叉熵的计算条件的参数

6、torchvision.transforms

①torchvision.transforms.Resize

用于对载入的图片数据按我 们需求的大小进行缩放。传递给这个类的参数可以是一个整型数据,也 可以是一个类似于(h,w)的序列,其中,h代表高度,w代表宽度,但 是如果使用的是一个整型数据,那么表示缩放的宽度和高度都是这个整 型数据的值。

②torchvision.transforms.Scale

用于对载入的图片数据按我们 需求的大小进行缩放,用法和torchvision.transforms.Resize类似。

③torchvision.transforms.CenterCrop

用于对载入的图片以图 片中心为参考点,按我们需要的大小进行裁剪。传递给这个类的参数可 以是一个整型数据,也可以是一个类似于(h,w)的序列。

④torchvision.transforms.RandomCrop

用于对载入的图片按我们需要的大小进行随机裁剪。传递给这个类的参数可以是一个整型数据,也可以是一个类似于(h,w)的序列。

⑤torchvision.transforms.RandomHorizontalFlip

用于对载入的图片按随机概率进行水平翻转。我们可以通过传递给这个类的参数自 定义随机概率,如果没有定义,则使用默认的概率值0.5。

⑥torchvision.transforms.RandomVerticalFlip

用于对载入的图片按随机概率进行垂直翻转。我们可以通过传递给这个类的参数自定义随机概率,如果没有定义,则使用默认的概率值0.5。

⑦torchvision.transforms.ToTensor

用于对载入的图片数据进行类型转换,将之前构成PIL图片的数据转换成Tensor数据类型的变量,让PyTorch能够对其进行计算和处理。

⑧torchvision.transforms.ToPILImage

用于将Tensor变量的数据转换成PIL图片数据,主要是为了方便图片内容的显示。

⑨torchvision.transforms.Normalize

用均值和标准差归一化张量图像,一般将std与mean均设置为[0.5,0.5,0.5]

三、实际操作

1、导入库

import torch 
from torchvision import datasets, transforms 
from torch.autograd import Variable
import torchvision
import matplotlib.pyplot as plt

2、导入pytorch中的mnist数据集

transform = transforms.Compose([transforms.ToTensor(),transforms.Lambda(lambda x: x.repeat(3,1,1)),transforms.Normalize(mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5))])   
#ToTensor()能够把灰度范围从0-255变换到0-1之间,
# 而后面的transform.Normalize()则把0-1变换到(-1,1).
# 具体地说,对每个通道而言,Normalize执行以下操作:
# image=(image-mean)/std
# 其中mean和std分别通过(0.5,0.5,0.5)和(0.5,0.5,0.5)进行指定。原来的0-1最小值0则变成(0-#0.5)/0.5=-1,而最大值1则变成(1-0.5)/0.5=1.
data_train=datasets.MNIST(root="D:/jupyter_notebook/pytorch/train/",train =True,transform = transform,download = True)
data_test=datasets.MNIST(root="D:/jupyter_notebook/pytorch/test/",train =False,transform = transform,download=True)
data_loader_train =torch.utils.data.DataLoader(dataset = data_train,batch_size = 64,shuffle = True #打乱数据)
data_loader_test =torch.utils.data.DataLoader(dataset = data_test,batch_size = 64,shuffle = True #打乱数据)

3、展示数据集规模及些许图片

images,labels = next(iter(data_loader_train))
img = torchvision.utils.make_grid(images)img = img.numpy().transpose(1,2,0)
std = [0.5,0.5,0.5]
mean = [0.5,0.5,0.5]
img = img*std + mean
print([labels[i] for i in range(64)] )
plt.imshow(img)
#展示数据集与测试集大小
print("train_data:",data_train.train_data.size())
print("train_labels:",data_train.train_labels.size())
print("test_data:",data_test.test_data.size())
print("test_labels:",data_test.test_labels.size())

规模大小如下图:

4、构建模型

class Model(torch.nn.Module): def __init__ (self): super(Model , self).__init__ () self.convl=torch.nn.Sequential( torch.nn.Conv2d (3,64,kernel_size=3,stride=1,padding=1) , torch.nn.ReLU(), torch.nn.Conv2d(64,128,kernel_size=3, stride=1,padding=1), torch.nn.ReLU() , torch.nn.MaxPool2d(stride=2,kernel_size=2)) self.dense=torch.nn.Sequential( torch.nn.Linear(14*14*128,1024), torch.nn.ReLU(),torch.nn.Dropout(p= 0.5), torch.nn.Linear(1024, 10)) def forward(self, x) : x = self.convl(x) x = x . view(-1 , 14*14*128) x = self. dense(x) return xmodel = Model() 
cost= torch.nn.CrossEntropyLoss() 
optimizer = torch.optim.Adam(model.parameters())
print(model)

该神经网络结构如下图:

为什么这样构建?我们来梳理一下:

先看conv1序列:

(0)conv2d卷积层用于特征提取,用一个模板去图像上寻找与它相似的区域,与卷积核模式越相似,激活值越高,从而实现特征提取

(1)激活函数对特征进行非线性变换,赋予多层神经网络具有深度的意义

(2)、(3)与上面类似

(4)池化层:经过池化后的图像基本上没什么差别,但是图像的尺寸减少了一半, 所以池化层是可以帮助我们剔除一些冗余像素或减少后面计算量。

再看dense序列

(0)Linear层即全连接层,起到概括图片局部高级特征的作用,输入一个25088*1的列向量,输出一个1024*1的列向量,可以这么理解它的作用:例如7可以拆分为上部分的“-”以及下部分的“1”,2可以拆分为上部分的弧与下部分的“-”,根据经过conv1处理后的图片,判断出图片有无这1024个局部高级特征,例如短横、小弯曲等等

(1)激活函数对特征进行非线性变换,赋予多层神经网络具有深度的意义

(2)Dropout用于防止卷积神经网络在训练过程中发生过拟合,原理是以一定的随机概率将卷积神经网络模型的部分参数归零,以达到减少相邻两层神经连接的目的

(3)Linear层:输入一个1024*1的列向量,输出一个10*1的列向量,分别代表了利用1024个局部高级特征,测算出训练或者测试时的图片对应数字0、1、2、3、4、5、6、7、8、9共十个数字下的得分函数,分值越高,可能性越大,那么需要左乘一个10*1024的权重矩阵。

5、训练

n_epochs = 5
for epoch in range (n_epochs):runnig_loss = 0.0running_correct = 0.0print("Epoch {}/{}".format(epoch,n_epochs))print("-"*10)i=0for data in data_loader_train:i=i+1X_train, y_train = dataX_train, y_train = Variable(X_train), Variable(y_train)outputs = model(X_train)_,pred = torch.max(outputs.data, 1)optimizer.zero_grad()loss = cost(outputs, y_train)loss.backward()optimizer.step()runnnig_loss += loss.item()running_correct += torch.sum(pred == y_train.data)print("times:{}".format(i))testing_correct = 0for data in data_loader_test:X_test, y_test = dataX_test, y_test = Variable(X_test), Variable(y_test)outputs = model(X_test)_, pred = torch.max(outputs.data,1)testing_correct += torch.sum(pred == y_test.data)print("Loss is:{:.4f},Train Accuracy is:{:.4f}%, Test Accuracy is:{:.4f}".format(runnig_loss/len(data_train),100*running_correct/len(data_train),100*testing_correct/len(data_test)))

第五个epoch训练结果如图:

准确率还有98.7%,属实是不错了

6、测试

data2_loader_test= torch.utils.data.DataLoader(dataset=data_test, batch_size = 4 , shuffle = True)
X_test2, y_test2= next (iter(data2_loader_test)) 
inputs = Variable(X_test2) 
pred = model(inputs) 
_,pred = torch.max(pred, 1) 
print ( "Predict Label is :",[i for i in pred.data]) 
print ("Real Label is :", [ i for i in y_test2]) 
img = torchvision.utils.make_grid(X_test2) 
img = img.numpy().transpose(1,2,0) 
std= [0.5,0.5,0.5] 
mean = [0.5,0.5,0.5] 
img = img*std+mean
plt.imshow (img)

测试结果如下图:

好的,本实验到此结束啦,实验的目的从来不只是为了识别这么几个数字,更重要的是,利用这个实验学会搭建出一个完整的神经网络,了解各个层的作用,了解pytorch各个函数的实际用途

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

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

相关文章

DragonEnglish:COCA20000+单词+释义

去年的时候接触到了 COCA20000 单词,对这种给单词特定顺序的方式蛮感兴趣的。因为我当时接触的版本只有单词或者单词释义的版本,所以我直接通过各种方式给它搭配了音标例句发音,然后每100个切割成1份,分成了 202 个文件来学习&…

[设计模式 Go实现] 创建型~工厂方法模式

工厂方法模式使用子类的方式延迟生成对象到子类中实现。 Go中不存在继承 所以使用匿名组合来实现 代码实现 package factorymethod//Operator 是被封装的实际类接口 type Operator interface {SetA(int)SetB(int)Result() int }//OperatorFactory 是工厂接口 type OperatorF…

Unity坦克大战开发全流程——开始场景——开始界面

开始场景——开始界面 step1:设置UI 反正按照这张图拼就行了 step2:写脚本 前面的拼UI都是些比较机械化的工作,直到这里写代码的时候才真正开始有点意思了,从这里开始,我们就要利用面向对象的思路来进行分析&#xff1…

Vue独立组件开发-动态组件

文章目录 一、前言二、实现三、优化四、总结五、最后 一、前言 在开发中&#xff0c;你经常会遇到这么一种情况&#xff1a;根据条件动态地切换某个组件&#xff0c;或动态地选择渲染某个组件。 Vue 提供了另外一个内置的组件 <component> 和 is 特性&#xff0c;可以更…

Visual Studio 任务列表

任务列表 帮助我们快速找到注释位置&#xff08;用在需要反复查找修改的地方&#xff09; 使用//todo&#xff1a;注释的内容就会显示在任务列表中。 任务列表如何打开&#xff1f; 视图—任务列表 &#xff08;CTRlwt&#xff09; 创建自定义令牌&#xff1a; 在 “工具”…

Go语言中的HTTP重定向

大家好&#xff0c;我是你们可爱的编程小助手&#xff0c;今天我们要一起探讨如何使用Go语言实现HTTP重定向&#xff0c;让我们开始吧&#xff01; 大家都知道&#xff0c;网站开发中有时候需要将用户的请求从一个URL导向到另一个URL。比如说&#xff0c;你可能想将旧的URL结构…

matplotlib单变量和双变量可视化

使用seaborn 库的tips数据集&#xff0c;其中包含了某餐厅服务员收集的顾客付小费的相关数据&#xff08;评论区&#xff09; 单变量可视化 直方图 直方图是观察单个变量最常用的方法。这些值是经过"装箱"&#xff08;bin&#xff09;处理的 直方图会将数据分组后绘…

2023最新租号平台系统源码支持单独租用或合租使用

这是一款租号平台源码&#xff0c;采用常见的租号模式。目前网络上还很少见到此类类型的源码。 平台的主要功能如下&#xff1a; 支持单独租用或采用合租模式&#xff1b; 采用易支付通用接口进行支付&#xff1b; 添加邀请返利功能&#xff0c;以便站长更好地推广&#xf…

数模学习day05-插值算法

插值算法有什么作用呢&#xff1f; 答&#xff1a;数模比赛中&#xff0c;常常需要根据已知的函数点进行数据、模型的处理和分析&#xff0c;而有时候现有的数据是极少的&#xff0c;不足以支撑分析的进行&#xff0c;这时就需要使用一些数学的方法&#xff0c;“模拟产生”一些…

私有部署ELK,搭建自己的日志中心(三)-- Logstash的安装与使用

一、部署ELK 上文把采集端filebeat如何使用介绍完&#xff0c;现在随着数据的链路&#xff0c;继续~~ 同样&#xff0c;使用docker-compose部署&#xff1a; version: "3" services:elasticsearch:container_name: elasticsearchimage: elastic/elasticsearch:7.9…

c++简易AI

今天小编一时雅兴大发&#xff0c;做了一个c的简易AI&#xff0c;还是很垃圾的&#xff01; 题外话&#xff08;每期都会有&#xff09;&#xff1a;我的蛋仔名叫酷影kuying&#xff0c;大家能加我好友吗&#xff1f; 上代码咯&#xff01; #include<bits/stdc.h> #in…

全球电商平台API数据稳定接入

API是什么&#xff1f; API就是接口&#xff0c;就是通道&#xff0c;负责一个程序和其他软件的沟通&#xff0c;本质是预先定义的函数。”比如&#xff1a;电脑需要调用手机里面的信息&#xff0c;这时候你会拿一根数据线将电脑手机连接起来&#xff0c;电脑和手机上连接数据…