欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用Pytorch搭建模型的步驟

 更新時(shí)間:2020年11月16日 08:58:32   作者:頎周  
這篇文章主要介紹了使用Pytorch搭建模型的步驟,幫助大家更好的理解和使用Pytorch,進(jìn)行機(jī)器學(xué)習(xí),感興趣的朋友可以了解下

  本來(lái)是只用Tenorflow的,但是因?yàn)門F有些Numpy特性并不支持,比如對(duì)數(shù)組使用列表進(jìn)行切片,所以只能轉(zhuǎn)戰(zhàn)Pytorch了(pytorch是支持的)。還好Pytorch比較容易上手,幾乎完美復(fù)制了Numpy的特性(但還有一些特性不支持),怪不得熱度上升得這么快。

1  模型定義

  和TF很像,Pytorch也通過(guò)繼承父類來(lái)搭建自定義模型,同樣也是實(shí)現(xiàn)兩個(gè)方法。在TF中是__init__()和call(),在Pytorch中則是__init__()和forward()。功能類似,都分別是初始化模型內(nèi)部結(jié)構(gòu)和進(jìn)行推理。其它功能比如計(jì)算loss和訓(xùn)練函數(shù),你也可以繼承在里面,當(dāng)然這是可選的。下面搭建一個(gè)判別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:獲取設(shè)備,以方便后面的模型與變量進(jìn)行內(nèi)存遷移,設(shè)備名只有兩種:'cuda'和'cpu'。通常是在你有GPU的情況下需要這樣顯式進(jìn)行設(shè)備的設(shè)置,從而在需要時(shí),你可以將變量從主存遷移到顯存中。如果沒(méi)有GPU,不獲取也沒(méi)事,pytorch會(huì)默認(rèn)將參數(shù)都保存在主存中。

  #2:模型中層的定義,可以使用Sequential將想要統(tǒng)一管理的層集中表示為一層。

  #3:在初始化中將模型參數(shù)遷移到GPU顯存中,加速運(yùn)算,當(dāng)然你也可以在需要時(shí)在外部執(zhí)行model.to(device)進(jìn)行遷移。

  #4:定義模型的優(yōu)化器,和TF不同,pytorch需要在定義時(shí)就將需要梯度下降的參數(shù)傳入,也就是其中的self.parameters(),表示當(dāng)前模型的所有參數(shù)。實(shí)際上你不用擔(dān)心定義優(yōu)化器和模型參數(shù)的順序問(wèn)題,因?yàn)閟elf.parameters()的輸出并不是模型參數(shù)的實(shí)例,而是整個(gè)模型參數(shù)對(duì)象的指針,所以即使你在定義優(yōu)化器之后又定義了一個(gè)層,它依然能優(yōu)化到。當(dāng)然優(yōu)化器你也可以在外部定義,傳入model.parameters()即可。這里定義了一個(gè)隨機(jī)梯度下降。

  #5:模型的前向傳播,和TF的call()類似,定義好model()所執(zhí)行的就是這個(gè)函數(shù)。

  #6:我將獲取loss的函數(shù)集成在了模型中,這里計(jì)算的是真實(shí)標(biāo)簽和預(yù)測(cè)標(biāo)簽之間的交叉熵。

  #7/8/9:在TF中,參數(shù)梯度是保存在梯度帶中的,而在pytorch中,參數(shù)梯度是各自集成在對(duì)應(yīng)的參數(shù)中的,可以使用tensor.grad來(lái)查看。每次對(duì)loss執(zhí)行backward(),pytorch都會(huì)將參與loss計(jì)算的所有可訓(xùn)練參數(shù)關(guān)于loss的梯度疊加進(jìn)去(直接相加)。所以如果我們沒(méi)有疊加梯度的意愿的話,那就要在backward()之前先把之前的梯度刪除。又因?yàn)槲覀兦懊嬉呀?jīng)把待訓(xùn)練的參數(shù)都傳入了優(yōu)化器,所以,對(duì)優(yōu)化器使用zero_grad(),就能把所有待訓(xùn)練參數(shù)中已存在的梯度都清零。那么梯度疊加什么時(shí)候用到呢?比如批量梯度下降,當(dāng)內(nèi)存不夠直接計(jì)算整個(gè)批量的梯度時(shí),我們只能將批量分成一部分一部分來(lái)計(jì)算,每算一個(gè)部分得到loss就backward()一次,從而得到整個(gè)批量的梯度。梯度計(jì)算好后,再執(zhí)行優(yōu)化器的step(),優(yōu)化器根據(jù)可訓(xùn)練參數(shù)的梯度對(duì)其執(zhí)行一步優(yōu)化。

  #10:使用torchsummary函數(shù)顯示模型結(jié)構(gòu)。奇怪為什么不把這個(gè)繼承在torch里面,要重新安裝一個(gè)torchsummary庫(kù)。

2  訓(xùn)練及可視化

  接下來(lái)使用模型進(jìn)行訓(xùn)練,因?yàn)閜ytorch自帶的MNIST數(shù)據(jù)集并不好用,所以我使用的是Keras自帶的,定義了一個(gè)獲取數(shù)據(jù)的生成器。下面是完整的訓(xùn)練及繪圖代碼(50次迭代記錄一次準(zhǔn)確率):

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):
 #訓(xùn)練
 imgs,labels = next(train_dg)
 model.train(imgs,labels)

 #驗(yàn)證
 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)

  準(zhǔn)確率變化圖如下:

3  其它使用技巧

3.1  tensor與array

  需要注意的是,pytorch的tensor基于numpy的array,它們是共享內(nèi)存的。也就是說(shuō),如果你把tensor直接插入一個(gè)列表,當(dāng)你修改這個(gè)tensor時(shí),列表中的這個(gè)tensor也會(huì)被修改;更容易被忽略的是,即使你用tensor.detach.numpy(),先將tensor轉(zhuǎn)換為array類型,再插入列表,當(dāng)你修改原本的tensor時(shí),列表中的這個(gè)array也依然會(huì)被修改。所以如果我們只是想保存tensor的值而不是整個(gè)對(duì)象,就要使用np.array(tensor)將tensor的值復(fù)制出來(lái)。

3.2  自定義層

  在TF中,自定義模型通常繼承keras的Model,而自定義層則是繼承l(wèi)ayers.Layer,繼承不同的父類通常會(huì)造成初學(xué)者的困擾。而在pytorch中,自定義層與自定義模型一樣,都是繼承nn.Module。Pytorch將層與模型都看成了模塊,這很容易理解。的確,層與模型之間本來(lái)也沒(méi)有什么明確的界限。并且定義方式與上面定義模型的方式一樣,也是實(shí)現(xiàn)兩個(gè)函數(shù)即可。代碼示例如下:

import torch  
from torch import nn 

class ParaDeconv(nn.Module):#——————1——————
 def __init__(self,in_n,out_n):
  super().__init__() 
  self.w = nn.Parameter(torch.normal(0,0.01,size = [in_n,out_n]),requires_grad=True)
  self.b = nn.Parameter(torch.normal(0,0.01,size = [out_n]),requires_grad=True) 
 def forward(self,inputs):
  x = torch.matmul(inputs,self.w)
  x = x + self.b
  return x 
layer = ParaDeconv(2,3)
y = layer(torch.ones(100,2))#——————2——————
loss = torch.sum(y)#——————3——————
loss.backward()#——————4——————
for i in layer.parameters():#——————5——————
 print(i.grad)#——————6——————

  #1:自定義一個(gè)全連接層。層中可訓(xùn)練參數(shù)的定義是使用nn.Parameter,如果直接使用torch.tensor是無(wú)法在#5中遍歷到的。

  #2/3/4:輸入并計(jì)算loss,然后反向傳播計(jì)算參數(shù)梯度。

  #5/6:輸出完成反向傳播后層參數(shù)的梯度。

  以上定義的層可以和pytorch自帶的層一樣直接插入模型中使用。

3.3  保存/加載

3.3.1  保存/加載模型

  有兩種方式,一種是保存模型的參數(shù):

torch.save(model.state_dict(), PATH)         #保存  
model.load_state_dict(torch.load(PATH),strict=True) #加載

  這種加載方式需要先定義模型,然后再加載參數(shù)。如果你定義的模型參數(shù)名與保存的參數(shù)對(duì)不上,就會(huì)出錯(cuò)。但如果把strict修改成False,不嚴(yán)格匹配,它就會(huì)只匹配對(duì)應(yīng)上的鍵值,不會(huì)因多出或缺少的參數(shù)而報(bào)錯(cuò)。

  另一種是直接保存模型:

torch.save(model, PATH) #保存
model = torch.load(PATH) #加載

  這種方式看似方便,實(shí)際上更容易出錯(cuò)。因?yàn)閜ython不能保存整個(gè)模型的類,所以它只能保存定義類的代碼文件位置,以在加載時(shí)獲取類的結(jié)構(gòu)。如果你改變了定義類的代碼位置,就有可能因?yàn)檎也坏筋惗鲥e(cuò)。

3.3.2  保存訓(xùn)練點(diǎn)
  當(dāng)你要保存某個(gè)訓(xùn)練階段的狀態(tài),比如包含優(yōu)化器參數(shù)、模型參數(shù)、訓(xùn)練迭代次數(shù)等,可以進(jìn)行如下操作:

#保存訓(xùn)練點(diǎn)
torch.save({
      'epoch': epoch,
      'model_state_dict': model.state_dict(),
      'optimizer_state_dict': optimizer.state_dict(),
      'loss': loss
      }, PATH)
#加載訓(xùn)練點(diǎn)
model = TheModelClass(*args, **kwargs)
optimizer = TheOptimizerClass(*args, **kwargs)

checkpoint = torch.load(PATH)

model.load_state_dict(checkpoint['model_state_dict'])
optimizer.load_state_dict(checkpoint['optimizer_state_dict'])
epoch = checkpoint['epoch']
loss = checkpoint['loss']

  和保存模型一樣,也是使用torch.save()。它很靈活,可以保存字典,因此讀取的時(shí)候也按照字典索引讀取即可。當(dāng)然要注意,并不是任何類型都能保存的,這里保存的四個(gè)類型分別是:

  1. int

  2. collections.OrderedDict

  3. collections.OrderedDict

  4. list 

3.4  修改模型參數(shù)

  Pytorch沒(méi)有提供額外的方式讓我們修改模型參數(shù),我們可以使用上面加載模型參數(shù)的方式來(lái)修改參數(shù)。對(duì)于某個(gè)參數(shù),我們只要把鍵值和對(duì)應(yīng)要修改的值放在字典中傳入load_state_dict即可。如果沒(méi)傳入所有的參數(shù),記得把strict設(shè)為False。示例如下:

model.load_state_dict({'weight':torch.tensor([0.])},strict=False) #修改模型參數(shù)

  參數(shù)名,也就是鍵值,和對(duì)應(yīng)的參數(shù)shape可以通過(guò)model.state_dict()查看。

以上就是使用Pytorch搭建模型的步驟的詳細(xì)內(nèi)容,更多關(guān)于Pytorch搭建模型的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Python 解決空列表.append() 輸出為None的問(wèn)題

    Python 解決空列表.append() 輸出為None的問(wèn)題

    在本篇文章里小編給大家整理了一篇關(guān)于Python 解決空列表.append() 輸出為None的問(wèn)題的相關(guān)內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。
    2021-05-05
  • python3操作注冊(cè)表的方法(Url protocol)

    python3操作注冊(cè)表的方法(Url protocol)

    使用python操作注冊(cè)表的方法最近學(xué)習(xí)了一下,現(xiàn)在做一下筆記,由于對(duì)Python語(yǔ)言的使用還不是很熟練,所以寫不出高大上的結(jié)構(gòu)
    2020-02-02
  • 淺談一下Python中閉包的作用

    淺談一下Python中閉包的作用

    這篇文章主要介紹了淺談一下Python中閉包的作用,閉包特點(diǎn)是返回的函數(shù)還引用了外層函數(shù)的局部變量,所以,要正確使用閉包,就要確保引用的局部變量在函數(shù)返回后不能變,需要的朋友可以參考下
    2023-12-12
  • 解決Pytorch修改預(yù)訓(xùn)練模型時(shí)遇到key不匹配的情況

    解決Pytorch修改預(yù)訓(xùn)練模型時(shí)遇到key不匹配的情況

    這篇文章主要介紹了解決Pytorch修改預(yù)訓(xùn)練模型時(shí)遇到key不匹配的情況,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Python使用matplotlib創(chuàng)建Gif動(dòng)圖的思路

    Python使用matplotlib創(chuàng)建Gif動(dòng)圖的思路

    這篇文章主要介紹了Python使用matplotlib創(chuàng)建Gif動(dòng)圖,我們將討論matplotlib提供的名為“Animation”的動(dòng)畫庫(kù)之一,Python二維繪圖庫(kù)是Matplolib可以輕松創(chuàng)建繪圖、直方圖、條形圖、散點(diǎn)圖等,需要的朋友可以參考下
    2022-04-04
  • Tensor和NumPy相互轉(zhuǎn)換的方法

    Tensor和NumPy相互轉(zhuǎn)換的方法

    本文主要介紹了Tensor和NumPy相互轉(zhuǎn)換的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • 列舉Python中吸引人的一些特性

    列舉Python中吸引人的一些特性

    這篇文章主要介紹了Python中吸引人的一些特性,有助于初學(xué)者或者開發(fā)者在選擇編程語(yǔ)言時(shí)用作參考或入門指引,需要的朋友可以參考下
    2015-04-04
  • Python  Asyncio模塊實(shí)現(xiàn)的生產(chǎn)消費(fèi)者模型的方法

    Python Asyncio模塊實(shí)現(xiàn)的生產(chǎn)消費(fèi)者模型的方法

    這篇文章主要介紹了Python Asyncio模塊實(shí)現(xiàn)的生產(chǎn)消費(fèi)者模型的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • python騰訊語(yǔ)音合成實(shí)現(xiàn)過(guò)程解析

    python騰訊語(yǔ)音合成實(shí)現(xiàn)過(guò)程解析

    這篇文章主要介紹了python騰訊語(yǔ)音合成實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-08-08
  • python詞云庫(kù)wordcloud的使用方法與實(shí)例詳解

    python詞云庫(kù)wordcloud的使用方法與實(shí)例詳解

    這篇文章主要介紹了python詞云庫(kù)wordcloud的使用方法與實(shí)例詳解,需要的朋友可以參考下
    2020-02-02

最新評(píng)論