PyTorch Tutorials 2 AUTOGRAD: AUTOMATIC DIFFERENTIATION

%matplotlib inline

Autograd: 自動求導機制

PyTorch 中全部神經網絡的核心是 autograd 包。
咱們先簡單介紹一下這個包,而後訓練第一個簡單的神經網絡。html

autograd包爲張量上的全部操做提供了自動求導。
它是一個在運行時定義的框架,這意味着反向傳播是根據你的代碼來肯定如何運行,而且每次迭代能夠是不一樣的。python

示例網絡

張量(Tensor)

torch.Tensor是這個包的核心類。若是設置
.requires_gradTrue,那麼將會追蹤全部對於該張量的操做。
當完成計算後經過調用 .backward(),自動計算全部的梯度,
這個張量的全部梯度將會自動積累到 .grad 屬性。框架

要阻止張量跟蹤歷史記錄,能夠調用.detach()方法將其與計算曆史記錄分離,並禁止跟蹤它未來的計算記錄。ui

爲了防止跟蹤歷史記錄(和使用內存),能夠將代碼塊包裝在with torch.no_grad():中。
在評估模型時特別有用,由於模型可能具備requires_grad = True的可訓練參數,可是咱們不須要梯度計算。spa

在自動梯度計算中還有另一個重要的類Function.scala

Tensor and Function are interconnected and build up an acyclic
graph, that encodes a complete history of computation. Each tensor has
a .grad_fn attribute that references a Function that has created
the Tensor (except for Tensors created by the user - their
grad_fn is None).code

TensorFunction互相鏈接並生成一個非循環圖,它表示和存儲了完整的計算曆史。
每一個張量都有一個.grad_fn屬性,這個屬性引用了一個建立了TensorFunction(除非這個張量是用戶手動建立的,即,這個張量的
grad_fnNone)。orm

若是須要計算導數,你能夠在Tensor上調用.backward()
若是Tensor是一個標量(即它包含一個元素數據)則不須要爲backward()指定任何參數,
可是若是它有更多的元素,你須要指定一個gradient 參數來匹配張量的形狀。htm

譯者注:在其餘的文章中你可能會看到說將Tensor包裹到Variable中提供自動梯度計算,Variable 這個在0.41版中已經被標註爲過時了,如今能夠直接使用Tensor,官方文檔在這裏:
(https://pytorch.org/docs/stable/autograd.html#variable-deprecated)

具體的後面會有詳細說明

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=<AddBackward>)

結果y已經被計算出來了,因此,grad_fn已經被自動生成了。

print(y.grad_fn)
<AddBackward object at 0x00000232535FD860>

對y進行一個操做

z = y * y * 3
out = z.mean()

print(z, out)
tensor([[27., 27.],
        [27., 27.]], grad_fn=<MulBackward>) tensor(27., grad_fn=<MeanBackward1>)

.requires_grad_( ... ) 能夠改變現有張量的 requires_grad屬性。
若是沒有指定的話,默認輸入的flag是 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 0x000002325360B438>

梯度

反向傳播
由於 out是一個純量(scalar),out.backward() 等於out.backward(torch.tensor(1))

out.backward()

print gradients d(out)/dx

print(x.grad)
tensor([[4.5000, 4.5000],
        [4.5000, 4.5000]])

獲得矩陣 4.5.調用 out
Tensor\(o\)」.

獲得 \(o = \frac{1}{4}\sum_i z_i\),
\(z_i = 3(x_i+2)^2\) and \(z_i\bigr\rvert_{x_i=1} = 27\).

所以,
\(\frac{\partial o}{\partial x_i} = \frac{3}{2}(x_i+2)\), hence
\(\frac{\partial o}{\partial x_i}\bigr\rvert_{x_i=1} = \frac{9}{2} = 4.5\).

可使用 autograd 作更多的操做

x = torch.randn(3, requires_grad=True)

y = x * 2
while y.data.norm() < 1000:
    y = y * 2

print(y)
tensor([-920.6895, -115.7301, -867.6995], grad_fn=<MulBackward>)
gradients = torch.tensor([0.1, 1.0, 0.0001], dtype=torch.float)
y.backward(gradients)

print(x.grad)
tensor([ 51.2000, 512.0000,   0.0512])

若是.requires_grad=True可是你又不但願進行autograd的計算,
那麼能夠將變量包裹在 with torch.no_grad()中:

print(x.requires_grad)
print((x ** 2).requires_grad)

with torch.no_grad():
    print((x ** 2).requires_grad)
True
True
False

稍後閱讀:

autogradFunction 的官方文檔 https://pytorch.org/docs/autograd

相關文章
相關標籤/搜索