(Pytorch)torch.autograd.grad()与torch.autograd.backward()
一、torch.autograd.grad()
torch.autograd.grad(
outputs, # 计算图的数据结果张量--它就是需要进行求导的函数
inputs, # 需要对计算图求导的张量--它是进行求导的变量
grad_outputs=None, # 如果outputs不是标量,需要使用此参数
retain_graph=None, # 保留计算图
create_graph=None, # 创建计算图
allow_unused=False#inputs如果有不相关的变量,
#即不对Outputs产生贡献的,比如你随便乱写一个inputs在那里,会报错,
#改为True就不会报错,此时对这个垃圾inputs梯度为None返回。
)
① outputs为标量
outputs为标量时,不需要设置grad_outputs,保持grad_outputs=None即可
import torch
from torch import autograd
x = torch.rand(3, 4)
x.requires_grad_()
print(x)
# 对x中的所有元素求和,得到的结果是标量
y = torch.sum(x)
print(y)
grads = autograd.grad(y, x)[0] # 不加[0]原来是个元组
print(grads)
输出结果:
tensor([[0.3386, 0.4305, 0.9076, 0.9317],
[0.0469, 0.2624, 0.6704, 0.1637],
[0.1290, 0.4532, 0.2795, 0.4979]], requires_grad=True)
tensor(5.1112, grad_fn=<SumBackward0>)
tensor([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
② outputs为向量
outputs为向量时,求解梯度,需要将grad_outputs设置为全1的、与outputs形状相同的张量
import torch
from torch import autograd
x = torch.rand(3, 4)
x.requires_grad_()
print(x)
y = x[:,0] + x[:,1] # 每一行的前两列进行计算
print(y)
grad = autograd.grad(y, x, grad_outputs=torch.ones_like(y))[0]
print(grad)
输出结果:
tensor([[0.9690, 0.6985, 0.2925, 0.5004],
[0.9879, 0.1989, 0.4519, 0.6293],
[0.2920, 0.4773, 0.4992, 0.2948]], requires_grad=True)
tensor([1.6676, 1.1867, 0.7693], grad_fn=<AddBackward0>)
tensor([[1., 1., 0., 0.],
[1., 1., 0., 0.],
[1., 1., 0., 0.]])
③ 求二阶导数
import torch
from torch import autograd
x = torch.rand(3, 4)
x.requires_grad_()
print(x)
y = x ** 2
grad1 = autograd.grad(y, x, grad_outputs=torch.ones_like(y), create_graph=True)[0]
print(grad1)
grad2 = autograd.grad(grad1, x, grad_outputs=torch.ones_like(grad1))[0]
print(grad2)
输出结果:
tensor([[0.6094, 0.9100, 0.9239, 0.0150],
[0.5815, 0.1840, 0.2764, 0.7244],
[0.0326, 0.4640, 0.5433, 0.1477]], requires_grad=True)
tensor([[1.2189, 1.8200, 1.8479, 0.0300],
[1.1630, 0.3680, 0.5527, 1.4488],
[0.0652, 0.9280, 1.0865, 0.2953]], grad_fn=<MulBackward0>)
tensor([[2., 2., 2., 2.],
[2., 2., 2., 2.],
[2., 2., 2., 2.]])
可以看到 求出的一阶导数为2x,二阶导数为2
二、 torch.autograd.backward()
import torch
x=torch.rand(2,2,requires_grad=True)
print(x)
y=x +2
print(y)
z=torch.sum(y)
print(z)
# ①求dz/dx
dzdy=torch.autograd.grad(z,y,retain_graph=True)[0]
dzdx=torch.autograd.grad(y,x,grad_outputs=dzdy)[0]
print(dzdx)
print(dzdy)
# ② 求dz/dx
z.backward() #作用相当于backward(torch.ones_like(z))
print(x.grad)