PyTorch实现拉格朗日对偶优化时反向传播报错的解决咨询
PyTorch线性规划对偶优化反向传播报错解决
问题根源
报错核心原因是**lagrange_multiplier的计算逻辑放在了循环外部**,导致它的计算图在第一次反向传播后被自动释放,第二次循环时试图复用已销毁的计算图。注意:zero_grad()只是清空参数的梯度值,并不会保留或重建计算图。
修复方案
把lagrange_multiplier = torch.nn.functional.softplus(_lagrange_multiplier)移到循环内部,每次迭代都重新计算拉格朗日乘子,这样每次都会生成全新的计算图,彻底避免复用已释放的图。不需要额外添加retain_graph=True(这里完全没必要,反而会浪费内存)。
修改后的完整代码:
c_t = torch.tensor(c).float() A_t = torch.tensor(A).float() b_t = torch.tensor(b).float() x_t = torch.rand(n, 1, requires_grad=True) def max_grad(grad): return -grad _lagrange_multiplier = torch.rand(m, requires_grad=True) _lagrange_multiplier.register_hook(max_grad) # 对lambda求最大化,反转梯度方向 opt_weights = torch.optim.Adam([x_t], lr=0.1) opt_lagrange = torch.optim.Adam([_lagrange_multiplier], lr=0.1) for i in range(10): print(i) opt_weights.zero_grad() opt_lagrange.zero_grad() # 每次循环重新计算拉格朗日乘子,生成新的计算图 lagrange_multiplier = torch.nn.functional.softplus(_lagrange_multiplier) objective = c_t.T @ x_t constraint = (A_t @ x_t).squeeze() - b_t lagrangian = objective + lagrange_multiplier.T @ constraint lagrangian.backward() opt_weights.step() opt_lagrange.step()
补充说明
softplus是可微分操作,必须每次迭代基于当前的_lagrange_multiplier重新计算,才能让梯度正确流经这个操作。如果放在循环外,第一次反向传播后该操作的中间张量会被释放,第二次循环时无法构建有效的反向传播路径。register_hook绑定在_lagrange_multiplier上,不需要移动位置,它会持续作用于这个参数的梯度计算过程。
内容的提问来源于stack exchange,提问作者Tob
相关产品推荐
相关产品推荐

