autograd
包为tensors上的所有操作提供自动微分。是一个按运行定义的框架,这意味着你的反向求导是由代码的运行方式定义的,并且每个迭代都可以是不同的。
torch.Tensor
是autograd
包的中心类。
将Tensor的属性.requires_grad
设置为True
,它将开始跟踪其上的所有操作(比如加减乘除等等计算)。
完成计算后,可调用.backward()
自动计算所有梯度。此Tensor的梯度将累积到.grad
属性中。
调用.detach()
将tensor与梯度跟踪断开连接,防止其未来计算被跟踪
为了防止跟踪历史记录(和使用内存),还可以将代码包装在:with torch.no_grad():
里,这在评估模型时尤其有用,因为模型可能有可训练的参数,且.requires_grad = True
,但我们不需要求梯度。
另一个自动求导里非常重要的类Function
。
Tensor
和Function
是相互联系的,并建立了一个无环图,编码了完整的计算历史。
每个Tensor包含了一个属性.grad_fn
,用来引用创建Tensor的函数(用户创建的Tensor除外-它们的梯度为“None”)
如果要计算梯度,可以对Tensor调用.backward()
。
若Tensor是标量,则不需要为.backward()指定任何参数,但是如果它有更多元素,则需要指定一个梯度参数,该参数是匹配形状的Tensor
import torch
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=)
因为y是作为加法操作的结果,所以有grad_fn
print(y.grad_fn)
输出:
z = y * y * 3
out = z.mean()
print(z, out)
输出:
tensor([[27., 27.],
[27., 27.]], grad_fn=)
tensor(27., grad_fn=)
.requires_grad_( ... )
in-place的改变现有Tensor的requires_grad
的值. 默认为False
x= torch.randn(2, 2)
x = ((x * 3) / (x - 1))
print(x.requires_grad)
x.requires_grad_(True)
print(x.requires_grad)
y = (x * x).sum()
print(y.grad_fn)
输出:
False
True
y.backward()
因为b是标量,所以相当于
b.backard(torch.tensor(1.))
print(x.grad)
输出:
tensor([[4.5000, 4.5000],
[4.5000, 4.5000]])
一般而言,
autograd
是一计算向量-雅可比积的引擎。向量-雅可比积的特性,使得可以非常方便的将外部梯度输入到具有非标量输出的模型里。
x = torch.randn(3, requires_grad=True)
y = x * 2
while y.data.norm() < 1000:
y = y * 2
print(y)
输出:
tensor([ 20.5556, 285.4648, -1303.7313], grad_fn=)
下面 y 不再是标量.
torch.autograd
不能直接计算全部的雅可比式, 但如果知识需要向量-雅可比积, 简单的将向量作为参数输入backward
就可以:
v = torch.tensor([0.1, 1.0, 0.0001], dtype=torch.float)
y.backward(v)
print(x.grad)
输出:
tensor([1.0240e+02, 1.0240e+03, 1.0240e-01])
print(x.requires_grad)
print((x ** 2).requires_grad)
with torch.no_grad():
print((x ** 2).requires_grad)
输出:
True
True
False
print(x.requires_grad)
y = x.detach()
print(y.requires_grad)
print(x.eq(y).all())
输出
True
False
tensor(True)