如何使用Pytorch搭建模型


Posted in Python onOctober 26, 2020

1  模型定义

和TF很像,Pytorch也通过继承父类来搭建模型,同样也是实现两个方法。在TF中是__init__()和call(),在Pytorch中则是__init__()和forward()。功能类似,都分别是初始化模型内部结构和进行推理。其它功能比如计算loss和训练函数,你也可以继承在里面,当然这是可选的。下面搭建一个判别MNIST手写字的Demo,首先给出模型代码:

import numpy as np
import matplotlib.pyplot as plt 
import torch 
from torch import nn,optim 
from torchsummary import summary 
from keras.datasets import mnist
from keras.utils import to_categorical
device = torch.device('cuda') #——————1——————
 
class ModelTest(nn.Module):
 def __init__(self,device):
  super().__init__() 
  self.layer1 = nn.Sequential(nn.Flatten(),nn.Linear(28*28,512),nn.ReLU())#——————2——————
  self.layer2 = nn.Sequential(nn.Linear(512,512),nn.ReLU()) 
  self.layer3 = nn.Sequential(nn.Linear(512,512),nn.ReLU())
  self.layer4 = nn.Sequential(nn.Linear(512,10),nn.Softmax()) 

  self.to(device) #——————3——————
  self.opt = optim.SGD(self.parameters(),lr=0.01)#——————4——————
 def forward(self,inputs): #——————5——————
  x = self.layer1(inputs)
  x = self.layer2(x)
  x = self.layer3(x)
  x = self.layer4(x)
  return x 
 def get_loss(self,true_labels,predicts): 
  loss = -true_labels * torch.log(predicts) #——————6——————
  loss = torch.mean(loss)
  return loss
 def train(self,imgs,labels): 
  predicts = model(imgs) 
  loss = self.get_loss(labels,predicts)
  self.opt.zero_grad()#——————7——————
  loss.backward()#——————8——————
  self.opt.step()#——————9——————
model = ModelTest(device)
summary(model,(1,28,28),3,device='cuda') #——————10——————

#1:获取设备,以方便后面的模型与变量进行内存迁移,设备名只有两种:'cuda'和'cpu'。通常是在你有GPU的情况下需要这样显式进行设备的设置,从而在需要时,你可以将变量从主存迁移到显存中。如果没有GPU,不获取也没事,pytorch会默认将参数都保存在主存中。

#2:模型中层的定义,可以使用Sequential将想要统一管理的层集中表示为一层。

#3:在初始化中将模型参数迁移到GPU显存中,加速运算,当然你也可以在需要时在外部执行model.to(device)进行迁移。

#4:定义模型的优化器,和TF不同,pytorch需要在定义时就将需要梯度下降的参数传入,也就是其中的self.parameters(),表示当前模型的所有参数。实际上你不用担心定义优化器和模型参数的顺序问题,因为self.parameters()的输出并不是模型参数的实例,而是整个模型参数对象的指针,所以即使你在定义优化器之后又定义了一个层,它依然能优化到。当然优化器你也可以在外部定义,传入model.parameters()即可。这里定义了一个随机梯度下降。

#5:模型的前向传播,和TF的call()类似,定义好model()所执行的就是这个函数。

#6:我将获取loss的函数集成在了模型中,这里计算的是真实标签和预测标签之间的交叉熵。

#7/8/9:在TF中,参数梯度是保存在梯度带中的,而在pytorch中,参数梯度是各自集成在对应的参数中的,可以使用tensor.grad来查看。每次对loss执行backward(),pytorch都会将参与loss计算的所有可训练参数关于loss的梯度叠加进去(直接相加)。所以如果我们没有叠加梯度的意愿的话,那就要在backward()之前先把之前的梯度删除。又因为我们前面已经把待训练的参数都传入了优化器,所以,对优化器使用zero_grad(),就能把所有待训练参数中已存在的梯度都清零。那么梯度叠加什么时候用到呢?比如批量梯度下降,当内存不够直接计算整个批量的梯度时,我们只能将批量分成一部分一部分来计算,每算一个部分得到loss就backward()一次,从而得到整个批量的梯度。梯度计算好后,再执行优化器的step(),优化器根据可训练参数的梯度对其执行一步优化。

#10:使用torchsummary函数显示模型结构。奇怪为什么不把这个继承在torch里面,要重新安装一个torchsummary库。

2  训练及可视化

接下来使用模型进行训练,因为pytorch自带的MNIST数据集并不好用,所以我使用的是Keras自带的,定义了一个获取数据的生成器。下面是完整的训练及绘图代码(50次迭代记录一次准确率):

import numpy as np
import matplotlib.pyplot as plt 
import torch 
from torch import nn,optim 
from torchsummary import summary 
from keras.datasets import mnist
from keras.utils import to_categorical
device = torch.device('cuda') #——————1——————
 
class ModelTest(nn.Module):
 def __init__(self,device):
  super().__init__() 
  self.layer1 = nn.Sequential(nn.Flatten(),nn.Linear(28*28,512),nn.ReLU())#——————2——————
  self.layer2 = nn.Sequential(nn.Linear(512,512),nn.ReLU()) 
  self.layer3 = nn.Sequential(nn.Linear(512,512),nn.ReLU())
  self.layer4 = nn.Sequential(nn.Linear(512,10),nn.Softmax()) 

  self.to(device) #——————3——————
  self.opt = optim.SGD(self.parameters(),lr=0.01)#——————4——————
 def forward(self,inputs): #——————5——————
  x = self.layer1(inputs)
  x = self.layer2(x)
  x = self.layer3(x)
  x = self.layer4(x)
  return x 
 def get_loss(self,true_labels,predicts): 
  loss = -true_labels * torch.log(predicts) #——————6——————
  loss = torch.mean(loss)
  return loss
 def train(self,imgs,labels): 
  predicts = model(imgs) 
  loss = self.get_loss(labels,predicts)
  self.opt.zero_grad()#——————7——————
  loss.backward()#——————8——————
  self.opt.step()#——————9——————
def get_data(device,is_train = True, batch = 1024, num = 10000):
 train_data,test_data = mnist.load_data()
 if is_train:
  imgs,labels = train_data
 else:
  imgs,labels = test_data 
 imgs = (imgs/255*2-1)[:,np.newaxis,...]
 labels = to_categorical(labels,10) 
 imgs = torch.tensor(imgs,dtype=torch.float32).to(device)
 labels = torch.tensor(labels,dtype=torch.float32).to(device)
 i = 0
 while(True):
  i += batch
  if i > num:
   i = batch 
  yield imgs[i-batch:i],labels[i-batch:i] 
train_dg = get_data(device, True,batch=4096,num=60000) 
test_dg = get_data(device, False,batch=5000,num=10000) 

model = ModelTest(device) 
summary(model,(1,28,28),11,device='cuda') 
ACCs = []
import time
start = time.time()
for j in range(20000):
 #训练
 imgs,labels = next(train_dg)
 model.train(imgs,labels)

 #验证
 img,label = next(test_dg)
 predicts = model(img) 
 acc = 1 - torch.count_nonzero(torch.argmax(predicts,axis=1) - torch.argmax(label,axis=1))/label.shape[0]
 if j % 50 == 0:
  t = time.time() - start
  start = time.time()
  ACCs.append(acc.cpu().numpy())
  print(j,t,'ACC: ',acc)
#绘图
x = np.linspace(0,len(ACCs),len(ACCs))
plt.plot(x,ACCs)

准确率变化图如下:

如何使用Pytorch搭建模型

3   注意事项

需要注意的是,pytorch的tensor基于numpy的array,它们是共享内存的。也就是说,如果你把tensor直接插入一个列表,当你修改这个tensor时,列表中的这个tensor也会被修改;更容易被忽略的是,即使你用tensor.detach.numpy(),先将tensor转换为array类型,再插入列表,当你修改原本的tensor时,列表中的这个array也依然会被修改。所以如果我们只是想保存tensor的值而不是整个对象,就要使用np.array(tensor)将tensor的值复制出来。

以上就是如何使用Pytorch搭建模型的详细内容,更多关于Pytorch搭建模型的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
编写Python小程序来统计测试脚本的关键字
Mar 12 Python
安装Python的教程-Windows
Jul 22 Python
Python实现的购物车功能示例
Feb 11 Python
Pytorch入门之mnist分类实例
Apr 14 Python
Sanic框架异常处理与中间件操作实例分析
Jul 16 Python
Windows 64位下python3安装nltk模块
Sep 19 Python
设置python3为默认python的方法
Oct 31 Python
Python魔法方法详解
Feb 13 Python
树莓派与PC端在局域网内运用python实现即时通讯
Jun 22 Python
Python datetime包函数简单介绍
Aug 28 Python
python3 tcp的粘包现象和解决办法解析
Dec 09 Python
理解python中装饰器的作用
Jul 21 Python
使用python-cv2实现视频的分解与合成的示例代码
Oct 26 #Python
python递归函数用法详解
Oct 26 #Python
Python实现LR1文法的完整实例代码
Oct 25 #Python
Python操作word文档插入图片和表格的实例演示
Oct 25 #Python
python时间time模块处理大全
Oct 25 #Python
使用AJAX和Django获取数据的方法实例
Oct 25 #Python
Python Tkinter实例——模拟掷骰子
Oct 24 #Python
You might like
PHP和Shell实现检查SAMBA与NFS Server是否存在
2015/01/07 PHP
PHP编写登录验证码功能 附调用方法
2016/05/19 PHP
Swoole4.4协程抢占式调度器详解
2019/05/23 PHP
关于jquery ajax 调用带参数的webservice返回XML数据一个小细节
2012/07/31 Javascript
select标签模拟/美化方法采用JS外挂式插件
2013/04/01 Javascript
jQuery写的日历(包括日历的样式及功能)
2013/04/23 Javascript
JS自调用匿名函数具体实现
2014/02/11 Javascript
javascript实现2048游戏示例
2014/05/04 Javascript
浅谈页面装载js及性能分析方法
2014/12/09 Javascript
javascript实现下拉提示选择框
2015/12/29 Javascript
详解WordPress开发中get_current_screen()函数的使用
2016/01/11 Javascript
js判断数组key是否存在(不用循环)的简单实例
2016/08/03 Javascript
jQuery多级联动下拉插件chained用法示例
2016/08/20 Javascript
AngularJS实现星星等级评分功能
2016/09/24 Javascript
详解微信小程序开发之下拉刷新 上拉加载
2016/11/24 Javascript
实现jquery放大镜的两种方法
2018/02/22 jQuery
layui--select使用以及下拉框实现键盘选择的例子
2019/09/24 Javascript
vue指令v-html使用过滤器filters功能实例
2019/10/25 Javascript
[02:08]2014DOTA2国际邀请赛 430专访:力争取得小组前二
2014/07/11 DOTA
Python使用Flask框架同时上传多个文件的方法
2015/03/21 Python
python win32 简单操作方法
2017/05/25 Python
解决Python下json.loads()中文字符出错的问题
2018/12/19 Python
Python安装Flask环境及简单应用示例
2019/05/03 Python
django解决订单并发问题【推荐】
2019/07/31 Python
python调用百度API实现人脸识别
2020/11/17 Python
python动态规划算法实例详解
2020/11/22 Python
BookOutlet加拿大:在网上书店购买廉价折扣图书和小说
2018/10/05 全球购物
DOM和JQuery对象有什么区别
2016/11/11 面试题
护理专业优质毕业生自荐书
2014/01/31 职场文书
节能环保口号
2014/06/12 职场文书
2014年销售工作总结
2014/12/01 职场文书
大学生个人学年总结
2015/02/15 职场文书
故意杀人罪辩护词
2015/05/21 职场文书
有关三国演义的读书笔记
2015/06/25 职场文书
Python 中的Sympy详细使用
2021/08/07 Python
利用python做数据拟合详情
2021/11/17 Python