詳解Pytorch自動求導機制
1. 自動求導
在深度學習中,我們通常需要訓練一個模型來最小化損失函數(shù)。這個過程可以通過梯度下降等優(yōu)化算法來實現(xiàn)。梯度是函數(shù)在某一點上的變化率,可以告訴我們?nèi)绾握{(diào)整模型的參數(shù)以使損失函數(shù)最小化。自動求導是一種計算梯度的技術,它允許我們在定義模型時不需要手動推導梯度計算公式。PyTorch 提供了自動求導的功能,使得梯度的計算變得非常簡單和高效。
PyTorch是動態(tài)圖,即計算圖的搭建和運算是同時的,隨時可以輸出結(jié)果。在pytorch的計算圖里只有兩種元素:數(shù)據(jù)(tensor)和 運算(operation)。
運算包括了:加減乘除、開方、冪指對、三角函數(shù)等可求導運算。
數(shù)據(jù)可分為:葉子節(jié)點(leaf node)和非葉子節(jié)點;葉子節(jié)點是用戶創(chuàng)建的節(jié)點,不依賴其它節(jié)點;它們表現(xiàn)出來的區(qū)別在于反向傳播結(jié)束之后,非葉子節(jié)點的梯度會被釋放掉,只保留葉子節(jié)點的梯度,這樣就節(jié)省了內(nèi)存。如果想要保留非葉子節(jié)點的梯度,可以使用
retain_grad()
方法。
torch.tensor 具有如下屬性:
- 查看 是否可以求導
requires_grad
- 查看 運算名稱
grad_fn
- 查看 是否為葉子節(jié)點
is_leaf
- 查看 導數(shù)值
grad
針對requires_grad屬性,自己定義的葉子節(jié)點默認為False,而非葉子節(jié)點默認為True,神經(jīng)網(wǎng)絡中的權(quán)重默認為True。判斷哪些節(jié)點是True/False的一個原則就是從你需要求導的葉子節(jié)點到loss節(jié)點之間是一條可求導的通路。當我們想要對某個Tensor
變量求梯度時,需要先指定requires_grad
屬性為True
,指定方式主要有兩種:
x = torch.tensor(1.).requires_grad_() # 第一種 x = torch.tensor(1., requires_grad=True) # 第二種
總結(jié):
(1)torch.tensor()設置requires_grad關鍵字參數(shù)
(2)查看tensor是否可導,x.requires_grad 屬性
(3)設置葉子變量 leaf variable的可導性,x.requires_grad_()方法
(4)自動求導方法 y.backward() ,直接調(diào)用backward()方法,只會計算對計算圖葉節(jié)點的導數(shù)。
(5)查看求得的到數(shù)值, x.grad 屬性
1.1 梯度計算
自動求導的核心是反向傳播算法(Backpropagation)。反向傳播算法是一種高效地計算梯度的方法,它使用鏈式法則計算每個可導操作的梯度,然后利用這些梯度更新參數(shù)。一旦我們創(chuàng)建了可導張量,PyTorch 將會自動追蹤所有涉及這些張量的操作,并構(gòu)建一個計算圖。計算圖是一個有向無環(huán)圖,表示了計算過程中張量之間的依賴關系。
1.1.1 一階導數(shù)
然后我們舉個例子:z=w*x+b
import torch x=torch.tensor(1.,requires_grad=True) b=torch.tensor(2.,requires_grad=True) w=torch.tensor(3.,requires_grad=True) z=w*x+b z.backward()#反向傳播 print(x.grad)#x導數(shù)值 print(w.grad)#w導數(shù)值 print(b.grad)#b導數(shù)值
運行結(jié)果如下圖:
要想使上面的x,b,w支持求導,必須讓它們?yōu)楦↑c類型,也就是我們給初始值的時候要加個點:“.”。不然的話,就會報錯。
1.1.2 二階導數(shù)
import torch x = torch.tensor(2.).requires_grad_() y = torch.tensor(3.).requires_grad_() z = x * x * y z.backward(create_graph=True) # x.grad = 12 print(x.grad) x.grad.data.zero_() #PyTorch使用backward()時默認會累加梯度,需要手動把前一次的梯度清零 x.grad.backward() #對x一次求導后為2xy,然后再次反向傳播 print(x.grad)
運行結(jié)果如下圖:
1.1.3 向量
在pytorch里面,默認:只能是【標量】對【標量】,或者【標量】對向【量/矩陣】求導
在深度學習中在求導的時候是對損失函數(shù)求導,損失函數(shù)一般都是一個標量,參數(shù)又往往是向量或者是矩陣。
比如有一個輸入層為3節(jié)點的輸入層,輸出層為一個節(jié)點的輸出層,這樣一個簡單的神經(jīng)網(wǎng)絡,針對一組樣本而言,有
X=(x1,x2,x3)=(1.5,2.5,3.5),X是(1,3)維的,輸出層的權(quán)值矩陣為W=(w1,w2,w3)W=(0.2,0.4,0.6)T,這里表示初始化的權(quán)值矩陣,T表示轉(zhuǎn)置,則W表示的是(3,1)維度,偏置項為b=0.1,是一個標量,則可以構(gòu)建一個模型如下:
Y=XW+b,其中W,b就是要求倒數(shù)的變量,這里Y是一個標量,W是向量,b是標量,W,b是葉節(jié)點。
將上面展開得到:
Y=x1*w1+x2*w2*x3*w3+b
import torch # 創(chuàng)建一個多元函數(shù),即Y=XW+b=Y=x1*w1+x2*w2*x3*w3+b,x不可求導,W,b設置可求導 X = torch.tensor([1.5, 2.5, 3.5], requires_grad=False) W = torch.tensor([0.2, 0.4, 0.6], requires_grad=True) b = torch.tensor(0.1, requires_grad=True) Y = torch.add(torch.dot(X, W), b) # 求導,通過backward函數(shù)來實現(xiàn) Y.backward() # 查看導數(shù),也即所謂的梯度 print(W.grad) print(b.grad)
運行截圖如下:
1.2 線性回歸實戰(zhàn)
定義一個y=2*x+1線性方程,下面是一個使用 PyTorch 實現(xiàn)線性回歸模型,并利用自動求導訓練模型的示例:
import torch import numpy as np import torch.nn as nn import torch.optim as optim x_values=[i for i in range(11)] x_train=np.array(x_values,dtype=np.float32) x_train=x_train.reshape(-1,1) y_values=[2*i +1 for i in x_values] y_values=np.array(y_values,dtype=np.float32) y_train=y_values.reshape(-1,1) #這里線性回歸就相當于不加激活函數(shù)的全連接層 class LinearRegression(nn.Module): def __init__(self): super(LinearRegression, self).__init__() self.linear = nn.Linear(1, 1) def forward(self, x): return self.linear(x) #使用GPU訓練 device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") # 創(chuàng)建模型實例和優(yōu)化器 model = LinearRegression() model.to(device) optimizer = optim.SGD(model.parameters(), lr=0.01) # 定義損失函數(shù) criterion = nn.MSELoss() for epoch in range(100): # 創(chuàng)建數(shù)據(jù)集 inputs = torch.from_numpy(x_train).to(device) targets = torch.from_numpy(y_train).to(device) # 前向傳播 outputs = model(inputs) loss = criterion(outputs, targets) # 反向傳播和優(yōu)化器更新 #梯度清零每一次迭代 optimizer.zero_grad() #反向傳播 loss.backward() #更新權(quán)重參數(shù) optimizer.step() #每10輪,打印一下?lián)p失函數(shù) if epoch%10==0: print("epoch {}, loss {}".format(epoch,loss.item())) #使用訓練完的模型進行數(shù)據(jù)的預測 predicted=model(torch.from_numpy(x_train).to(device)) print(predicted) print(targets)
在上面的例子中,我們首先創(chuàng)建了一個簡單的線性回歸模型 LinearRegression
,并創(chuàng)建了一個包含11個樣本的數(shù)據(jù)集。然后,我們定義了損失函數(shù) criterion
和優(yōu)化器 optimizer
,并在訓練循環(huán)中進行模型訓練。
模型訓練中損失值變化如下:
在模型中預測結(jié)果和標簽值對比如下圖:上面的為模型預測結(jié)果,下面的為標簽值
到此這篇關于Pytorch自動求導機制詳解的文章就介紹到這了,更多相關Pytorch自動求導內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Python實現(xiàn)迪杰斯特拉算法并生成最短路徑的示例代碼
這篇文章主要介紹了Python實現(xiàn)迪杰斯特拉算法并生成最短路徑的示例代碼,幫助大家更好的理解和使用python,感興趣的朋友可以了解下2020-12-12PyTorch上搭建簡單神經(jīng)網(wǎng)絡實現(xiàn)回歸和分類的示例
本篇文章主要介紹了PyTorch上搭建簡單神經(jīng)網(wǎng)絡實現(xiàn)回歸和分類的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-04-04numpy如何按條件給元素賦值np.where、np.clip
這篇文章主要介紹了numpy如何按條件給元素賦值np.where、np.clip問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-06-06python3實現(xiàn)ftp服務功能(服務端 For Linux)
這篇文章主要介紹了python3實現(xiàn)ftp服務功能,服務端 For Linux,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-03-03