协方差矩阵的特征值应为实数且为非负值,因为协方差矩阵是对称且为半正定的。
但是,请看下面的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
您提出了两个问题:
scipy.linalg.eig
这两个问题都是由截断和舍入错误引入的错误的结果,而在使用浮点算术的迭代算法中总是会发生这种错误。请注意,Matlab结果也产生了负的特征值。
现在,对于问题的一个更有趣的方面:为什么Matlab的结果是真实的,而SciPy的结果却包含一些复杂的成分?
Matlabeig检测输入矩阵是实对称的还是Hermitian的,并在输入时使用Cholesky因式分解。请参阅文档中对自chol变量的描述。这不是在SciPy中自动完成的。eig
eig
chol
如果要使用利用实数对称或Hermitian矩阵结构的算法,请使用scipy.linalg.eigh。对于问题中的示例:
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的结果相同。