PyTorch中间节点梯度丢失:为何coefficients.grad始终为None?
问题描述
我查阅过其他相关帖子,了解到默认情况下中间张量不会保留梯度,因此需要设置requires_grad=True,且在反向传播时需使用retain_grad()。但我无法理解为何以下示例中coefficients.grad始终为None?
def solvePolynomial(coefficients, x): return sum(coefficients[j] * (x**j) for j in range(len(coefficients))) coefficients = torch.randn(2, requires_grad=True) coefficients.retain_grad() # 这似乎对最后一行的错误无影响 predicted = torch.tensor([solvePolynomial(coefficients, x) for x in xs]) loss = ((predicted - ys)**2).mean() loss.requires_grad() # 我认为这是必需的?否则下一行会报错:element 0 of tensors does not require grad and does not have a grad_fn loss.backward() coefficients -= 0.01 * coefficients.grad # 此处总是失败,coefficients.grad始终为NoneType
问题原因与解决方法
核心问题是创建predicted张量时破坏了计算图的梯度传播链:
- 用列表推导式生成张量列表后,直接用
torch.tensor()包裹转换会切断原张量与coefficients的梯度关联——torch.tensor()默认创建新张量,不继承原有计算图信息。应该用torch.stack()拼接这些张量,它会完整保留计算图的梯度连接。 coefficients是叶子节点张量,不需要调用retain_grad(),这个方法是给非叶子节点用的,叶子节点的梯度会自动被保留,除非计算图断开。loss.requires_grad()这行完全多余,它仅返回布尔值,不会改变loss的梯度属性。loss由带梯度的coefficients计算而来,本身已经具备梯度传播能力。
修正后的代码
import torch def solvePolynomial(coefficients, x): return sum(coefficients[j] * (x**j) for j in range(len(coefficients))) # 补充xs和ys的示例值(原代码中缺失) xs = torch.tensor([1.0, 2.0, 3.0]) ys = torch.tensor([3.0, 7.0, 13.0]) coefficients = torch.randn(2, requires_grad=True) # 去掉多余的retain_grad() predicted = torch.stack([solvePolynomial(coefficients, x) for x in xs]) # 用stack替代torch.tensor() loss = ((predicted - ys)**2).mean() # 去掉多余的loss.requires_grad() loss.backward() coefficients -= 0.01 * coefficients.grad # 现在grad不再是None
内容的提问来源于stack exchange,提问作者errorline1
相关产品推荐
相关产品推荐

