如何使用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内置函数dir详解
Apr 14 Python
python中的格式化输出用法总结
Jul 28 Python
用Python设计一个经典小游戏
May 15 Python
pandas进行数据的交集与并集方式的数据合并方法
Jun 27 Python
python requests爬取高德地图数据的实例
Nov 10 Python
浅谈pandas筛选出表中满足另一个表所有条件的数据方法
Feb 08 Python
Python之lambda匿名函数及map和filter的用法
Mar 05 Python
django中forms组件的使用与注意
Jul 08 Python
Python如何实现动态数组
Nov 02 Python
Tensorflow训练模型越来越慢的2种解决方案
Feb 07 Python
Python ADF 单位根检验 如何查看结果的实现
Jun 03 Python
详解pandas赋值失败问题解决
Nov 29 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类的使用 实例代码讲解
2009/12/28 PHP
PHP下 Mongodb 连接远程数据库的实例代码
2017/08/30 PHP
一些mootools的学习资源
2010/02/07 Javascript
js左侧三级菜单导航实例代码
2013/09/13 Javascript
javascript中typeof的使用示例
2013/12/19 Javascript
transport.js和jquery冲突问题的解决方法
2015/02/10 Javascript
基于js实现投票的实例代码
2015/08/04 Javascript
AngularJS入门心得之directive和controller通信过程
2016/01/25 Javascript
JavaScript添加随滚动条滚动窗体的方法
2016/02/23 Javascript
AngularJS ng-style中使用filter
2016/09/21 Javascript
简单理解Vue条件渲染
2016/12/03 Javascript
详解js的事件处理函数和动态创建html标记方法
2016/12/16 Javascript
VUE开发一个图片轮播的组件示例代码
2017/03/06 Javascript
Vue中插入HTML代码的方法
2018/09/21 Javascript
基于Vue-Cli 打包自动生成/抽离相关配置文件的实现方法
2018/12/09 Javascript
js取0-9随机取4个数不重复的数字代码实例
2019/03/27 Javascript
JS co 函数库的含义和用法实例总结
2020/04/08 Javascript
原生js实现自定义消息提示框
2020/11/19 Javascript
jQuery实现增删改查
2020/12/22 jQuery
[33:33]完美世界DOTA2联赛PWL S2 FTD.C vs SZ 第二场 11.27
2020/11/30 DOTA
写了个监控nginx进程的Python脚本
2012/05/10 Python
Python内置函数Type()函数一个有趣的用法
2015/02/18 Python
python 计算两个列表的相关系数的实现
2019/08/29 Python
Python下载的11种姿势(小结)
2020/11/18 Python
营销与策划专业毕业生求职信
2013/11/01 职场文书
房产委托公证书样本
2014/04/04 职场文书
财务会计专业自荐书
2014/06/30 职场文书
乡村教师党员四风问题对照检查材料思想汇报
2014/10/08 职场文书
会计岗位职责
2015/02/03 职场文书
Javascript中的解构赋值语法详解
2021/04/02 Javascript
Python3 类型标注支持操作
2021/06/02 Python
MySQL和Oracle批量插入SQL的通用写法示例
2021/11/17 MySQL
Python数据结构之队列详解
2022/03/21 Python
详解Python+OpenCV绘制灰度直方图
2022/03/22 Python
使用Docker容器部署rocketmq单机的全过程
2022/04/03 Servers
浅谈音视频 pts dts基本概念及理解
2022/08/05 数码科技