自动微分
创建一个张量,设置 requires_grad=True 来跟踪与它相关的计算
如果将其属性 .requires_grad 设置为 True,则会开始跟踪针对 tensor 的所有操作。
import torch
#创建一个张量,设置 requires_grad=True 来跟踪与它相关的计算
#如果将其属性 .requires_grad 设置为 True,则会开始跟踪针对 tensor 的所有操作。
x = torch.ones(2, 2, requires_grad=True)
print(x)
# 对张量做一个操作
y = x + 2
print(y)
# y 作为操作的结果被创建,所以它有 grad_fn
# 每个张量都有一个 .grad_fn 属性保存着创建了张量的 Function 的引用
print(y.grad_fn)
# output:<AddBackward0 object at 0x00000110648210F0>
z = y * y * 3
out = z.mean()
print(z, out)
# output:tensor([[27., 27.],
[27., 27.]], grad_fn=<MulBackward0>) tensor(27., grad_fn=<MeanBackward0>)
如果用户自己创建张量,grad_fn为None
a = torch.randn(2, 2)
a = ((a * 3) / (a - 1))
# 通过requires_grad_()会改变张量的 requires_grad标记。输入的标记默认为 False
print(a.requires_grad)
a.requires_grad_(True)
print(a.requires_grad)
b = (a * a).sum()
print(b.grad_fn)
# output:
False
True
<SumBackward0 object at 0x0000011061052A58>
#我们现在后向传播,因为输出包含了一个标量,out.backward()等同于out.backward(torch.tensor(1.)),如果你想计算导数,你可以调用Tensor.backward()。如果 Tensor 是标量,则不需要指定任何参数backward(),但是如果它有更多元素,则需要指定一个gradient 参数来指定张量的形状。
# 梯度反向传播
out.backward()
梯度为4.5,是out对x求偏导的出的结果
print(x.grad)
tensor([[4.5000, 4.5000],
[4.5000, 4.5000]])
可以通过将代码包裹在 with torch.no_grad(),来停止对从跟踪历史中的 .requires_grad=True 的张量自动求导。要停止跟踪历史记录(和使用内存),还可以将代码块使用 with torch.no_grad(): 包装起来。在评估模型时,这是特别有用,因为模型在训练阶段具有 requires_grad = True 的可训练参数有利于调参,但在评估阶段我们不需要梯度。
print(x.requires_grad)
print((x ** 2).requires_grad)
with torch.no_grad():
print((x ** 2).requires_grad)
output:
True
True
False