葉子節點和tensor的requires_grad參數

無論如何定義計算過程、如何定義計算圖,要謹記我們的核心目的是爲了計算某些tensor的梯度。在pytorch的計算圖中,其實只有兩種元素:數據(tensor)和運算,運算就是加減乘除、開方、冪指對、三角函數等可求導運算,而tensor可細分爲兩類:葉子節點(leaf node)和非葉子節點。使用backward()函數反向傳播計算tensor的梯度時,並不計算所有tensor的梯度,而是隻計算滿足這幾個條件的tensor的梯度:1.類型爲葉子節點、2.requires_grad=True、3.依賴該tensor的所有tensor的requires_grad=True。首先,葉子節點可以理解成不依賴其他tensor的tensor,如下圖

                     

在pytorch中,神經網絡層中的權值w的tensor均爲葉子節點;自己定義的tensor例如a=torch.tensor([1.0])定義的節點是葉子節點;一個有趣的現象是:

import torch
a=torch.tensor([1.0])

a.is_leaf
True

b=a+1
b.is_leaf
True

可以看出b竟然也是葉節點!這件事可以這樣理解,單純從數值關係上b=a+1,b確實依賴a。但是從pytorch的看來,一切是爲了反向求導,a的requires_grad屬性爲False,其不要求獲得梯度,那麼a這個tensor在反向傳播時其實是“無意義”的,可認爲是遊離在計算圖之外的,故b仍然爲葉子節點,如下圖

           

再例如下圖的計算圖,本來是葉子節點是可以正常進行反向傳播計算梯度的:

     

但是使用detach()函數將某一個非葉子節點剝離成爲葉子節點後:

    

無論requires_grad屬性爲何值,原先的葉子節點求導通路中斷,便無法獲得梯度數值了。其次,如上所示,對於需要求導的tensor,其requires_grad屬性必須爲True,例如對於下圖中最上面的葉子節點,pytorch不會自動計算其導數。

                  

自己定義的tensor的requires_grad屬性默認爲False,神經網絡層中的權值w的tensor的requires_grad屬性默認爲True。需要說明,如果自行定義了一個tensor並將其requires_grad設置爲True,該tensor是葉子節點,且依賴該tensor的其他tensor是非葉子節點(非葉子節點不會自動求導),其requires_grad自動設置爲True,這樣便形成了一條從葉節點到loss節點的求導的“通路”。

import torch
a=torch.tensor([1.0])
a.requires_grad=True

b=a+1
b.is_leaf
False
b.requires_grad
True

而對於非葉子節點,其不僅requiresgrad屬性爲True,而且還有一個grad_fn屬性,記錄了該節點產生時使用的運算函數,加?乘方?使得反向求導時可以計算梯度。另外,如果需要使得某一個節點成爲葉子節點,只需使用detach()即可將它從創建它的計算圖中分離開來。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章