Autograd: 自動求導
pyTorch里神經網絡能夠訓練就是靠autograd
包。我們來看下這個包,然后我們使用它來訓練我們的第一個神經網絡。
autograd
包提供了對張量的所有運算自動求導。它是一種在運行時才被定義的,意味着反向傳播只有再代碼運行的時候才會計算,每次循環的時候都可以不同,就是說可以有不同的計算圖。
用以下幾個例子來看autograd:
張量
torch.Tensor
是torch庫的核心類。如果你把Tensor類的 .requires_grad
設置為
True
,它就會計算其上的梯度。 當你計算完所有的值后使用 .backward()
就可以自動的計算所有的導數。 該張量的梯度會累加到 .grad
屬性。
To stop a tensor from tracking history, you can call .detach()
to detach it from the computation history, and to prevent future computation from being tracked.
To prevent tracking history (and using memory), you can also wrap the code block in with torch.no_grad():
. This can be particularly helpful when evaluating a model because the model may have trainable parameters with requires_grad=True, but for which we don’t need the gradients.
有一個對自動求導實現非常關鍵的類:Function。
Tensor
和
Function
互相連接起來,構建了一個無圈圖,對所有的歷史進行了編碼。每個張量都有一個叫 .grad_fn
的屬性,是生成該tensor的Function的
索引(而那些由我們創建的Tensor的.grad_fn是None)
如果你想計算導數,那么你就可以對一個Tensor調用它的.backward()方法。如果Tensor是一個標量(只有一個元素的數據),你不需要指明backward()的任何參數,如果它有多個元素的話,就需要指定一個gradient的參數,該參數與調用該Tensor的形狀相同。
import torch
創建一個tensor並且設置 requires_grad=True 來跟蹤計算。
x = torch.ones(2, 2, requires_grad=True) print(x)
輸出:
tensor([[1., 1.],
[1., 1.]], requires_grad=True)
給它來個運算:
y = x + 2 print(y)
輸出:
tensor([[3., 3.],
[3., 3.]], grad_fn=<AddBackward0>)
y
是有運算產生的張量,所以它有grad_fn
print(y.grad_fn)
輸出:
<AddBackward0 object at 0x7f0ea616bac8>
給 y再來一些運算:
z = y * y * 3 out = z.mean() print(z, out)
輸出:
tensor([[27., 27.],
[27., 27.]], grad_fn=<MulBackward0>) tensor(27., grad_fn=<MeanBackward1>)
.requires_grad_( ... )
改變現有張量的 requires_grad
標志。如果沒有提供.requires_grad參數的話,輸入的標志默認是False。參看例子:
#這在fine tune神經網絡時候很有用,特別是遷移的時候
a = torch.randn(2, 2) a = ((a * 3) / (a - 1)) print(a.requires_grad) a.requires_grad_(True) print(a.requires_grad) b = (a * a).sum() print(b.grad_fn)
輸出:
False
True
<SumBackward0 object at 0x7f0e86396e48>
梯度
Let’s backprop now Because out
contains a single scalar, out.backward()
is equivalent to out.backward(torch.tensor(1))
.
讓我們反向傳播,由於out是一個標量,
out.backward()
等價於 out.backward(torch.tensor(1))
.
out.backward()
輸出 d(out)/dx的梯度
print(x.grad)
輸出:
tensor([[4.5000, 4.5000],
[4.5000, 4.5000]])
可以得到一個4*4的元素是 4.5的舉證。讓我們稱為
out
張量。
至於這個函數的偏導數怎么計算,參見微積分吧!
有了autograd,我們可以做一些瘋狂的事情!
x = torch.randn(3, requires_grad=True) y = x * 2 while y.data.norm() < 1000: y = y * 2 print(y)
輸出:
tensor([-1178.9551, 1202.9015, 293.6342], grad_fn=<MulBackward0>) #每次的輸出可能不同
gradients = torch.tensor([0.1, 1.0, 0.0001], dtype=torch.float) y.backward(gradients) print(x.grad)
輸出:
tensor([ 102.4000, 1024.0000, 0.1024])
You can also stop autograd from tracking history on Tensors with .requires_grad=True
by wrapping the code block in with torch.no_grad()
:
你可以使用with torch.no_grad()停止自動的梯度計算,即使tensor的屬性.requires_grad=True
print(x.requires_grad) print((x ** 2).requires_grad) with torch.no_grad(): print((x ** 2).requires_grad)
Out:
True
True
False
更多閱讀:
autograd
和 Function
的文檔在: http://pytorch.org/docs/autograd