PyTorch执行.backward后i1.grad、i2.grad返回None的问题求解
问题根本原因
你代码中的计算逻辑完全切断了i1、i2和输出z之间的梯度计算链路,这是i1、i2梯度为None的核心原因,具体分为两点:
- 使用
math.cos、math.sin处理PyTorch张量时,会自动将张量转为无梯度信息的Python普通浮点数,直接丢失计算图跟踪关系。 - 对x、y的计算结果额外包裹
tr.tensor(),相当于用无梯度关联的普通数值创建新张量,彻底断开了i1、i2到x、y的依赖关系。此时z的计算图仅将x、y作为叶子节点,反向传播的梯度只会传递到x、y为止,i1、i2完全不在z的计算链路中,因此无论是否调用retain_grad()都无法获取梯度。
修复方案
仅需要调整x、y的计算逻辑即可:
- 替换所有
math库的三角函数为PyTorch自带的张量运算函数tr.cos、tr.sin,保证运算过程中计算图不会中断。 - 删除x、y赋值时外层的
tr.tensor()包裹,PyTorch张量运算的结果本身就是合法张量,会自动继承上游张量的梯度属性,保留计算链路。
修正后可正常获取梯度的代码如下:
import torch as tr import math i1 = tr.tensor(0.0, requires_grad=True) i2 = tr.tensor(0.0, requires_grad=True) # 移除tr.tensor包裹,替换math函数为torch内置函数 x = 2*(tr.cos(i1)*tr.cos(i2) - tr.sin(i1)*tr.sin(i2)) + 3*tr.cos(i1) y = 2*(tr.sin(i1)*tr.cos(i2) + tr.cos(i1)*tr.sin(i2)) + 3*tr.sin(i1) z = (x - (-2))**2 + (y - 3)**2 z.backward() dz_t1 = i1.grad dz_t2 = i2.grad print(dz_t1) print(dz_t2)
如果需要保留x、y的梯度,仅需要额外对x、y调用retain_grad()即可,不需要主动设置requires_grad=True,运算会自动继承上游的梯度属性。
内容的提问来源于stack exchange,提问作者Dr.
相关产品推荐
相关产品推荐

