2 - Autograd:自动微分

原文地址:
https://pytorch.org/tutorials/beginner/blitz/autograd_tutorial.html

Autograd: automatic differentiation 【Autograd:自动微分】

在PyTorch的所有神经网络的核心是autograd包。让我们首先简要地访问它,然后我们去训练我们地第一个神经网络。

autograd包未Tensor上地所有操作提供了自动微分。它是一个自由定义地框架,这意味着你的 BP算法是由你代码地运行方式定义地,并且每次迭代都是不同的。

让我们用更简单的术语来看看这些例子。

Tensor

torch.Tensor 是这个包的核心类。如果你设置它的属性 .requires_grad为True,则它会开始跟踪上面的所有操作。当你完成你的计算你可以调用 .backward()并且自动计算出所有梯度。tensor的梯度将会累积到 .grad属性中。

要停止tensor的跟踪历史,你可以调用 .detach()将其域计算历史记录分离,并且防止未来的计算被跟踪。

未来防止跟踪历史记录(和使用内存),你可以使用torch.no_grad():将代码块包装起来,在评估模型时这可能会非常有用,因为模型可能具有 reguires_grad=True的训练参数,但是我们不需要梯度。

还有一个类对于autograd实现非常重要- a Function.

Tensor和Function是互相连通的,并且构建了一个非循环图,它编码了一个完整的计算历史。每个tensor都有一个 .grad_fn属性,该属性引用function已创建的Tensor(除了用户所创建的Tensor-他们的grad_fn属性是None)。

如果你想计算导数,你可以在Tensor中调用 .backward()。如果Tensor是一个标量(也就是说它包含一个元素数据),则不需要指定任何参数 backward(),但是如果它有更多的元素,你需要指定一个和tensor匹配形状的梯度参数。

1
import torch

创建一个tensor并且设置requires_grad=true跟踪它的计算

1
2
x = torch.ones(2, 2, requires_grad=True)
print(x)

输出

1
2
tensor([[1., 1.],
[1., 1.]], requires_grad=True)

做一个tensor操作:

1
2
y = x + 2
print(y)

输出

1
2
tensor([[3., 3.],
[3., 3.]], grad_fn=<AddBackward>)

y是作为一个操作的结果创建的,所以它有一个grad_fn。

1
print(y.grad_fn)

输出

1
<AddBackward object at 0x00000251A7EC7F60>

在y上做更多的操作

1
2
3
4
z = y * y * 3
out = z.mean()

print(z, out)

输出

1
2
tensor([[27., 27.],
[27., 27.]], grad_fn=<MulBackward>) tensor(27., grad_fn=<MeanBackward1>)

.requires_grad_(…)
改变一个现有Tensor的requiresgrad标志。
如果没有给出输入标志,则默认为False。

1
2
3
4
5
6
7
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)

输出

1
2
3
False
True
<SumBackward0 object at 0x00000251A7ED09B0>

Gradients 【梯度】

现在让我们后退一步,因为out包含一个标量,out.backward()等价于out.backward(torch.tensor(1))。

1
out.backward()

输出梯度d(out)/ dx

1
print(x.grad)

输出

1
2
tensor([[4.5000, 4.5000],
[4.5000, 4.5000]])

你应该有一个矩阵4.5. 我们称 outTensor “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)$, 因此
$\frac{\partial o}{\partial x_i}\bigr\rvert_{x_i=1} = \frac{9}{2} = 4.5$.

你可以用autograd做很多疯狂的事情!

1
2
3
4
5
6
7
x = torch.randn(3, requires_grad=True)

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

print(y)

输出

1
tensor([-816.7130, 1152.6641,  765.0383], grad_fn=<MulBackward>)
1
2
3
4
gradients = torch.tensor([0.1, 1.0, 0.0001], dtype=torch.float)
y.backward(gradients)

print(x.grad)

输出

1
tensor([ 102.4000, 1024.0000,    0.1024])

我们可以阻止autograd跟踪历史在Tensor上使用 .requires_grad=True 使用torch.no_grad()将代码块封装起来。

1
2
3
4
5
print(x.requires_grad)
print((x ** 2).requires_grad)

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

输出

1
2
3
True
True
False

Read Later:

Documentation of autograd and Function is at http://pytorch.org/docs/autograd