PyTorch调用Optimizer后模型参数无法更新的问题求助
模型参数不更新问题的诊断与解决
核心原因:不可导操作导致梯度断裂
你的CLUSTER_L模型forward方法中使用了round()函数:
outputs = ((self.af(d_outputs)+0.1)*10).round()
round()是不可导的离散操作,反向传播时该操作的梯度为0,导致梯度无法传递到前面的线性层(self.cl中的参数),因此执行loss.backward()后,模型参数的梯度始终为0,optimiser_c.step()自然无法更新参数。
即使替换为cross_entropy,只要round()还在,梯度传递就会被阻断,参数依然不会更新。
解决方案
1. 移除或替换不可导的round()操作
训练阶段必须保证前向传播的所有操作都是可导的,建议先移除round(),仅在推理阶段对输出做离散化处理:
修改后的forward方法:
def forward(self, inputs): d_outputs = self.cl(inputs).view(self.n*self.lbd, self.input_size) # 训练阶段仅保留可导操作,移除round() outputs = (self.af(d_outputs)+0.1)*10 outputs2 = outputs * inputs return outputs2
如果业务需求必须在训练阶段做近似离散化,可以用可导的近似函数替代round(),比如用硬sigmoid配合缩放:
# 用平滑函数近似round,保留可导性 def smooth_round(x): return torch.floor(x) + torch.sigmoid(10*(x - torch.floor(x) - 0.5)) outputs = smooth_round((self.af(d_outputs)+0.1)*10)
2. 其他排查要点
- 确认
cluster_L损失函数返回的是标量且requires_grad为True(可打印loss_Cluster.requires_grad验证) - 检查优化器绑定的
c_param是否包含cluster的所有可训练参数(可打印len(c_param),对应3个线性层的权重+偏置,共6个参数) - 暂时注释
clip_grad_norm_,验证是否因梯度裁剪阈值过大导致梯度被清零
修改后的验证步骤
- 移除
round()后,在loss.backward()后打印cluster.cl[0].weight.grad,确认梯度不为0 - 执行
optimiser_c.step()后,对比参数更新前后的值,确认参数已变化
内容的提问来源于stack exchange,提问作者KaraLee
相关产品推荐
相关产品推荐

