自动求导: 自动微分

译者:@小王子

校对者:@李子文

PyTorch 中所有神经网络的核心是 autograd 自动求导包. 我们先来简单介绍一下, 然后我们会去训练我们的第一个神经网络.

autograd 自动求导包针对张量上的所有操作都提供了自动微分操作. 这是一个逐个运行的框架, 这意味着您的反向传播是由您的代码如何运行来定义的, 每个单一的迭代都可以不一样.

让我们用一些更简单的术语与例子来了解这些套路.

Variable(变量)

autograd.Variable 是包的核心类. 它包装了张量, 并且支持几乎所有的操作. 一旦你完成了你的计算, 你就可以调用 .backward() 方法, 然后所有的梯度计算会自动进行.

你还可以通过 .data 属性来访问原始的张量, 而关于该 variable(变量)的梯度会被累计到 .grad 上去.

Variable

Variable

还有一个针对自动求导实现来说非常重要的类 - Function.

VariableFunction 是相互联系的, 并且它们构建了一个非循环的图, 编码了一个完整的计算历史信息. 每一个 variable(变量)都有一个 .grad_fn 属性, 它引用了一个已经创建了 VariableFunction (除了用户创建的 Variable 之外 - 它们的 grad_fnNone ).

如果你想计算导数, 你可以在 Variable 上调用 .backward() 方法. 如果 Variable 是标量的形式(例如, 它包含一个元素数据), 你不必指定任何参数给 backward(), 但是, 如果它有更多的元素. 你需要去指定一个 grad_output 参数, 该参数是一个匹配 shape(形状)的张量.

  1. import torch
  2. from torch.autograd import Variable

创建 variable(变量):

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

variable(变量)的操作:

  1. y = x + 2
  2. print(y)

y 由操作创建,所以它有 grad_fn 属性.

  1. print(y.grad_fn)

y 的更多操作

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

梯度

我们现在开始了解反向传播, out.backward()out.backward(torch.Tensor([1.0])) 这样的方式一样

  1. out.backward()

但因 d(out)/dx 的梯度

  1. print(x.grad)

你应该得到一个 4.5 的矩阵. 让我们推导出 out Variableo”. 我们有 o = \frac{1}{4}\sum_i z_i, z_i = 3(x_i+2)^2z_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.

你可以使用自动求导来做很多有趣的事情

  1. x = torch.randn(3)
  2. x = Variable(x, requires_grad = True)
  3. y = x * 2
  4. while y.data.norm() < 1000:
  5. y = y * 2
  6. print(y)
  1. gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
  2. y.backward(gradients)
  3. print(x.grad)

稍候阅读:

VariableFunction 的文档请参阅 http://pytorch.apachecn.org/cn/docs/0.3.0/autograd.html