摘自:https://github.com/bat67/Deep-Learning-with-PyTorch-A-60-Minute-Blitz-cn
嚶嚶嚶求star~,最新版也會首先更新在github上
有誤的地方拜託大家指出~
Autograd:自動求導
PyTorch中,所有神經網絡的核心是autograd
包。先簡單介紹一下這個包,然後訓練我們的第一個的神經網絡。
autograd
包爲張量上的所有操作提供了自動求導機制。它是一個在運行時定義(define-by-run)的框架,這意味着反向傳播是根據代碼如何運行來決定的,並且每次迭代可以是不同的.
讓我們用一些簡單的例子來看看吧。
張量
torch.Tensor
是這個包的核心類。如果設置它的屬性 .requires_grad
爲True
,那麼它將會追蹤對於該張量的所有操作。當完成計算後可以通過調用.backward()
,來自動計算所有的梯度。這個張量的所有梯度將會自動累加到.grad
屬性.
要阻止一個張量被跟蹤歷史,可以調用.detach()
方法將其與計算曆史分離,並阻止它未來的計算記錄被跟蹤。
爲了防止跟蹤歷史記錄(和使用內存),可以將代碼塊包裝在with torch.no_grad():
中。在評估模型時特別有用,因爲模型可能具有requires_grad = True
的可訓練的參數,但是我們不需要在此過程中對他們進行梯度計算。
還有一個類對於autograd的實現非常重要:Function
。
Tensor
和Function
互相連接生成了一個非循環圖,它編碼了完整的計算曆史。每個張量都有一個.grad_fn
屬性,它引用了一個創建了這個Tensor
的Function
(除非這個張量是用戶手動創建的,即這個張量的grad_fn
是None
)。
如果需要計算導數,可以在Tensor
上調用.backward()
。如果Tensor
是一個標量(即它包含一個元素的數據),則不需要爲backward()
指定任何參數,但是如果它有更多的元素,則需要指定一個gradient
參數,它是形狀匹配的張量。
import torch
創建一個張量並設置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 0x7f1b248453c8>
對y進行更多操作
z = y * y * 3
out = z.mean()
print(z, out)
輸出:
tensor([[27., 27.],
[27., 27.]], grad_fn=<MulBackward0>) tensor(27., grad_fn=<MeanBackward0>)
.requires_grad_(...)
原地改變了現有張量的 requires_grad
標誌。如果沒有指定的話,默認輸入的這個標誌是False
。
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 0x7f1b24845f98>
梯度
因爲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.5
的矩陣。調用out
張量 。
得到
和
因此,
所以,
數學上,若有向量值函數 ,那麼 相對於 的梯度是一個雅可比矩陣:
通常來說,torch.autograd
是計算雅可比向量積的一個“引擎”。也就是說,給定任意向量 ,計算乘積 。如果 恰好是一個標量函數 的導數,即 ,那麼根據鏈式法則,雅可比向量積應該是 對 的導數:
雅可比向量積的這一特性使得將外部梯度輸入到具有非標量輸出的模型中變得非常方便。
現在我們來看一個雅可比向量積的例子:
x = torch.randn(3, requires_grad=True)
y = x * 2
while y.data.norm() < 1000:
y = y * 2
print(y)
輸出:
tensor([-278.6740, 935.4016, 439.6572], grad_fn=<MulBackward0>)
在這種情況下,y
不再是標量。torch.autograd
不能直接計算完整的雅可比矩陣,但是如果我們只想要雅可比向量積,只需將這個向量作爲參數傳給backward
:
v = torch.tensor([0.1, 1.0, 0.0001], dtype=torch.float)
y.backward(v)
print(x.grad)
輸出:
tensor([4.0960e+02, 4.0960e+03, 4.0960e-01])
爲了防止跟蹤歷史記錄(和使用內存),可以將代碼塊包裝在with torch.no_grad():
中。在評估模型時特別有用,因爲模型可能具有requires_grad = True
的可訓練的參數,但是我們不需要在此過程中對他們進行梯度計算。
也可以通過將代碼塊包裝在 with torch.no_grad():
中,來阻止autograd跟蹤設置了 .requires_grad=True
的張量的歷史記錄。
print(x.requires_grad)
print((x ** 2).requires_grad)
with torch.no_grad():
print((x ** 2).requires_grad)
輸出:
True
True
False
後續閱讀:
autograd
和Function
的文檔見:https://pytorch.org/docs/autograd