pytorch api文档:张量的 backward()方法-反向传播自动计算梯度(求导)

作用

在 PyTorch 中,.backward() 是张量(Tensor)的一个方法,用于自动计算梯度(求导)。
PyTorch 会通过构建计算图(Computational Graph)记录张量的运算过程,调用 .backward() 时,会从当前张量(通常是标量损失值)出发,沿着计算图 反向传播,计算出图中所有依赖张量的梯度,并将梯度存储到对应张量的 .grad 属性中。

前提

只有设置了 requires_grad=True 的张量,才会被追踪运算并计算梯度(默认是 False)。

例子

1. 对标量张量调用 .backward()(最常用场景)

这是训练模型时的核心场景(损失函数输出是标量),无需传入参数:

import torch

# 1. 定义需要求导的张量
x = torch.tensor([2.0], requires_grad=True)
y = torch.tensor([3.0], requires_grad=True)

# 2. 构建计算图:z = x² + y³
z = x**2 + y**3

# 3. 反向传播,计算梯度
z.backward()

# 4. 查看梯度(dz/dx = 2x, dz/dy = 3y²)
print("dz/dx =", x.grad)  # 输出:tensor([4.])
print("dz/dy =", y.grad)  # 输出:tensor([27.])

2. 对矩阵张量调用 .backward()

如果要对向量/矩阵调用 .backward(),必须传入一个与当前张量形状相同的 gradient 参数(相当于“梯度的权重”),本质是计算“当前张量 × 传入梯度”的标量对各参数的梯度:

import torch

# 定义张量
x = torch.tensor([1.0, 2.0, 3.0], requires_grad=True)
# 非标量输出:y = 2x
y = 2 * x

# 对y反向传播,需传入gradient参数(比如全1向量)
y.backward(gradient=torch.ones_like(y))

# 查看梯度(dy/dx = 2)
print("dy/dx =", x.grad)  # 输出:tensor([2., 2., 2.])

注意事项

梯度累加问题

PyTorch 不会自动清空 .grad 属性,多次调用 .backward() 会导致梯度累加。因此在训练模型时,每次反向传播前需要用 optimizer.zero_grad() 清空梯度:

# 示例:模拟训练循环中的梯度清空
x = torch.tensor([2.0], requires_grad=True)
for _ in range(2):
    y = x**2
    y.backward()
    print(x.grad)  # 第一次输出tensor([4.]), 第二次输出tensor([8.])

# 正确做法:清空梯度
x.grad.zero_()  # 或 optimizer.zero_grad()
y = x**2
y.backward()
print(x.grad)  # 输出tensor([4.])

计算图的保留与释放

默认情况下,调用 .backward() 后,计算图会被销毁(节省内存)。如果需要多次反向传播(如RNN训练),需设置 retain_graph=True:

x = torch.tensor([2.0], requires_grad=True)
y = x**2
y.backward(retain_graph=True)  # 保留计算图
print(x.grad)  # tensor([4.])
y.backward()   # 可再次调用,计算图最终销毁
print(x.grad)  # tensor([8.])

禁止梯度计算

如果不需要计算梯度(如验证/测试阶段),可以用 torch.no_grad() 上下文管理器,避免构建计算图,提升效率:

x = torch.tensor([2.0], requires_grad=True)
with torch.no_grad():
    y = x**2
    # y.backward()  # 此处调用会报错,因为no_grad下不追踪梯度
print(y.requires_grad)  # 输出:False

总结

  1. .backward() 的核心作用是反向传播计算梯度,梯度会存储在张量的 .grad 属性中,仅对 requires_grad=True 的张量有效。
  2. 标量张量调用 .backward() 无需传参,非标量需传入同形状的 gradient 参数。
  3. 关键注意点:训练时需用 zero_grad() 清空梯度,多次反向传播需设置 retain_graph=True,无需梯度时用 torch.no_grad() 提升效率。

原文出处:/show_1GW2ehYk3VIf.html