基于Kendall论文实现Pytorch回归偶然不确定性估计出现负损失问题
负损失与方差异常的核心原因
你遇到的两个问题根源完全一致:损失函数实现与Kendall论文的公式不匹配,具体错误如下:
- 论文中面向高斯分布的偶然不确定性损失(负对数似然)公式为:
$\mathcal{L} = \frac{1}{N}\sum_{i=1}^N \left( \frac{1}{2\sigma_i^2} (y_i - \mu_i)^2 + \frac{1}{2}\log \sigma_i^2 \right)$
你定义的$s_i = \log \sigma_i^2$,代入后残差项应为$\frac{1}{2}\exp(-s_i) * (y_i-\mu_i)^2$ - 你的代码中额外添加了
torch.sqrt,把平方误差改成了绝对值误差,残差项的量级被大幅压缩:当均值拟合效果较好时,残差绝对值非常小,远小于$|\frac{1}{2}s_i|$(当方差小于1时$s_i$为负),总损失就会变为负数。 - 同时模型为了最小化损失,会倾向于让$s_i$尽可能小(也就是方差尽可能趋近于0),最终输出的方差完全不符合真实噪声分布,也就是你遇到的方差异常问题。
修复方案
直接修改损失函数,删除多余的torch.sqrt即可,修正后的代码如下:
def loss_function(pred_mean, pred_log_var, y): return 1/len(pred_mean)*(0.5 * torch.exp(-pred_log_var)*torch.pow(y-pred_mean, 2)+0.5*pred_log_var).sum()
如果需要进一步提升训练稳定性,可以对pred_log_var加取值范围限制,避免数值溢出:
def loss_function(pred_mean, pred_log_var, y): # 限制log方差范围在-10到10之间,避免exp计算时出现数值异常 pred_log_var = torch.clamp(pred_log_var, min=-10, max=10) return 1/len(pred_mean)*(0.5 * torch.exp(-pred_log_var)*torch.pow(y-pred_mean, 2)+0.5*pred_log_var).sum()
修复后重新训练,损失不会再出现负值,输出的方差会稳定在你生成数据时添加的噪声水平(0.2左右),符合预期。
内容的提问来源于stack exchange,提问作者lauers
相关产品推荐
相关产品推荐

