從零開始深度學習Pytorch筆記(8)—— 計算圖與自動求導(上)

前文傳送門:從零開始深度學習Pytorch筆記(1)——安裝Pytorch從零開始深度學習Pytorch筆記(2)——張量的創(chuàng)建(上)從零開始深度學習Pytorch筆記(3)——張量的創(chuàng)建(下)從零開始深度學習Pytorch筆記(4)——張量的拼接與切分從零開始深度學習Pytorch筆記(5)——張量的索引與變換從零開始深度學習Pytorch筆記(6)——張量的數(shù)學運算從零開始深度學習Pytorch筆記(7)—— 使用Pytorch實現(xiàn)線性回歸
在該系列的上一篇,我們介紹了使用Pytorch搭建線性回歸模型,本文教會大家使用Pytorch時涉及的兩個重要知識點——計算圖和自動求導。什么是計算圖呢?首先,在深度學習中有著圖的概念,所以有邊和節(jié)點,節(jié)點為張量,而邊為計算過程,則為計算圖,具體可以看圖:
x、y、z、m 的計算關系如圖所示,他們可構成一個計算圖。說完計算圖之后,我們來看看自動求導。
我們可以從這個計算圖中看出,如果 x 為一個張量,則根據(jù)計算關系可以推出 y 也為一個張量,z 也為一個張量,而 m 是對 z 張量中的每個元素求均值,則 z 為一個標量。
當我們使用Pytorch時,經(jīng)常會搭建各種神經(jīng)網(wǎng)絡結構模型,而在神經(jīng)網(wǎng)絡結構中的誤差反向傳播是很基礎但又很實用的內容,在誤差反傳的時候需要求導計算,我們來看看Pytorch的自動求導。首先我們定義一個張量x,并初始化賦值。注意的地方時,我們加入了requires_grad=True這個參數(shù),該參數(shù)使得x張量可以被求導操作。
import?torch
x?=?torch.ones(2,3,requires_grad=True)
print(x)
然后我們通過x生成張量y。y?=?x?+?1
print(y)
我們檢查張量y,發(fā)現(xiàn)張量y可以求導。y.requires_grad我們來完整構建一個計算圖(按照之前的計算圖)。
x?=?torch.tensor([[1.,2.,3.],[4.,5.,6.]],requires_grad=True)然后我們m進行求導。
y?=?x+1
z?=?2*y
m?=?torch.mean(z)
m.backward()然后看看m對x求導的結果,通過復合求導我們可以算出,m對x的導數(shù)為1/3的x,因為x是全1張量:
x.grad?# m對x求導結果?結果為:1/3
發(fā)現(xiàn)計算結果和代碼運行結果一致!如果我們使用中間變量z求導,如下所示。
z.backward()
結果會有異常,這是因為默認情況下,求導的操作只能是標量對標量求導,或者是標量對向量/矩陣求導!其實,也可以使用非標量(向量/矩陣)對其他張量求導,只需要研究backward的方法參數(shù)即可,但是一般的神經(jīng)網(wǎng)絡誤差反傳場景下,我們的誤差通常是個標量,所以掌握標量的求導已經(jīng)夠用啦~還有一點比較重要的是,一個計算圖默認情況下只能backward一次。
m.backward()#當我們嘗試再次使用backward
仔細看拋出的異常: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.大概意思是:你第二次再backward的時候,計算圖已經(jīng)銷毀了,如果需要多次backward,你需要在第一次backward的時候,加上retain_graph=True的參數(shù)。所以反向求導會讓計算圖銷毀,主要是為了節(jié)約內存,你想想,我們的深度學習網(wǎng)絡這么復雜,訓練時要在網(wǎng)絡中不斷正向和反向傳播,會計算n多次求導,是不是會很占用內存呢?我們嘗試重新建立計算圖!x?=?torch.tensor([[1.,2.,3.],[4.,5.,6.]],requires_grad=True)這樣在第二次backward求導就不會出問題啦~
y?=?x+1
z?=?2*y
m?=?torch.mean(z)
m.backward(retain_graph=True)
m.backward()
喜歡記得點在看哦,證明你來看過~