在我正在编写的 Python 脚本中,我正在使用表达式模拟多元正态随机向量
np.random.multivariate_normal(np.zeros(dim_obs), y_cov)
我的脚本运行,但生成以下警告:
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) )
最佳答案
理论上,您的矩阵是半正定矩阵,其中几个特征值恰好为零。但是 float 的计算会引入截断误差,导致其中一些特征值非常小但负;因此,矩阵不是正半定的。
目前看来警告可以忽略;但是 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)
这会引发相同的警告(很有可能)。
关于python - numpy 半正定警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41515522/