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

修改Tensor的.data属性后计算图与梯度计算的困惑

解析使用.data修改Tensor后梯度异常的原因

首先明确torch.autograd.grad(out, a, weight)的计算逻辑:这个函数计算的是加权和sum(weight * out)对a的梯度,对于每个元素a[i],梯度值为weight[i] * d(out[i])/d(a[i])。而sigmoid函数的导数公式是:d(sigmoid(x))/dx = sigmoid(x) * (1 - sigmoid(x)),也就是out[i] * (1 - out[i])(因为out[i] = sigmoid(a[i]))。

第一段代码的梯度计算

你通过c = out.data拿到了out的底层存储引用,直接修改c的数值后,out的实际值已经变成了[1, 3, 4](.data绕过了计算图,直接修改原Tensor的数值)。反向传播时,PyTorch会用out的当前数值来计算导数:

  • 第一个元素:1 * (1 - 1) = 0,乘以weight 1,得到0;
  • 第二个元素:3 * (1 - 3) = -6,乘以weight 1,得到-6;
  • 第三个元素:4 * (1 - 4) = -12,乘以weight 1,得到-12;
    这和你得到的d = tensor([0., -6., -12.])完全匹配。

第二段代码的梯度计算

同样,你用c.zero_()把out的数值改成了[0, 0, 0],反向传播时计算导数:

  • 每个元素都是0 * (1 - 0) = 0,乘以weight 1后结果都是0;
    所以得到d = tensor([0., 0., 0.])。

核心原因

.data直接操作Tensor的底层存储,不会被计算图追踪,这会导致正向传播的计算记录和反向传播时使用的Tensor数值不一致。虽然两段代码的正向流程看起来一样,但你修改了out的实际数值,反向传播时导数计算依赖的是修改后的out值,自然会得到不同的梯度结果。

注意事项

现在PyTorch官方已经不推荐使用.data,建议用.detach()获取脱离计算图的Tensor,但要注意.detach()返回的Tensor和原Tensor共享存储,修改它依然会影响原Tensor。如果需要修改且不影响原Tensor,应该用.detach().clone()。

内容的提问来源于stack exchange,提问作者BaeHann

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 20:32:55