torch.autograd

torch.autograd提供了类和函数用来对任意标量函数进行求导。要想使用自动求导,只需要对已有的代码进行微小的改变。只需要将所有的tensor包含进Variable对象中即可。

torch.autograd.backward(variables, grad_variables, retain_variables=False)

给定图的叶子节点variables, 计算图中变量的梯度和。

注意:我们需要在调用此函数之前将leaf variable的梯度置零。叶子节点和Variable是两个概念,叶子节点是说用户创建的变量,可以保存梯度以进行反向传播;Variable只是对tensor的包装,当设置Variable的required_grad=True时,可以计算梯度,但如果不是叶子节点的话,在反向传播之前会释放梯度。

参数说明:

  • variables (variable 列表) – 被求微分的叶子节点,即 ys 。
  • grad_variables (Tensor 列表) – 对应variable的梯度。仅当variable不是标量且需要求梯度的时候使用。
  • retain_variables (bool) – True,计算梯度时所需要的buffer在计算完梯度后不会被释放。如果想对一个子图多次求微分的话,需要设置为True。

class torch.autograd.Variable

包装一个Tensor,它同时保存着Variable的梯度和创建这个Variable的Function的引用。这个引用可以用来追溯创建这个Variable的整条链。如果Variable是用户创建的,那么它的creator是None,我们称这种对象为 leaf Variables

由于autograd只支持标量值的反向求导(即:y是标量),梯度的大小总是和数据的大小匹配。同时,仅仅给leaf variables分配梯度,其他Variable的梯度总是为0.

变量:

  • data – 包含的Tensor
  • grad – 保存着Variable的梯度。这个属性是懒分配的,且不能被重新分配。
  • requires_grad – 布尔值,指示这个Variable是否是被一个包含Variable的子图创建的。只能改变leaf variable的这个标签。
  • volatile – 布尔值,指示这个Variable是否被用于推断模式(即,不保存历史信息)。只能改变leaf variable的这个标签。
  • creator – 创建这个Variable的Function,对于leaf variable,这个属性为None。只读属性。这个属性其实是grad_fn,可能是官方文档上没有改正过来。下面提到creator我们都默认是grad_fn。

属性:

  • data (any tensor class) – 被包含的Tensor
  • requires_grad (bool) – requires_grad标记. 只能通过keyword传入.
  • volatile (bool) – volatile标记. 只能通过keyword传入.

所包含的方法:

  • backward(gradient=None, retain_variables=False)

当前Variableleaf variable求偏导。

计算图可以通过链式法则求导。如果Variable是 非标量(non-scalar)的,且requires_grad=True。那么此函数需要指定gradient,它的形状应该和Variable的长度匹配,里面保存了Variable的梯度。

此函数累积leaf variable的梯度。你可能需要在调用此函数之前将Variable的梯度置零。

参数:

  • gradient (Tensor) – 其他函数对于此Variable的导数。仅当Variable不是标量的时候使用,类型和位形状应该和self.data一致。gradient的作用是可以简单地理解成在求梯度时的权重,因为可能不同值的梯度对结果影响程度不同,所以pytorch弄了个这种接口,而没有固定为全是1。具体gradients参数的作用参考Pytorch autograd,backward详解。

  • retain_variables (bool) – True, 计算梯度所必要的buffer在经历过一次backward过程后不会被释放。如果你想多次计算某个子图的梯度的时候,设置为True。在某些情况下,使用autograd.backward()效率更高。

  • detach()

返回一个新的Variable,从当前图中分离下来的。

返回的Variable requires_grad=False,如果输入 volatile=True,那么返回的Variable volatile=True

注意:返回的Variable和原始的Variable公用同一个data tensor。in-place修改会在两个Variable上同时体现(因为它们共享data tensor),可能会导致错误。

  • detach_()

将一个Variable从创建它的图中分离,并把它设置成leaf variable

1. Variable内部机理

参考:Torch Autograd详解

实现autograd依赖于Variable和Function这两种数据类型。Variable是Tensor的外包装,Varibale和Tensor基本一致,区别在于多了下面几个属性。

torch.autograd_第1张图片

variable类型变量的data属性存储着Tensor数据,grad属性存储关于该变量的导数,creator是代表该变量的创造者。

Variable和Function它们是彼此不分开的,如下图所示,是数据向前传输和向后传输生成导数的过程。

torch.autograd_第2张图片

如图,假设我们有一个输入变量input(数据类型为Variable),input是用户输入的,所以其创造者creator为null值,input经过第一个数据操作operation1(比如加减乘除运算)得到output1变量(数据类型仍为Variable),这个过程中会自动生成一个function1的变量(数据类型为Function的一个实例),而output1的创造者就是这个function1。随后,output1再经过一个数据操作生成output2,这个过程也会生成另外一个实例function2,output2的创造者creator为function2。

在这个向前传播的过程中,function1和function2记录了数据input的所有操作历史,当output2运行其backward函数时,会使得function2和function1自动反向计算input的导数值并存储在grad属性中。

creator为null的变量才能被返回导数,比如input,若把整个操作流看成是一张图(Graph),那么像input这种creator为null的被称之为图的叶子(graph leaf)。而creator非null的变量比如output1和output2,是不能被返回导数的,它们的grad均为0。所以只有叶子节点才能被autograd。

例子: 参考PyTorch教程之Autograd

创建变量x

import torch
from torch.autograd import Variable

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

输出结果:

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

在x基础上进行运算:

y = x + 2 
print(y)

输出结果:

tensor([[3., 3.],
        [3., 3.]], grad_fn=<AddBackward0>)

查看x的grad_fn

None

查看y的grad_fn

print(y.grad_fn)

输出结果:

<AddBackward0 object at 0x0000027B00384C48>

可以看到y是作为运算的结果产生的,所以y有grad_fn,而x是直接创建的,所以x没有grad_fn。

在y基础上进行运算:

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

输出结果:

tensor([[27., 27.],
        [27., 27.]], grad_fn=<MulBackward0>)
tensor(27., grad_fn=<MeanBackward0>)

如果Variable是一个标量(例如它包含一个单元素数据),你无需对backward()指定任何参数.

out.backward()等价于out.backward(torch.Tensor([1.0])).

out.backward()
    print(x.grad)

输出结果:

tensor([[4.5000, 4.5000],
        [4.5000, 4.5000]])

如果它有更多的元素(矢量),你需要指定一个和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)

输出结果:

tensor([ 396.7552, 1183.1866,  862.6874], grad_fn=<MulBackward0>)

不传入参数:

y.backward()
print(x.grad)

输出结果:

RuntimeError: grad can be implicitly created only for scalar outputs

传入参数:

gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
y.backward(gradients)
print(x.grad)

输出结果:

tensor([5.1200e+01, 5.1200e+02, 5.1200e-02])

具体gradients参数的作用参考Pytorch autograd,backward详解

你可能感兴趣的:(#,Pytorch常用库,pytorch,torch.autograd)