詳解Pytorch自動(dòng)求導(dǎo)機(jī)制
1. 自動(dòng)求導(dǎo)
在深度學(xué)習(xí)中,我們通常需要訓(xùn)練一個(gè)模型來(lái)最小化損失函數(shù)。這個(gè)過(guò)程可以通過(guò)梯度下降等優(yōu)化算法來(lái)實(shí)現(xiàn)。梯度是函數(shù)在某一點(diǎn)上的變化率,可以告訴我們?nèi)绾握{(diào)整模型的參數(shù)以使損失函數(shù)最小化。自動(dòng)求導(dǎo)是一種計(jì)算梯度的技術(shù),它允許我們?cè)诙x模型時(shí)不需要手動(dòng)推導(dǎo)梯度計(jì)算公式。PyTorch 提供了自動(dòng)求導(dǎo)的功能,使得梯度的計(jì)算變得非常簡(jiǎn)單和高效。
PyTorch是動(dòng)態(tài)圖,即計(jì)算圖的搭建和運(yùn)算是同時(shí)的,隨時(shí)可以輸出結(jié)果。在pytorch的計(jì)算圖里只有兩種元素:數(shù)據(jù)(tensor)和 運(yùn)算(operation)。
運(yùn)算包括了:加減乘除、開(kāi)方、冪指對(duì)、三角函數(shù)等可求導(dǎo)運(yùn)算。
數(shù)據(jù)可分為:葉子節(jié)點(diǎn)(leaf node)和非葉子節(jié)點(diǎn);葉子節(jié)點(diǎn)是用戶創(chuàng)建的節(jié)點(diǎn),不依賴其它節(jié)點(diǎn);它們表現(xiàn)出來(lái)的區(qū)別在于反向傳播結(jié)束之后,非葉子節(jié)點(diǎn)的梯度會(huì)被釋放掉,只保留葉子節(jié)點(diǎn)的梯度,這樣就節(jié)省了內(nèi)存。如果想要保留非葉子節(jié)點(diǎn)的梯度,可以使用
retain_grad()方法。
torch.tensor 具有如下屬性:
- 查看 是否可以求導(dǎo)
requires_grad - 查看 運(yùn)算名稱
grad_fn - 查看 是否為葉子節(jié)點(diǎn)
is_leaf - 查看 導(dǎo)數(shù)值
grad
針對(duì)requires_grad屬性,自己定義的葉子節(jié)點(diǎn)默認(rèn)為False,而非葉子節(jié)點(diǎn)默認(rèn)為True,神經(jīng)網(wǎng)絡(luò)中的權(quán)重默認(rèn)為True。判斷哪些節(jié)點(diǎn)是True/False的一個(gè)原則就是從你需要求導(dǎo)的葉子節(jié)點(diǎn)到loss節(jié)點(diǎn)之間是一條可求導(dǎo)的通路。當(dāng)我們想要對(duì)某個(gè)Tensor變量求梯度時(shí),需要先指定requires_grad屬性為True,指定方式主要有兩種:
x = torch.tensor(1.).requires_grad_() # 第一種 x = torch.tensor(1., requires_grad=True) # 第二種
總結(jié):
(1)torch.tensor()設(shè)置requires_grad關(guān)鍵字參數(shù)
(2)查看tensor是否可導(dǎo),x.requires_grad 屬性
(3)設(shè)置葉子變量 leaf variable的可導(dǎo)性,x.requires_grad_()方法
(4)自動(dòng)求導(dǎo)方法 y.backward() ,直接調(diào)用backward()方法,只會(huì)計(jì)算對(duì)計(jì)算圖葉節(jié)點(diǎn)的導(dǎo)數(shù)。
(5)查看求得的到數(shù)值, x.grad 屬性
1.1 梯度計(jì)算
自動(dòng)求導(dǎo)的核心是反向傳播算法(Backpropagation)。反向傳播算法是一種高效地計(jì)算梯度的方法,它使用鏈?zhǔn)椒▌t計(jì)算每個(gè)可導(dǎo)操作的梯度,然后利用這些梯度更新參數(shù)。一旦我們創(chuàng)建了可導(dǎo)張量,PyTorch 將會(huì)自動(dòng)追蹤所有涉及這些張量的操作,并構(gòu)建一個(gè)計(jì)算圖。計(jì)算圖是一個(gè)有向無(wú)環(huán)圖,表示了計(jì)算過(guò)程中張量之間的依賴關(guān)系。
1.1.1 一階導(dǎo)數(shù)
然后我們舉個(gè)例子: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導(dǎo)數(shù)值 print(w.grad)#w導(dǎo)數(shù)值 print(b.grad)#b導(dǎo)數(shù)值
運(yùn)行結(jié)果如下圖:

要想使上面的x,b,w支持求導(dǎo),必須讓它們?yōu)楦↑c(diǎn)類型,也就是我們給初始值的時(shí)候要加個(gè)點(diǎn):“.”。不然的話,就會(huì)報(bào)錯(cuò)。
1.1.2 二階導(dǎo)數(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()時(shí)默認(rèn)會(huì)累加梯度,需要手動(dòng)把前一次的梯度清零 x.grad.backward() #對(duì)x一次求導(dǎo)后為2xy,然后再次反向傳播 print(x.grad)
運(yùn)行結(jié)果如下圖:

1.1.3 向量
在pytorch里面,默認(rèn):只能是【標(biāo)量】對(duì)【標(biāo)量】,或者【標(biāo)量】對(duì)向【量/矩陣】求導(dǎo)
在深度學(xué)習(xí)中在求導(dǎo)的時(shí)候是對(duì)損失函數(shù)求導(dǎo),損失函數(shù)一般都是一個(gè)標(biāo)量,參數(shù)又往往是向量或者是矩陣。
比如有一個(gè)輸入層為3節(jié)點(diǎn)的輸入層,輸出層為一個(gè)節(jié)點(diǎn)的輸出層,這樣一個(gè)簡(jiǎn)單的神經(jīng)網(wǎng)絡(luò),針對(duì)一組樣本而言,有
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)維度,偏置項(xiàng)為b=0.1,是一個(gè)標(biāo)量,則可以構(gòu)建一個(gè)模型如下:
Y=XW+b,其中W,b就是要求倒數(shù)的變量,這里Y是一個(gè)標(biāo)量,W是向量,b是標(biāo)量,W,b是葉節(jié)點(diǎn)。
將上面展開(kāi)得到:
Y=x1*w1+x2*w2*x3*w3+b
import torch # 創(chuàng)建一個(gè)多元函數(shù),即Y=XW+b=Y=x1*w1+x2*w2*x3*w3+b,x不可求導(dǎo),W,b設(shè)置可求導(dǎo) 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) # 求導(dǎo),通過(guò)backward函數(shù)來(lái)實(shí)現(xiàn) Y.backward() # 查看導(dǎo)數(shù),也即所謂的梯度 print(W.grad) print(b.grad)
運(yùn)行截圖如下:

1.2 線性回歸實(shí)戰(zhàn)
定義一個(gè)y=2*x+1線性方程,下面是一個(gè)使用 PyTorch 實(shí)現(xiàn)線性回歸模型,并利用自動(dòng)求導(dǎo)訓(xù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)
#這里線性回歸就相當(dāng)于不加激活函數(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訓(xùn)練
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
# 創(chuàng)建模型實(shí)例和優(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()))
#使用訓(xùn)練完的模型進(jìn)行數(shù)據(jù)的預(yù)測(cè)
predicted=model(torch.from_numpy(x_train).to(device))
print(predicted)
print(targets)在上面的例子中,我們首先創(chuàng)建了一個(gè)簡(jiǎn)單的線性回歸模型 LinearRegression,并創(chuàng)建了一個(gè)包含11個(gè)樣本的數(shù)據(jù)集。然后,我們定義了損失函數(shù) criterion 和優(yōu)化器 optimizer,并在訓(xùn)練循環(huán)中進(jìn)行模型訓(xùn)練。
模型訓(xùn)練中損失值變化如下:

在模型中預(yù)測(cè)結(jié)果和標(biāo)簽值對(duì)比如下圖:上面的為模型預(yù)測(cè)結(jié)果,下面的為標(biāo)簽值

到此這篇關(guān)于Pytorch自動(dòng)求導(dǎo)機(jī)制詳解的文章就介紹到這了,更多相關(guān)Pytorch自動(dòng)求導(dǎo)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 詳解Pytorch自動(dòng)求導(dǎo)機(jī)制
- 使用pytorch進(jìn)行張量計(jì)算、自動(dòng)求導(dǎo)和神經(jīng)網(wǎng)絡(luò)構(gòu)建功能
- pytorch如何定義新的自動(dòng)求導(dǎo)函數(shù)
- 在?pytorch?中實(shí)現(xiàn)計(jì)算圖和自動(dòng)求導(dǎo)
- Pytorch自動(dòng)求導(dǎo)函數(shù)詳解流程以及與TensorFlow搭建網(wǎng)絡(luò)的對(duì)比
- 淺談Pytorch中的自動(dòng)求導(dǎo)函數(shù)backward()所需參數(shù)的含義
- 關(guān)于PyTorch 自動(dòng)求導(dǎo)機(jī)制詳解
相關(guān)文章
Python進(jìn)行圖片驗(yàn)證碼識(shí)別方法步驟
這篇文章主要給大家介紹了關(guān)于Python進(jìn)行圖片驗(yàn)證碼識(shí)別的相關(guān)資料,基于Python和OpenCV的驗(yàn)證碼識(shí)別系統(tǒng)具有重要的研究意義和實(shí)際應(yīng)用價(jià)值,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-09-09
pytest通過(guò)assert進(jìn)行斷言的實(shí)現(xiàn)
assert斷言是一種用于檢查代碼是否按預(yù)期工作的方法,在pytest中,assert斷言可以用于測(cè)試代碼的正確性,以確保代碼在運(yùn)行時(shí)按照預(yù)期工作,本文就來(lái)介紹一下如何使用,感興趣的可以了解下2023-12-12
使用python向MongoDB插入時(shí)間字段的操作
這篇文章主要介紹了使用python向MongoDB插入時(shí)間字段的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-05-05
Python實(shí)現(xiàn)迪杰斯特拉算法并生成最短路徑的示例代碼
這篇文章主要介紹了Python實(shí)現(xiàn)迪杰斯特拉算法并生成最短路徑的示例代碼,幫助大家更好的理解和使用python,感興趣的朋友可以了解下2020-12-12
PyTorch上搭建簡(jiǎn)單神經(jīng)網(wǎng)絡(luò)實(shí)現(xiàn)回歸和分類的示例
本篇文章主要介紹了PyTorch上搭建簡(jiǎn)單神經(jīng)網(wǎng)絡(luò)實(shí)現(xiàn)回歸和分類的示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-04-04
numpy如何按條件給元素賦值np.where、np.clip
這篇文章主要介紹了numpy如何按條件給元素賦值np.where、np.clip問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06
python3實(shí)現(xiàn)ftp服務(wù)功能(服務(wù)端 For Linux)
這篇文章主要介紹了python3實(shí)現(xiàn)ftp服務(wù)功能,服務(wù)端 For Linux,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03

