如何使用pytorch自動求梯度

構(gòu)建深度學(xué)習(xí)模型的基本流程就是:搭建計(jì)算圖锦庸,求得損失函數(shù)机蔗,然后計(jì)算損失函數(shù)對模型參數(shù)的導(dǎo)數(shù),再利用梯度下降法等方法來更新參數(shù)甘萧。搭建計(jì)算圖的過程萝嘁,稱為“正向傳播”,這個是需要我們自己動手的扬卷,因?yàn)槲覀冃枰O(shè)計(jì)我們模型的結(jié)構(gòu)牙言。由損失函數(shù)求導(dǎo)的過程,稱為“反向傳播”怪得,求導(dǎo)是件辛苦事兒咱枉,所以自動求導(dǎo)基本上是各種深度學(xué)習(xí)框架的基本功能和最重要的功能之一,PyTorch也不例外徒恋。

一蚕断、pytorch自動求導(dǎo)初步認(rèn)識

比如有一個函數(shù),y=x的平方(y=x2),在x=3的時(shí)候它的導(dǎo)數(shù)為6入挣,我們通過代碼來演示這樣一個過程亿乳。

x=torch.tensor(3.0,requires_grad=True)
y=torch.pow(x,2)

#判斷x,y是否是可以求導(dǎo)的
print(x.requires_grad)
print(y.requires_grad)

#求導(dǎo),通過backward函數(shù)來實(shí)現(xiàn)
y.backward()

#查看導(dǎo)數(shù)径筏,也即所謂的梯度
print(x.grad)

最終的運(yùn)行結(jié)果為:

True
True
tensor(6.) #這和我們自己算的是一模一樣的葛假。

這里有一些關(guān)鍵點(diǎn)

1.1 tensor的創(chuàng)建與屬性設(shè)置

先來看一下tensor的定義:

tensor(data, dtype=None, device=None, requires_grad=False) -> Tensor

參數(shù):
data: (array_like): tensor的初始值. 可以是列表,元組滋恬,numpy數(shù)組聊训,標(biāo)量等;
dtype: tensor元素的數(shù)據(jù)類型
device: 指定CPU或者是GPU設(shè)備,默認(rèn)是None
requires_grad:是否可以求導(dǎo)恢氯,即求梯度魔眨,默認(rèn)是False媳维,即不可導(dǎo)的

(1)tensor對象的requires_grad屬性

每一個tensor都有一個requires_grad屬性,表示這個tensor是否是可求導(dǎo)的遏暴,如果是true則可以求導(dǎo)侄刽,否則不能求導(dǎo),語法格式為:

x.requires_grad 判斷一個tensor是否可以求導(dǎo)朋凉,返回布爾值

需要注意的是州丹,只有當(dāng)所有的“葉子變量”,即所謂的leaf variable都是不可求導(dǎo)的杂彭,那函數(shù)y才是不能求導(dǎo)的墓毒,什么是leaf variable呢?這其實(shí)涉及到“計(jì)算圖”相關(guān)的知識亲怠,但是我們通過下面的例子一下就能明白了所计,如下:

#創(chuàng)建一個二元函數(shù),即z=f(x,y)=x2+y2团秽,x可求導(dǎo)主胧,y設(shè)置不可求導(dǎo)
x=torch.tensor(3.0,requires_grad=True)
y=torch.tensor(4.0,requires_grad=False)
z=torch.pow(x,2)+torch.pow(y,2)

#判斷x,y是否是可以求導(dǎo)的
print(x.requires_grad)
print(y.requires_grad)
print(z.requires_grad)

#求導(dǎo),通過backward函數(shù)來實(shí)現(xiàn)
z.backward()

#查看導(dǎo)數(shù)习勤,也即所謂的梯度
print(x.grad)
print(y.grad)

運(yùn)行結(jié)果為:

True # x是可導(dǎo)的
False # y是不可導(dǎo)的
True # z是可導(dǎo)的踪栋,因?yàn)樗幸粋€ leaf variable 是可導(dǎo)的,即x可導(dǎo)
tensor(6.) # x的導(dǎo)數(shù)
None # 因?yàn)閥不可導(dǎo)图毕,所以是none

如果是上面的 leaf variable變量x也設(shè)置為不可導(dǎo)的夷都,那么z也不可導(dǎo),因?yàn)閤予颤、y均不可導(dǎo)囤官,那么z自然不可導(dǎo)了。

(2)leaf variable(也是tensor)的requires_grad_()方法

如果某一個葉子變量蛤虐,開始時(shí)不可導(dǎo)的治拿,后面想設(shè)置它可導(dǎo),或者反過來笆焰,該怎么辦呢劫谅?tensor提供了一個方法,即

x.requires_grad_(True/False) 設(shè)置tensor的可導(dǎo)與不可導(dǎo)嚷掠,注意后面有一個下劃線哦捏检!

但是需要注意的是,我只能夠設(shè)置葉子變量不皆,即leaf variable的這個方法贯城,否則會出現(xiàn)以下錯誤:

RuntimeError: you can only change requires_grad flags of leaf variables.

1.2 函數(shù)的求導(dǎo)方法——y.backward()方法

上面只演示了簡單函數(shù)的求導(dǎo)法則,

需要注意的是:如果出現(xiàn)了復(fù)合函數(shù)霹娄,比如 y是x的函數(shù)能犯,z是y的函數(shù)鲫骗,f是z的函數(shù),那么在求導(dǎo)的時(shí)候踩晶,會使用 f.backwrad()只會默認(rèn)求f對于葉子變量leaf variable的導(dǎo)數(shù)值执泰,而對于中間變量y、z的導(dǎo)數(shù)值是不知道的渡蜻,直接通過x.grad是知道的术吝、y.grad、z.grad的值為none茸苇。

下面來看一下這個函數(shù)backward的定義:

backward(gradient=None, retain_graph=None, create_graph=False)

它的三個參數(shù)都是可選的排苍,上面的示例中還沒有用到任何一個參數(shù),關(guān)于這三個參數(shù)学密,我后面會詳細(xì)說到淘衙,這里先跳過。

1.3 查看求得的導(dǎo)數(shù)的值——x.grad屬性

通過tensor的grad屬性查看所求得的梯度值腻暮。

總結(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ǎo)方法 y.backward() 西壮,直接調(diào)用backward()方法遗增,只會計(jì)算對計(jì)算圖葉節(jié)點(diǎn)的導(dǎo)數(shù)叫惊。

(5)查看求得的到數(shù)值款青, x.grad 屬性

易錯點(diǎn):

為什么上面的標(biāo)量x的值是3.0和4.0,而不是整數(shù)呢霍狰?這是因?yàn)槁詹荩胧箈支持求導(dǎo),必須讓x為浮點(diǎn)類型蔗坯,也就是我們給初始值的時(shí)候要加個點(diǎn):“.”康震。不然的話,就會報(bào)錯宾濒。 即腿短,不能定義[1,2,3],而應(yīng)該定義成[1.,2.,3.]绘梦,前者是整數(shù)橘忱,后者才是浮點(diǎn)數(shù),浮點(diǎn)數(shù)才能求導(dǎo)卸奉。

二钝诚、求導(dǎo)的核心函數(shù)——backwrad函數(shù)詳解

2.1 默認(rèn)的求導(dǎo)規(guī)則

在pytorch里面,默認(rèn):只能是【標(biāo)量】對【標(biāo)量】榄棵,或者【標(biāo)量】對向【量/矩陣】求導(dǎo)凝颇!這個很關(guān)鍵潘拱,很重要!

(1)標(biāo)量對標(biāo)量求導(dǎo)

參見上面的例子拧略,x,y,z都是標(biāo)量芦岂,所以求導(dǎo)過程也很簡單,不再贅述辑鲤。

(2)標(biāo)量對向量/矩陣求導(dǎo)

為什么標(biāo)量對于向量/矩陣是默認(rèn)的呢盔腔?因?yàn)樵谏疃葘W(xué)習(xí)中,我們一般在求導(dǎo)的時(shí)候是對損失函數(shù)求導(dǎo)月褥,損失函數(shù)一般都是一個標(biāo)量弛随,即將所有項(xiàng)的損失加起來,但是參數(shù)又往往是向量或者是矩陣宁赤,所以這就是默認(rèn)的了舀透。看下面的例子决左。

比如有一個輸入層為3節(jié)點(diǎn)的輸入層愕够,輸出層為一個節(jié)點(diǎn)的輸出層,這樣一個簡單的神經(jīng)網(wǎng)絡(luò)佛猛,針對以組樣本而言惑芭,有

X=(x1,x2,x3)=(1.5,2.5,3.5),X是(1,3)維的继找,輸出層的權(quán)值矩陣為W=(w1,w2,w3)T=(0.2,0.4,0.6)T遂跟,這里表示初始化的權(quán)值矩陣,T表示轉(zhuǎn)置婴渡,則W表示的是(3,1)維度幻锁,偏置項(xiàng)為b=0.1,是一個標(biāo)量,則可以構(gòu)建一個模型如下:

Y=XW+b边臼,其中W,b就是要求倒數(shù)的變量哄尔,這里Y是一個標(biāo)量,W是向量柠并,b是標(biāo)量岭接,W,b是葉節(jié)點(diǎn),leaf variable臼予,

將上面展開得到:

Y=x1w1+x2w2x3w3+b (這里的1,2,3是下標(biāo)鸣戴,不是次方哦!難得用公式截圖)

自己手動計(jì)算得到瘟栖,

Y對w1的導(dǎo)數(shù)為1.5

Y對w2的導(dǎo)數(shù)為2.5

Y對w3的導(dǎo)數(shù)為3.5

Y對b的導(dǎo)數(shù)為1

下面我們來驗(yàn)證一下:

#創(chuàng)建一個多元函數(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)


#判斷每個tensor是否是可以求導(dǎo)的
print(X.requires_grad)
print(W.requires_grad)
print(b.requires_grad)
print(Y.requires_grad)


#求導(dǎo)酬滤,通過backward函數(shù)來實(shí)現(xiàn)
Y.backward()

#查看導(dǎo)數(shù)签餐,也即所謂的梯度
print(W.grad)
print(b.grad)

運(yùn)行結(jié)果為:

False
True
True
True
tensor([1.5000, 2.5000, 3.5000])
tensor(1.)

我們發(fā)現(xiàn)這和我們自己算的結(jié)果是一樣的。

(3)標(biāo)量對向量/矩陣求導(dǎo)的進(jìn)一步理解

比如有下面的一個復(fù)合函數(shù)盯串,而且是矩陣氯檐,定義如下:

x 是一個(2,3)的矩陣,設(shè)置為可導(dǎo)体捏,是葉節(jié)點(diǎn)冠摄,即leaf variable
y 是中間變量,由于x可導(dǎo),所以y可導(dǎo)
z 是中間變量,由于x几缭,y可導(dǎo)河泳,所以z可導(dǎo)
f 是一個求和函數(shù),最終得到的是一個標(biāo)量scaler

x = torch.tensor([[1.,2.,3.],[4.,5.,6.]],requires_grad=True)
y = torch.add(x,1)
z = 2*torch.pow(y,2)
f = torch.mean(z)

則x,y,z,f實(shí)際上的函數(shù)關(guān)系如下:

X=\left[\begin{array}{ccc} X_{11} & X_{12} & X_{13} \\ X_{21} & X_{22} & X_{23} \end{array}\right]

\mathrm{y}=\left[\begin{array}{lll} y_{11} & y_{12} & y_{13} \\ y_{21} & y_{22} & y_{23} \end{array}\right]

\mathrm{Z}=\left[\begin{array}{lll} Z_{11} & Z_{12} & Z_{13} \\ Z_{21} & Z_{22} & Z_{23} \end{array}\right]

f為:

\begin{aligned} & f=\frac{\sum_{i=1}^{6} z_{i}}{6}=\frac{z_{11}+z_{12}+z_{13}+z_{21}+z_{22}+z_{23}}{6} \\ =& \frac{2\left(\mathrm{y}_{11}^{2}+\mathrm{y}_{12}^{2}+\mathrm{y}_{13}^{2}+\mathrm{y}_{21}^{2}+\mathrm{y}_{22}^{2}+\mathrm{y}_{23}^{2}\right)}{6} \\ =& \frac{2\left[\left(x_{11}+1\right)^{2}+\left(x_{12}+1\right)^{2}+\left(x_{13}+1\right)^{2}+\left(x_{21}+1\right)^{2}+\left(x_{22}+1\right)^{2}+\left(x_{23}+1\right)^{2}\right]}{6} \end{aligned}

可見現(xiàn)在我么自己都可以手動求出函數(shù)f對于x11,x12,x13,x21,x22,x23的導(dǎo)數(shù)了年栓,那我們通過torch來試一試拆挥。

print(x.requires_grad)
print(y.requires_grad)
print(z.requires_grad)
print(f.requires_grad)
print('===================================')
f.backward()
print(x.grad)

運(yùn)行結(jié)果為:

True
True
True
True
===================================
tensor([[1.3333, 2.0000, 2.6667],
[3.3333, 4.0000, 4.6667]])

現(xiàn)在我們是不是更加了解自動求導(dǎo)的規(guī)則了呢?

標(biāo)量如何對標(biāo)量某抓、向量纸兔、矩陣求導(dǎo)數(shù)!7窀薄汉矿!

2.2 向量/矩陣 對 向量/矩陣求導(dǎo)——通過backward的第一個參數(shù)gradient來實(shí)現(xiàn)

(1)求導(dǎo)的一個規(guī)則

比如有下面的例子:

x 是一個(2,3)的矩陣,設(shè)置為可導(dǎo)备禀,是葉節(jié)點(diǎn)洲拇,即leaf variable
y 也是一個(2,3)的矩陣,即
y=x2+x (x的平方加x)
實(shí)際上痹届,就是要y的各個元素對相對應(yīng)的x求導(dǎo)

x = torch.tensor([[1.,2.,3.],[4.,5.,6.]],requires_grad=True)
y = torch.add(torch.pow(x,2),x)

gradient=torch.tensor([[1.0,1.0,1.0],[1.0,1.0,1.0]])

y.backward(gradient)

print(x.grad)

運(yùn)行結(jié)果為:

tensor([[ 3., 5., 7.],
[ 9., 11., 13.]])

這其實(shí)跟我們自己算的是一樣的呻待,

相較于上面的標(biāo)量對于向量或者是矩陣求導(dǎo)打月,關(guān)鍵是backward()函數(shù)的第一個參數(shù)gradient队腐,那么這個參數(shù)是什么意思呢?

為了搞清楚傳入的這個gradient參數(shù)到底做了什么工作奏篙,我們進(jìn)一步做一個實(shí)驗(yàn)柴淘,有下面的一個向量對向量的求導(dǎo),即

x = torch.tensor([1.,2.,3.],requires_grad=True)
y = torch.pow(x,2)

gradient=torch.tensor([1.0,1.0,1.0])
y.backward(gradient)
print(x.grad)

得到的結(jié)果:

tensor([2., 4., 6.]) 這和我們期望的是一樣的

因?yàn)檫@里的gradient參數(shù)全部是1秘通,所以看不出差別为严,現(xiàn)在更改一下gradient的值,如下:

gradient=torch.tensor([1.0,0.1,0.01])

輸出為:

tensor([2.0000, 0.4000, 0.0600])

從結(jié)果上來看肺稀,就是第二個導(dǎo)數(shù)縮小了十倍第股,第三個導(dǎo)數(shù)縮小了100倍,這個倍數(shù)和gradient里面的數(shù)字是息息相關(guān)的话原。

如果你想讓不同的分量有不同的權(quán)重夕吻,從效果上來理解確實(shí)是這樣子的诲锹,比如我是三個loss,loss1涉馅,loss2归园,loss3,它們的權(quán)重可能是不一樣的稚矿,我們就可以通過它來設(shè)置庸诱,即

dy/dx=0.1*dy1/dx+1.0*dy2/dx+0.0001*dy3/dx。

需要注意的是晤揣,gradient的維度是和最終的需要求導(dǎo)的那個y的維度是一樣的桥爽,從上面的兩個例子也可以看出來。

總結(jié):gradient參數(shù)的維度與最終的函數(shù)y保持一樣的形狀昧识,每一個元素表示當(dāng)前這個元素所對應(yīng)的權(quán)重

2.3 自動求導(dǎo)函數(shù)backward的第二聚谁、第三個參數(shù)

(1)保留運(yùn)算圖——retain_graph

在構(gòu)建函數(shù)關(guān)系的時(shí)候,特別是多個復(fù)合函數(shù)的時(shí)候滞诺,會有一個運(yùn)算圖形导,比如下面:


在這里插入圖片描述

則有如下一些函數(shù)關(guān)系:

p=f(y)——>y=f(x)

q=f(z)——>z=f(x)

一個計(jì)算圖在進(jìn)行反向求導(dǎo)之后,為了節(jié)省內(nèi)存习霹,這個計(jì)算圖就銷毀了朵耕。 如果你想再次求導(dǎo),就會報(bào)錯淋叶。

就比如這里的例子而言阎曹,

你先求p求導(dǎo),那么這個過程就是反向的p對y求導(dǎo)煞檩,y對x求導(dǎo)处嫌。 求導(dǎo)完畢之后,這三個節(jié)點(diǎn)構(gòu)成的計(jì)算子圖就會被釋放:


在這里插入圖片描述

那么計(jì)算圖就只剩下z斟湃、q了熏迹,已經(jīng)不完整,無法求導(dǎo)了凝赛。 所以這個時(shí)候注暗,無論你是想再次運(yùn)行p.backward()還是q.backward(),都無法進(jìn)行墓猎,因?yàn)閤已經(jīng)被銷毀了捆昏,報(bào)錯如下:

RuntimeError: Trying to backward through the graph a second time, but the buffers have already been freed. Specify retain_graph=True when calling backward the first time.

那怎么辦呢?遇到這種問題毙沾,我們可以通過設(shè)置 retain_graph=True 來保留計(jì)算圖骗卜,

即更改你的backward函數(shù),添加參數(shù)retain_graph=True,重新進(jìn)行backward寇仓,這個時(shí)候你的計(jì)算圖就被保留了勇皇,不會報(bào)錯。 但是這樣會吃內(nèi)存焚刺!敛摘,尤其是,你在大量迭代進(jìn)行參數(shù)更新的時(shí)候乳愉,很快就會內(nèi)存不足兄淫,所以這個參數(shù)在絕大部分情況下是不要去使用的。

(2)高階導(dǎo)數(shù)——create_graph

create_graph參數(shù)的資料現(xiàn)在很少蔓姚,我也還沒有搜尋到一些更詳細(xì)的用法捕虽,它的官方描述是這樣的:

更高層次的計(jì)算圖會創(chuàng)建出來,允許計(jì)算高階導(dǎo)數(shù)坡脐,如二階導(dǎo)數(shù)泄私、三階導(dǎo)數(shù)等等,下面有一個簡單的小例子:

x = torch.tensor(5.0,requires_grad=True)
y = torch.pow(x,3)

grad_x = torch.autograd.grad(y, x, create_graph=True)
print(grad_x) # dy/dx = 3 * x^2备闲,即75

grad_grad_x = torch.autograd.grad(grad_x[0],x)
print(grad_grad_x) # 二階導(dǎo)數(shù) d(2x)/dx = 30

運(yùn)行結(jié)果為:

(tensor(75., grad_fn=<MulBackward0>),)
(tensor(30.),)

三晌端、關(guān)于向量對向量求導(dǎo)的解釋

補(bǔ)充說明:關(guān)于向量對向量求梯度的進(jìn)一步繞論:

比如說下面一個三維向量求梯度:

然后,要計(jì)算z關(guān)于x或者y的梯度恬砂,需要將一個外部梯度傳遞給z.backward()函數(shù)咧纠,如下所示:

z.backward(torch.FloatTensor([1.0, 1.0, 1.0])

反向函數(shù)傳遞的張量就像梯度加權(quán)輸出的權(quán)值。從數(shù)學(xué)上講泻骤,這是一個向量乘以非標(biāo)量張量的雅可比矩陣(本文將進(jìn)一步討論)漆羔,因此它幾乎總是一個維度的單位張量,與 backward張量相同狱掂,除非需要計(jì)算加權(quán)輸出演痒。

注意 :向后圖是由autograd類在向前傳遞過程中自動動態(tài)創(chuàng)建的。Backward()只是通過將其參數(shù)傳遞給已經(jīng)生成的反向圖來計(jì)算梯度趋惨。

數(shù)學(xué)—雅克比矩陣和向量

從數(shù)學(xué)上講鸟顺,autograd類只是一個雅可比向量積計(jì)算引擎。雅可比矩陣是一個非常簡單的單詞希柿,它表示兩個向量所有可能的偏導(dǎo)數(shù)诊沪。它是一個向量相對于另一個向量的梯度养筒。

注意:在這個過程中曾撤,PyTorch從不顯式地構(gòu)造整個雅可比矩陣。直接計(jì)算JVP (Jacobian vector product)通常更簡單晕粪、更有效挤悉。

如果一個向量X = [x1, x2,…xn]通過f(X) = [f1, f2,…fn]來計(jì)算其他向量装悲,則雅可比矩陣(J)包含以下所有偏導(dǎo)組合:
\mathbf{J}=\left[\begin{array}{ccc} \frac{\partial \mathbf{f}}{\partial x_{1}} & \cdots & \frac{\partial \mathbf{f}}{\partial x_{n}} \end{array}\right]=\left[\begin{array}{ccc} \frac{\partial f_{1}}{\partial x_{1}} & \cdots & \frac{\partial f_{1}}{\partial x_{n}} \\ \vdots & \ddots & \vdots \\ \frac{\partial f_{m}}{\partial x_{1}} & & \frac{\partial f_{m}}{\partial x_{n}} \end{array}\right]

注意:雅可比矩陣實(shí)現(xiàn)的是 n維向量 到 m 維向量的映射昏鹃。

雅克比矩陣

上面的矩陣表示f(X)相對于X的梯度。

假設(shè)一個啟用PyTorch梯度的張量X:

X = x1,x2,…,xn

X經(jīng)過一些運(yùn)算形成一個向量Y

Y = f(X) = [y1, y2诀诊,…,ym]

然后使用Y計(jì)算標(biāo)量損失l洞渤。假設(shè)向量v恰好是標(biāo)量損失l關(guān)于向量Y的梯度,如下:(注意體會這句話属瓣,這個很重要T仄)
v=\left(\frac{\partial l}{\partial y_{1}} \quad \cdots \quad \frac{\partial l}{\partial_{y_{i}}}\right)^{T}

向量v稱為grad_tensor(梯度張量),并作為參數(shù)傳遞給backward() 函數(shù)抡蛙。

為了得到損失的梯度l關(guān)于權(quán)重X的梯度护昧,雅可比矩陣J是向量乘以向量v

J \cdot v=\left(\begin{array}{ccc} \frac{\partial y_{1}}{\partial x_{1}} & \cdots & \frac{\partial y_{m}}{\partial x_{1}} \\ \vdots & \ddots & \vdots \\ \frac{\partial y_{1}}{\partial x_{n}} & \cdots & \frac{\partial y_{m}}{\partial x_{n}} \end{array}\right)\left(\begin{array}{c} \frac{\partial l}{\partial y_{1}} \\ \vdots \\ \frac{\partial l}{\partial y_{m}} \end{array}\right)=\left(\begin{array}{c} \frac{\partial l}{\partial x_{1}} \\ \vdots \\ \frac{\partial l}{\partial e_{j}} \end{array}\right)
這種計(jì)算雅可比矩陣并將其與向量v相乘的方法使PyTorch能夠輕松地為非標(biāo)量輸出提供外部梯度。

四粗截、求導(dǎo)的另外兩種方法

方法一:通過 torch.autograd.backward()求導(dǎo)

前面介紹的求導(dǎo)的基本公式為:

y.backward(grad_tensors=None, retain_graph=None, create_graph=False),這三個參數(shù)我在前面已經(jīng)說了惋耙,

反向求導(dǎo)它等價(jià)于:

torch.autograd.backward(tensors,grad_tensors=None, retain_graph=None, create_graph=False), 這里的tensors參數(shù)就相當(dāng)于是y,

所以:

y.backward() #標(biāo)量y 等價(jià)于

torch.autograd.backward(y)。

需要注意的是熊昌,這個函數(shù)只是提供求導(dǎo)功能绽榛,并不返回值,返回的總是None婿屹,如下例子:

import torch

x=torch.tensor([1.0,2.0,3.0],requires_grad=True)
y=torch.tensor([4.0,5.0,6.0],requires_grad=True)

z=torch.sum(torch.pow(x,2)+torch.pow(y,3)) # z=x2+y3

torch.autograd.backward([z]) # 求導(dǎo)蒜田,等價(jià)于z.backward()

print(x.grad) # 獲取求導(dǎo)的結(jié)果
print(y.grad)

輸出

tensor([2., 4., 6.])
tensor([ 48., 75., 108.])

注意事項(xiàng):

(1)該方法只負(fù)責(zé)求導(dǎo),返回的總是None选泻,

(2)當(dāng)向量對向量求導(dǎo)的時(shí)候冲粤,需要傳遞參數(shù)grad_tensor,這個參數(shù)的含義其實(shí)和前一篇文章的y.backward()里面的那個是一個含義页眯;

(3)retain_graph=None, create_graph=False 也和前面的含義是一樣的

方法二:通過torch.autograd.grad()來求導(dǎo)

除了前面的兩種方法來求導(dǎo)以外梯捕,即

y.backward()

torch.autograd.backward(y) 這兩種方法

還有一種方法,即通過torch.autograd.grad()來求導(dǎo)窝撵,先來看一下這個函數(shù)的定義傀顾。

def grad(outputs, inputs, grad_outputs=None, retain_graph=None, create_graph=False,only_inputs=True, allow_unused=False):

outputs : 函數(shù)的因變量,即需要求導(dǎo)的那個函數(shù)碌奉,在本例子中短曾,為z,當(dāng)然赐劣,他可以是一個tensor嫉拐,也可以是幾個tensor,如[tensor1,tensor2,tensor3...]
inputs : 函數(shù)的自變量魁兼,在本例中婉徘,即對應(yīng)的是[x,y],他可以是一個tensor,也可以是幾個tensor盖呼,如[tensor1,tensor2,tensor3...]
grad_output : 這個參數(shù)和前面兩種方法中的grad_tensors是同樣的含義儒鹿,當(dāng)出現(xiàn)向量對向量求導(dǎo)的時(shí)候需要指定該參數(shù)

依然以這個例子而言,來看一下怎么做:

import torch

x=torch.tensor([1.0,2.0,3.0],requires_grad=True)
y=torch.tensor([4.0,5.0,6.0],requires_grad=True)

z=torch.sum(torch.pow(x,2)+torch.pow(y,3)) # z=x2+y3

print(torch.autograd.grad(z,[x,y])) # 求導(dǎo)几晤,并且返回值

輸出

(tensor([2., 4., 6.]), tensor([ 48., 75., 108.]))

注意事項(xiàng):

該函數(shù)會自動完成求導(dǎo)過程约炎,而且會自動返回對于每一個自變量求導(dǎo)的結(jié)果。這是和前面不一樣的地方蟹瘾。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末章钾,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子热芹,更是在濱河造成了極大的恐慌贱傀,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件伊脓,死亡現(xiàn)場離奇詭異府寒,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)报腔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進(jìn)店門株搔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人纯蛾,你說我怎么就攤上這事纤房。” “怎么了翻诉?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵炮姨,是天一觀的道長。 經(jīng)常有香客問我碰煌,道長舒岸,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任芦圾,我火速辦了婚禮蛾派,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘个少。我一直安慰自己洪乍,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布夜焦。 她就那樣靜靜地躺著壳澳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪糊探。 梳的紋絲不亂的頭發(fā)上钾埂,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天河闰,我揣著相機(jī)與錄音科平,去河邊找鬼褥紫。 笑死,一個胖子當(dāng)著我的面吹牛瞪慧,可吹牛的內(nèi)容都是我干的髓考。 我是一名探鬼主播,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼弃酌,長吁一口氣:“原來是場噩夢啊……” “哼氨菇!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起妓湘,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤查蓉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后榜贴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體豌研,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年唬党,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了鹃共。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡驶拱,死狀恐怖霜浴,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蓝纲,我是刑警寧澤阴孟,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站税迷,受9級特大地震影響温眉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜翁狐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一类溢、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧露懒,春花似錦闯冷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至坎弯,卻和暖如春纺涤,著一層夾襖步出監(jiān)牢的瞬間译暂,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工撩炊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留外永,地道東北人。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓拧咳,卻偏偏與公主長得像伯顶,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子骆膝,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評論 2 354