python - scipy.linalg.eig 返回协方差矩阵的复杂特征值?

标签 python matlab numpy scipy linear-algebra

协方差矩阵的特征值应该是实数且非负,因为协方差矩阵是对称的和半正定的。

但是,请看下面的 scipy 实验:

>>> a=np.random.random(5)
>>> b=np.random.random(5)
>>> ab = np.vstack((a,b)).T
>>> C=np.cov(ab)
>>> eig(C)
7.90174997e-01 +0.00000000e+00j,
2.38344473e-17 +6.15983679e-17j,
2.38344473e-17 -6.15983679e-17j,
-1.76100435e-17 +0.00000000e+00j,   
5.42658040e-33 +0.00000000e+00j

但是,在 Matlab 中重现上述示例可以正常工作:

a = [0.6271, 0.4314, 0.3453, 0.8073, 0.9739]
b = [0.1924, 0.3680, 0.0568, 0.1831, 0.0176]
C=cov([a;b])
eig(C)
-0.0000
-0.0000
 0.0000
 0.0000
 0.7902

最佳答案

您提出了两个问题:

  1. scipy.linalg.eig 返回的特征值不是真实的。
  2. 一些特征值是负的。

这两个问题都是截断和舍入错误引入的结果,使用浮点运算的迭代算法总是会发生这种情况。请注意,Matlab 结果也产生负特征值。

现在,问题的一个更有趣的方面:​​为什么 Matlab 的结果是真实的,而 SciPy 的结果有一些复杂的成分?

Matlab 的 eig 检测输入矩阵是实对称矩阵还是 Hermitian 矩阵,如果是,则使用 Cholesky 分解。请参阅 eig documentation 中对 chol 参数的描述.这不会在 SciPy 中自动完成。

如果您想使用利用实对称或厄米矩阵结构的算法,请使用 scipy.linalg.eigh .对于问题中的示例:

>>> eigh(C, eigvals_only=True)
array([ -3.73825923e-17,  -1.60154836e-17,   8.11704449e-19,
         3.65055777e-17,   7.90175615e-01])

如果您四舍五入到与 Matlab 打印的精度位数相同,则此结果与 Matlab 的结果相同。

关于python - scipy.linalg.eig 返回协方差矩阵的复杂特征值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8765310/

相关文章:

matlab - 基于第一行值扩展矩阵 (MATLAB)

python - 将整个数据框中的 NaN 值替换为其他值的平均值

optimization - 我应该往哪个方向走才能比 np.fft 更快

matlab - 如何在不同的子图中应用不同的颜色图?

Matlab 'heatmap' 与散点图数据

python - 生成新的列分组数据框

Python:使用 2 个或更多数据点推断趋势

python - pygame.display.update() 不能正常工作

python - Python如何判断两个文件是否相同

Python:如何将 'demote' 列标题更改为行并重命名列标题(不替换原始列标题)?