轉自:https://sherlockliao.github.io/2017/07/10/backward/
backward只能被應用在一個標量上,也就是一個一維tensor,或者傳入跟變量相關的梯度。
特別注意Variable
里面默認的參數requires_grad=False
,所以這里我們要重新傳入requires_grad=True
讓它成為一個葉子節點。
對其求偏導:
1 import torch as t 2 from torch.autograd import Variable as v 3 4 # simple gradient 5 a = v(t.FloatTensor([2, 3]), requires_grad=True) 6 b = a + 3 7 c = b * b * 3 8 out = c.mean() 9 out.backward() 10 print('*'*10) 11 print('=====simple gradient======') 12 print('input') 13 print(a.data) 14 print('compute result is') 15 print(out.data[0]) 16 print('input gradients are') 17 print(a.grad.data)
下面研究一下如何能夠對非標量的情況下使用backward。backward里傳入的參數是每次求導的一個系數。
首先定義好輸入m=(x1,x2)=(2,3),然后我們做的操作就是n=,這樣我們就定義好了一個向量輸出,結果第一項只和x1有關,結果第二項只和x2有關,那么求解這個梯度,
1 # backward on non-scalar output 2 m = v(t.FloatTensor([[2, 3]]), requires_grad=True) 3 n = v(t.zeros(1, 2)) 4 n[0, 0] = m[0, 0] ** 2 5 n[0, 1] = m[0, 1] ** 3 6 n.backward(t.FloatTensor([[1, 1]])) 7 print('*'*10) 8 print('=====non scalar output======') 9 print('input') 10 print(m.data) 11 print('input gradients are') 12 print(m.grad.data)
jacobian矩陣
對其求導:
k.backward(parameters)
接受的參數parameters
必須要和k
的大小一模一樣,然后作為k
的系數傳回去,backward里傳入的參數是每次求導的一個系數。
# jacobian j = t.zeros(2 ,2) k = v(t.zeros(1, 2)) m.grad.data.zero_() k[0, 0] = m[0, 0] ** 2 + 3 * m[0 ,1] k[0, 1] = m[0, 1] ** 2 + 2 * m[0, 0] # [1, 0] dk0/dm0, dk1/dm0 k.backward(t.FloatTensor([[1, 0]]), retain_variables=True) # 需要兩次反向求導 j[:, 0] = m.grad.data m.grad.data.zero_() # [0, 1] dk0/dm1, dk1/dm1 k.backward(t.FloatTensor([[0, 1]])) j[:, 1] = m.grad.data print('jacobian matrix is') print(j)
我們要注意backward()
里面另外的一個參數retain_variables=True
,這個參數默認是False,也就是反向傳播之后這個計算圖的內存會被釋放,這樣就沒辦法進行第二次反向傳播了,所以我們需要設置為True,因為這里我們需要進行兩次反向傳播求得jacobian矩陣。