在PyTorch中,autograd是所有神經網絡的核心內容,為Tensor所有操作提供自動求導方法。
它是一個按運行方式定義的框架,這意味着backprop是由代碼的運行方式定義的。
一、Variable
autograd.Variable 是autograd中最核心的類。 它包裝了一個Tensor,並且幾乎支持所有在其上定義的操作。一旦完成了你的運算,你可以調用 .backward()來自動計算出所有的梯度。
Variable有三個屬性:data,grad以及creator。
訪問原始的tensor使用屬性.data; 關於這一Variable的梯度則集中於 .grad; .creator反映了創建者,標識了是否由用戶使用.Variable直接創建(None)。
還有一個對autograd的實現非常重要的類——Function。Variable 和Function數是相互關聯的,並建立一個非循環圖,從而編碼完整的計算過程。每個變量都有一個.grad_fn屬性引用創建變量的函數(除了用戶創建的變量,它們的grad_fn是None)。
import torch from torch.autograd import Variable
創建變量x:
x = Variable(torch.ones(2, 2), requires_grad=True) print(x)
輸出結果:
Variable containing: 1 1 1 1 [torch.FloatTensor of size 2x2]
在x基礎上進行運算:
y = x + 2
print(y)
輸出結果:
Variable containing: 3 3 3 3 [torch.FloatTensor of size 2x2]
查看x的
grad_fn:
print(x.grad_fn)
輸出結果:
None
查看y的
grad_fn:
print(y.grad_fn)
輸出結果:
<torch.autograd.function.AddConstantBackward object at 0x7f603f6ab318>
可以看到y是作為運算的結果產生的,所以y有
grad_fn,而x是直接創建的,所以x沒有grad_fn。
在y基礎上進行運算:
z = y * y * 3 out = z.mean() print(z, out)
輸出結果:
Variable containing: 27 27 27 27 [torch.FloatTensor of size 2x2] Variable containing: 27 [torch.FloatTensor of size 1]
二、Gradients
如果Variable是一個標量(例如它包含一個單元素數據),你無需對backward()指定任何參數.
out.backward()
等價於out.backward(torch.Tensor([1.0])).
out.backward() print(x.grad)
輸出結果:
Variable containing: 4.5000 4.5000 4.5000 4.5000 [torch.FloatTensor of size 2x2]
如果它有更多的元素(矢量),你需要指定一個和tensor的形狀匹配的grad_output參數(y在指定方向投影對x的導數)
x = torch.randn(3) x = Variable(x, requires_grad=True) y = x * 2 while y.data.norm() < 1000: y = y * 2 print(y)
輸出結果:
Variable containing: -1296.5227 499.0783 778.8971 [torch.FloatTensor of size 3]
不傳入參數:
y.backward() print(x.grad)
輸出結果:
RuntimeError: grad can be implicitly created only for scalar outputs None
傳入參數:
gradients = torch.FloatTensor([0.1, 1.0, 0.0001]) y.backward(gradients) print(x.grad)
輸出結果:
Variable containing: 102.4000 1024.0000 0.1024 [torch.FloatTensor of size 3]
簡單測試一下不同參數的效果:
參數1:[1,1,1]
x=torch.FloatTensor([1,2,3]) x = Variable(x, requires_grad=True) y = x * x print(y) gradients = torch.FloatTensor([1,1,1]) y.backward(gradients) print(x.grad)
輸出結果:
Variable containing: 1 4 9 [torch.FloatTensor of size 3] Variable containing: 2 4 6 [torch.FloatTensor of size 3]
參數2:[3,2,1]
x=torch.FloatTensor([1,2,3]) x = Variable(x, requires_grad=True) y = x * x print(y) gradients = torch.FloatTensor([3,2,1]) y.backward(gradients) print(x.grad)
輸出結果:
Variable containing: 1 4 9 [torch.FloatTensor of size 3] Variable containing: 6 8 6 [torch.FloatTensor of size 3]