一、Tensor用於自動求梯度
"tensor"這個單詞⼀般可譯作“張量”,張量可以看作是⼀個多維數組。標量可以看作是0維張量,向量可以看作1維張量,矩陣可以看作是⼆維張量。
在深度學習中,我們經常需要對函數求梯度(gradient)。PyTorch提供的autograd
包能夠根據輸⼊和前向傳播過程⾃動構建計算圖,並執⾏反向傳播。本節將介紹如何使⽤autograd包來進⾏⾃動求梯度的有關操作。
概念
Pytorch中的Tensor
是這個包的核⼼類,如果將其屬性 .requires_grad
設置為 True
,它將開始追蹤(track)在其上的所有操作(這樣就可以利⽤鏈式法則進⾏梯度傳播了)。完成計算后,可以調⽤ .backward()
來完成所有梯度計算。此 Tensor
的梯度將累積到 .grad
屬性中。
注意在
y.backward()
時,如果y
是標量,則不需要為backward()
傳⼊任何參數;否則,需要傳⼊⼀個與y
同形的Tensor
。
如果不想要被繼續追蹤,可以調⽤ .detach()
將其從追蹤記錄中分離出來,這樣就可以防⽌將來的計算被追蹤,這樣梯度就傳不過去了。此外,還可以⽤ with torch.no_grad()
將不想被追蹤的操作代碼塊包裹起來,這種⽅法在評估模型的時候很常⽤,因為在評估模型時,我們並不需要計算可訓練參數(requires_grad=True
)的梯度。
Function
是另外⼀個很重要的類。 Tensor
和 Function
互相結合就可以構建⼀個記錄有整個計算過程的有向⽆環圖(DAG)。每個 Tensor 都有⼀個 .grad_fn
屬性,該屬性即創建該 Tensor
的Function
, 就是說該 Tensor
是不是通過某些運算得到的,若是,則 grad_fn
返回⼀個與這些運算相關的對象,否則是None。
import torch
# 通過設置`requires_grad=Ytue`,使得操作通過鏈式法則進行梯度傳播
x = torch.ones(2, 2, requires_grad=True)
print(x)
print(x.grad_fn)
# +的運算操作
y = x+2
print(y)
print(y.grad_fn)
print(x.is_leaf,y.is_leaf)
# 復雜一點的運算操作
z = y*y*2
print(z)
print(z.grad_fn)
out = z.mean()
print(z, out)
輸出結果:
二、梯度
因為 out
是⼀個標量,所以調⽤ backward()
時不需要指定求導變量:
# 通過`requires_grad()`來用`in-place`的方式來改變`requieres_grad`屬性
a = torch.rand(2,2)
a = ((a*3)/(a-1))
print(a.requires_grad) #False
a.requires_grad_(True)
print(a.requires_grad) #True
b = (a*a).sum()
print(b.grad_fn)
輸出結果:
因為 out
是⼀個標量,所以調⽤ backward()
時不需要指定求導變量:
# 因為 out 是⼀個標量,所以調⽤ backward() 時不需要指定求導變量:
out.backward()
print(x.grad)
輸出結果:(教程是4.5,因為前面我的數據處理不同)
量都為向量的函數\(\vec y = f\left(\vec x \right)\) , 那么\(\vec y\) 關於\(\vec x\)的梯度就是⼀個雅可⽐矩陣(Jacobian matrix):
⽽ torch.autograd
這個包就是⽤來計算⼀些雅克⽐矩陣的乘積的。例如,如果v
是⼀個標量函數的\(l = g \left(\vec y \right)\)的梯度:
那么根據鏈式法則我們有\(l\) 關於\(\vec x\) 的雅克⽐矩陣就為:
注意:grad在反向傳播過程中是累加的(accumulated),這意味着每⼀次運⾏反向傳播,梯度都會累加之前的梯度,所以⼀般在反向傳播之前需把梯度清零。
再來反向傳播⼀次,注意grad是累加的:
out2 = x.sum()
out2.backward()
print(x.grad)
out3 = x.sum()
x.grad.data.zero_()
out3.backward()
print(x.grad)
輸出結果:
Question:為什么在 y.backward()
時,如果 y 是標量,則不需要為 backward()
傳⼊任何參數,否則,需要傳⼊⼀個與 y 同形的 Tensor
?
Ans:為了避免向量(或者更高維張量)對張量進行求導,而轉換成標量對張量進行求導(通過將所有張量的元素加權求和的方式轉化為標量。)。