运行Pyro多变量预测教程时cholesky出现奇异矩阵报错如何解决
报错原因
这个RuntimeError: torch.linalg.cholesky: singular U报错本质是数值稳定性问题:高斯分布的协方差/精度矩阵出现了奇异(不可逆)情况,大概率是Pyro 1.7.0版本默认的数值抖动(jitter)太小,或者你用的torch预览版(1.19.0是非正式发行版)和Pyro兼容性差,优化过程中噪声参数收敛到了不合理的区间,导致矩阵对角元趋近于0,cholesky分解失败。
修复方案
按照优先级从高到低尝试:
方案1:调大模型数值抖动(无需改源码)
在你定义Forecaster或者构造噪声分布的时候,手动增加jitter值:
- 如果是调用官方教程里的
LinearHMM噪声模型,构造的时候加参数jitter=1e-4 - 如果是自定义的多元正态噪声,给协方差矩阵的对角加小偏移:
# 假设你原来构造协方差的代码是cov = xxx cov = cov + torch.eye(cov.shape[-1], device=cov.device) * 1e-4 noise_model = MultivariateNormal(torch.zeros_like(mean), cov)
- 也可以在初始化Forecaster的时候传入参数
forecaster_options={"jitter": 1e-4}
方案2:替换兼容性更好的版本组合
你当前使用的torch 1.19.0是开发预览版,和Pyro 1.7.0适配性差,建议换正式版本组合:
- torch 1.10.2 + pyro-ppl 1.8.0
这个版本组合运行官方多变量预测教程没有稳定性问题。
方案3:修改Pyro源码兜底
如果以上方法都无效,直接修改Pyro底层cholesky函数的逻辑,强制加抖动:
找到本地环境中pyro/ops/tensor_utils.py文件的cholesky函数,修改为:
def cholesky(x): if x.size(-1) == 1: return x.sqrt() # 新增:给对角加小抖动保证矩阵正定 x = x + torch.eye(x.size(-1), device=x.device, dtype=x.dtype) * 1e-4 return torch.linalg.cholesky(x)
方案4:检查输入数据与训练参数
- 检查输入的多变量序列是否存在完全线性相关的特征,比如两个序列完全一样,这种情况要先做特征筛选,去掉冗余特征,或者给输入数据加极小的随机噪声
- 调低训练学习率:初始化Forecaster时传入
learning_rate=1e-3(默认值可能是1e-2,太高容易导致参数优化不稳定)
内容的提问来源于stack exchange,提问作者user14710374
相关产品推荐
相关产品推荐

