Pytorch学习-自动求导
import torch
x = torch.arange(4.0)
x
tensor([0., 1., 2., 3.])
在计算梯度之前,需要存放梯度
x.requires_grad_(True)
x.grad #默认为None
y = 2*torch.dot(x,x)
y
tensor(28., grad_fn=<MulBackward0>)
通过调用反向传播函数来自动计算y关于x每个分量的梯度
y.backward()
x.grad
tensor([ 0., 4., 8., 12.])
x.grad == 4*x
tensor([True, True, True, True])
现在计算x的另一个函数
#在默认情况下,PyTorch会累积梯度,我们需要清除之前的值
x.grad.zero_()
#求向量的sum,梯度为全1
y = x.sum()
y.backward()
x.grad
tensor([1., 1., 1., 1.])
在深度学习中,我们的目的不是计算微分矩阵,而是批量中每个样本单独计算的偏导数之和。
#对非标量调用"backward"需要传入一个'gradient'参数,该参数指定微分函数
x.grad.zero_()
y = x*x
#等价于y.backward(torch.ones(len(x)))
y.sum().backward()
x.grad
tensor([0., 2., 4., 6.])
将某些计算移动到记录的计算图之外
#梯度清零
x.grad.zero_()
y = x*x
#将u视为标量
u = y.detach()
z = u * x
z.sum().backward()
x.grad == u
tensor([True, True, True, True])
x.grad.zero_()
y.sum().backward()
x.grad == 2*x
tensor([True, True, True, True])
即使构建函数的计算图需要通过Python控制流(例如:条件、循环或任意函数调用),我们仍然可以计算得到的变量的梯度
def f(a):
b = a*2
#norm用于求矩阵或向量范数
while b.norm() < 1000:
b = b*2
if b.sum() > 0:
c = b
else:
c = 100 * b
return c
#随机标量
a = torch.randn(size = (),requires_grad = True)
d = f(a)
d.backward()
a.grad == d/a
tensor(True)