神经网络训练中如何正确实现一个损失最大化、另一损失最小化
问题核心解决思路
- 最大化目标转最小化的方法
深度学习框架的优化器默认执行梯度下降最小化损失,要最大化某个损失分量,直接给该分量加负号即可。你原来的写法loss = loss1 + loss2相当于同时最小化loss1和loss2,和你要最大化loss2的需求完全相反,属于实现逻辑错误。
正确的总损失写法为:总损失 = 待最小化分量 + λ * (-待最大化分量)
其中λ是用来平衡两个损失量级的权重超参数。 - 多损失量级不平衡的解决方法
两个损失数值差距过大时,梯度会被数值大的分量主导,直接导致训练不稳定。你可以通过调整λ的取值,让两个损失分量的初始数值处于同一个量级:
- 先执行一次初始前向传播,获取初始状态下loss1和loss2的数值
- 按照
λ = 初始loss1数值 / 初始loss2数值设置初始λ,再根据实际训练效果微调即可
修正后的代码示例
loss1s = [] loss2s = [] # 先计算初始损失量级,设置平衡权重λ init_out = net(features) init_loss1 = torch.mean(torch.square(torch.tensor(5) - torch.sum(init_out))) init_loss2 = sum(w.sum() for w in net.parameters()) lam = init_loss1.item() / init_loss2.item() # 初始权重可根据训练效果手动调整 opt = optim.Adam(net.parameters()) for i in range(10000): opt.zero_grad() out = net(features) loss1 = torch.mean(torch.square(torch.tensor(5) - torch.sum(out))) loss2 = sum(w.sum() for w in net.parameters()) # 不要额外套torch.tensor,避免梯度断开 loss1s.append(loss1.item()) loss2s.append(loss2.item()) # 总损失逻辑:最小化loss1,最大化loss2,加λ平衡量级 loss = loss1 - lam * loss2 loss.backward() opt.step()
补充说明
如果后续需要处理更复杂的多损失优化场景,还可以选择动态加权方案,比如基于同方差不确定性的自动加权方法,不需要手动调参,但简单场景下手动调整λ的成本更低,效果也足够稳定。
内容的提问来源于stack exchange,提问作者Penguin
相关产品推荐
相关产品推荐

