首先聲明Pytorch的backward機制:
y.backward()
時,如果 y
是标量(scalar),則不需要為 backward()
傳入任何參數;
y.backward()
y
backward()
如果 y
是張量(tensor),需要傳入一個與 y
同形的 Tensor(張量)
y
y
Tensor(張量)
①y是scalar标量
②y是Tensor張量
①如果直接像标量那樣計算
就會報錯顯示: RuntimeError: grad can be implicitly created only for scalar outputs。
翻譯過來就是,grad隻能隐式地為标量輸出建立。
RuntimeError: grad can be implicitly created only for scalar outputs。
②y調用 backward
時需要傳入一個和 y
同形的權重向量進行權重求和得到一個标量。
backward
y
是以要謹記:在Pytorch中,調用 backward
時,一定是标量對張量求導。
backward
③續
1.為什麼不能Tensor 對 Tensor 求導
舉個例子,假設形狀為 m x n
的矩陣 X 經過運算得到了 p x q
的矩陣 Y,Y 又經過運算得到了 s x t
的矩陣 Z。那麼按照前面講的規則,dZ/dY 應該是一個 s x t x p x q
四維張量,dY/dX 是一個 p x q x m x n
的四維張量。問題來了,怎樣反向傳播?怎樣将兩個四維張量相乘???這要怎麼乘???就算能解決兩個四維張量怎麼乘的問題,四維和三維的張量又怎麼乘?導數的導數又怎麼求,這一連串的問題,感覺要瘋掉…… 為了避免這個問題,我們不允許張量對張量求導,隻允許标量對張量求導,求導結果是和自變量同形的張量。
m x n
p x q
s x t
s x t x p x q
p x q x m x n
2. y.backward(w)
前面提高的都是直接 y.backward()
,那麼如果是 y.backward(w)
呢?
y.backward()
y.backward(w)
y.backward(w) 求的就不是 y 對 x 的導數,而是 l = torch.sum(y*w) 對 x 的導數,即dl/dx = d(y*w)/dx。
舉個例子:
t.backward(z)
,即 l = torch.sum(t*z)
t.backward(z)
l = torch.sum(t*z)