Pytorch的梯度计算
Pytorch支持在创建tensor时指明requires_grad参数,当该参数为True时,Pytorch会自动追踪对该tensor进行的所有操作,每次操作的结果会具有grad_fn属性来记录所做的操作:
# 创建一个张量,并设置需要计算梯度以对它的计算进行追踪
x = torch.ones(2, 2, requires_grad=True)
print(x)
# 进行一次张量操作
y = x + 2
print(y)
print(y.grad_fn) # y作为一次操作的结果,因此具有grad_fn属性
# 对y进行更多操作
z = y * y * 3
out = z.mean()
print(z, out)
运行结果:
使用requires_gard_()方法可以就地改变现有tensor的require_grad标志。若未给出输入标志,默认为False:
# .requires_grad_()方法可以就地改变现有张量的require_grad标志。若未给出输入标志,则默认为False
a = torch.randn(2, 2)
a = ((a * 3) / (a - 1))
print(a.requires_grad)
a.requires_grad_(True)
print(a.requires_grad)
b = (a * a).sum()
print(b.grad_fn)
运行结果:
设置require_grad参数为True后,执行反向传播(backward),Pytorch会自动计算对应tensor的梯度。举个简单的例子:
import torch
x = torch.ones(2, 2, requires_grad=True) # 设置需要计算梯度
y = x + 2
z = y * y * 3
out = z.mean() # 计算平均值
out.backward() # 执行反向传播
print(x.grad)
"""
这里相当于 out = 1/4 * 3 * (x + 2)^2,则dout/dx = 3/2 * (x + 2),当x=1时,dout/dx = 9/2 = 4.5
"""
运行结果:
关于Pytorch计算梯度的方法,可参考:
Pytorch的自动求导机制详解
对设置需要计算梯度的张量,可以将不需要计算梯度的操作包含在torch.no_grad()代码块中,它不会影响张量本身的require_grad属性:
import torch
x = torch.randn(3, requires_grad=True)
print(x.requires_grad)
print((x ** 2).requires_grad)
with torch.no_grad():
print((x ** 2).requires_grad)
print(x.requires_grad)
结果如下:
使用detach()方法可以获得内容相同但不需要计算梯度的新张量:
import torch
x = torch.randn(3, requires_grad=True)
y = x.detach() # 使用.detach()获得具有相同内容但不需要计算梯度的新Tensor
print(x.requires_grad)
print(y.requires_grad)
print(y.eq(x).all()) # 验证y与x内容相同
运行结果: