You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 15:44:59