numpy 半正定警告

numpy positive semi-definite warning

在我正在编写的 Python 脚本中,我正在使用表达式

模拟多元正态随机向量
np.random.multivariate_normal(np.zeros(dim_obs), y_cov)

我的脚本 运行s,但生成以下警告:

RuntimeWarning: covariance is not positive-semidefinite.

还有我放入其中的小调试打印语句大部分时间都打印 False

print( np.all(np.linalg.eigvals(y_cov) > 0) )

为什么会出现误报?我的 y_cov 是半正定的,因为它是(抱歉缺少 TeX 标记)B x x'B' + y y' 其中 B 是矩阵,其他是每个元素为正的随机向量。

在这个特定的 运行 B 实际上只是一个大小为 9 的向量。我可以忽略这个警告吗? From the documentation:

Note that the covariance matrix must be positive semidefinite (a.k.a. nonnegative-definite). Otherwise, the behavior of this method is undefined and backwards compatibility is not guaranteed.

编辑: 这是一件 运行 完全可行的事情。感谢@user2357112 的提示。

import numpy as np
num_factors = 1
dim_obs = 9
u = np.random.normal(size = num_factors)
v = np.random.normal(size = dim_obs)
y_cov = np.dot(np.ones((9,1)), np.exp(u.reshape((num_factors,1))/2))
y_cov = np.dot(y_cov, np.exp(u.reshape((1,num_factors))/2)) #transpose
y_cov = np.dot(y_cov, np.transpose(np.ones((9,1))))
y_cov += np.dot(np.exp( v.reshape((dim_obs,1)) / 2), 
                np.exp( v.reshape((1,dim_obs)) / 2))
print( np.random.multivariate_normal(np.zeros(dim_obs), y_cov) )
print( np.all(np.linalg.eigvals(y_cov) > 0) )
print( np.linalg.eigvals(y_cov)  )

从理论上讲,您的矩阵是半正定矩阵,其中几个特征值恰好为零。但是浮点数的计算会引入截断误差,导致其中一些特征值非常小,但;因此,矩阵不是正半定的。

目前看来警告可以忽略;但是 NumPy 文档说非 psd 情况下的行为是未定义的,所以我不想依赖它。纠正浮点错误的一种方法是将单位矩阵的微小倍数添加到 y_cov。例如,像这样:

min_eig = np.min(np.real(np.linalg.eigvals(y_cov)))
if min_eig < 0:
    y_cov -= 10*min_eig * np.eye(*y_cov.shape)

添加一个固定的单位倍数,如 1e-12,适用于所有合理大小的矩阵,但对结果仍然没有影响。


为了完整性,重现问题的更简单方法:

import numpy as np
x = np.random.normal(size=(5,))
y = np.outer(x, x)
z = np.random.multivariate_normal(np.zeros(5), y)    

这会引发相同的警告(很有可能)。

在您的案例中生成高斯样本的更有效方法,也不受@zaq 确定的数值问题的影响,是观察协方差矩阵等于 a*a.T + b*b.Tab:列向量)在分布上等于随机向量 a*w1 + b*w2,其中 w1w2 是独立的高斯标量随机变量零均值和方差 1