PyTorch基礎系列(三)——深入理解autograd:Variable屬性方法【最新已經和tensor合併為一類】
torch.autograd.backward(variables, grad_variables, retain_variables=False)
當前Variable對leaf variable求偏導。
計算圖可以通過鏈式法則求導。如果Variable是 非標量(non-scalar)的,且requires_grad=True。那麼此函式需要指定gradient,它的形狀應該和Variable的長度匹配,裡面儲存了Variable的梯度。
此函式累積leaf variable的梯度。你可能需要在呼叫此函式之前將Variable的梯度置零。
引數說明:
-
variables (variable 列表) – 被求微分的葉子節點,即
ys
-
grad_variables (
Tensor
列表) – 對應variable
的梯度。僅當variable
不是標量且需要求梯度的時候使用。見下例中的c.backward(torch.ones(a.size()))
-
retain_variables (bool) –
True
,計算梯度時所需要的buffer
在計算完梯度後不會被釋放。如果想對一個子圖多次求微分的話,需要設定為True
。
#
retain_variables用法
x
=
V(t.ones(
3
))
w
=
V(t.rand(
3
),requires_grad
=
True
)
y
=
w.mul(x)
z
=
y.
sum
()
z.backward(retain_graph
=
True
)
print
(w.grad)
z.backward()#保留了上一次的結果,才能再一次backward()否則圖也解散第二次backward()會報錯
: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 當然你也可以選擇再構造一次圖 y
=
w.mul(x)
z
=
y.
sum()然後再
backward()也可以
print
(w.grad)
Variable containing: 1 1 1 Variable containing:【第二次結果是進行了累加第一次】 2 2 2
在PyTorch中計算圖的特點可總結如下:
葉子節點物件【使用者自己創造的物件】是一個 AccumulateGrad Object 表示梯度累加物件。通過grad_fn.next_functions可得。
非葉子節點的梯度計算完之後即被清空,grad為None
用 retain_grad可保留中間梯度
a
=
V(t.ones(
3
,
4
),requires_grad
=
True)
葉子節點 grad_fn
為None backward後grad有
b
=
V(t.zeros(
3
,4))requires_grad
=
False
葉子節點 grad_fn
為None backward後grad無
c
=
a.add(b)
所有依賴a
的節點requires_grad=True grad_fn
為AddBackward1 backward後grad無
d
=
c.sum()
所有依賴a
的節點 requires_grad=True grad_fn
為sum
Backward1
backward後grad無
d.backward() 這時候d是標量12,所以可以省略backward的
grad_variable引數,預設(torch.FloatTensor([1]))
c.backward(torch.ones(a.size())) c 是向量,需定義backward的
grad_variable引數,表示每一個都是1倍梯度。
- autograd根據使用者對variable的操作
Function
構建其計算圖。對變數的操作抽象為Function
。 - 對於那些不是任何函式(Function)的輸出,由使用者建立的節點稱為葉子節點,葉子節點的
grad_fn
為None。葉子節點中需要求導的variable,具有AccumulateGrad
標識,因其梯度是累加的。 - variable預設是不需要求導的,即
requires_grad
屬性預設為False,如果某一個節點requires_grad被設定為True,那麼所有依賴它的節點requires_grad
都為True。 - variable的
volatile
屬性預設為False,如果某一個variable的volatile
屬性被設為True,那麼所有依賴它的節點volatile
屬性都為True。volatile屬性為True的節點不會求導,volatile的優先順序比requires_grad
高。已經被torch.no_grad()替代 - 多次反向傳播時,梯度是累加的。反向傳播的中間快取會被清空,為進行多次反向傳播需指定
retain_graph
=True來儲存這些快取。 - 非葉子節點的梯度計算完之後即被清空,可以使用
autograd.grad
或hook
技術獲取非葉子節點的值。 - variable的grad與data形狀一致,應避免直接修改variable.data,因為對data的直接操作無法利用autograd進行反向傳播
- 反向傳播函式
backward
的引數grad_variables
可以看成鏈式求導的中間結果,如果是標量,可以省略,預設為1 - PyTorch採用動態圖設計,可以很方便地檢視中間層的輸出,動態的設計計算圖結構。
Variable類和計算圖
簡單的建立一個計算圖,便於理解幾個相關知識點:
-
requires_grad 是否要求導數,預設False,葉節點指定True後,依賴節點都被置為True
-
.backward() 根Variable的方法會反向求解葉Variable的梯度
-
.backward()方法grad_variable引數 形狀與根Variable一致,非標量Variable反向傳播方向指定
-
葉節點 由使用者建立的計算圖Variable物件,反向傳播後會保留梯度grad數值,非葉子節點Variable會清空為None
-
grad_fn 指向建立Tensor的Function,如果某一個物件由使用者建立葉子節點,則指向None
-
.is_leaf 是否是葉節點
-
.grad_fn.next_functions 本節點接收的上級節點的grad_fn,
# grad_fn.next_functions代表了本節點的輸入節點資訊,grad_fn表示了本節點的輸出資訊
-
.volatile 是否處於推理模式
作用於依賴路徑全部的Variable。已經被torch.no_grad()
,torch.set_grad_enabled(grad_mode)
替代,在0.4版本中。【具體案例見下面volatile部分】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
True False True True True True False False Variable containing: 1 1 1 1 1 1 1 1 1 1 1 1 [torch.FloatTensor of size 3x4] None None None
1 |
|
None None <AddBackward1 object at 0x000002A2F3D2EBA8> <SumBackward0 object at 0x000002A2F3D2ECC0>
.grad_fn.next_functions
# grad_fn.next_functions代表了本節點的輸入節點資訊,grad_fn表示了本節點的輸出資訊
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
.is_leaf True True True False False .requires_grad False True True True True .grad_fn None None None <MulBackward1 object at 0x000002A2F57F5710> <AddBackward1 object at 0x000002A2F57F5630> .grad_fn.next_functions ((<AccumulateGrad object at 0x000002A2F57F5630>, 0), (None, 0))第一個引數是w,使用者自己創造的葉子節點,梯度累加行AccumulateGrad,第二是x ((<MulBackward1 object at 0x000002A2F57F57B8>, 0), (<AccumulateGrad object at 0x000002A2F57F57F0>, 0))
z.grad_fn.next_functions[0][0]==y.grad_fn True
z.grad_fn.next_functions[0][0],y.grad_fn <MulBackward1 object at 0x000002A2F57F57F0> <MulBackward1 object at 0x000002A2F57F57F0>
.volatile
volatile was removed and now has no effect. Use `with torch.no_grad():` instead
1 2 3 4 5 6 7 8 9 |
|
False True False True False True
.volatile已經被orch.no_grad()
, torch.set_grad_enabled(grad_mode)
替代,在0.4版本中。
>>> x = torch.zeros(1, requires_grad=True)
>>> with torch.no_grad():
... y = x * 2
>>> y.requires_grad
False
>>>
>>> is_train = False
>>> with torch.set_grad_enabled(is_train):
... y = x * 2#這樣形成的y不求導
>>> y.requires_grad
False
>>> torch.set_grad_enabled(True) # this can also be used as a function
>>> y = x * 2
>>> y.requires_grad
True
>>> torch.set_grad_enabled(False)
>>> y = x * 2
>>> y.requires_grad
False
附錄、Variable類原始碼簡介
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
|