PyTorch模型反向传播时权重不更新、损失值恒定问题排查求助
问题定位
核心原因是模型输出到损失计算之间的计算图完全断裂,损失和模型参数没有梯度关联,反向传播无法把梯度回传到权重,所以权重不会更新,损失自然保持恒定。
具体问题点
- 张量转原生数值导致梯度丢失
你拿到模型输出output之后,使用float(output[0])、round()操作将带梯度的PyTorch张量转换为了Python原生数值,这一步直接清除了所有梯度关联属性。后续你操作的drawn_image是普通Numpy数组,最后计算损失时生成的drawn_image_tensor是从Numpy数组重新转换的张量,和模型输出、模型参数完全没有计算图依赖关系,反向传播时没有梯度可以回传到网络层。
你给输入张量设置requires_grad=True对解决这个问题没有任何作用,问题出在输出后的计算链路,和输入无关。 - 离散操作不可微
即使你不做数值转换,你用到的round、Numpy版的画线操作本身都是不可微的离散操作,PyTorch无法对这类操作计算梯度,一样会导致梯度链路中断。 - 超参数设置不合理
你设置的Adam优化器学习率为0.1,数值过大,即使梯度通路正常,也大概率会出现训练震荡无法收敛的问题。
修复方案
- 全程保留张量计算链路,不要将模型输出转换为Python原生数值/Numpy数组,所有计算尽量用PyTorch算子实现。
- 替换当前的离散画线逻辑,改用可微渲染实现:你可以针对10x10的小尺寸图像,自己实现简单的可微画线函数,计算每个像素到目标线段的距离,用距离权重平滑赋值给对应像素,替代离散的画线操作。
- 移除
round操作,如果需要限制RGB输出范围在0-255之间,可以在模型输出层加sigmoid激活后再缩放到对应范围。 - 调小学习率到1e-4 ~ 1e-3区间,避免训练震荡。
- 可以调整训练逻辑,累计完10次画线的总损失后再统一执行反向传播,减少梯度噪声。
内容的提问来源于stack exchange,提问作者EmilUpp
相关产品推荐
相关产品推荐

