2012-01-06 53 views
9

協方差矩陣的特徵值應該是實數且非負的,因爲協方差矩陣是對稱和半正定的。scipy.linalg.eig返回協方差矩陣的復特徵值?

但是,看看下面的實驗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 

回答

20

你提了兩個問題:

  1. 通過scipy.linalg.eig返回的特徵值是不是真實的。
  2. 某些特徵值是負值。

這兩個問題都是由截斷和舍入錯誤引起的錯誤的結果,這些錯誤始終發生在使用浮點算法的迭代算法中。請注意,Matlab結果也產生負特徵值。

現在,對於這個問題的一個更有趣的方面:​​爲什麼Matlab的結果是真實的,而SciPy的結果有一些複雜的組件?

Matlab的eig檢測輸入矩陣是真正的對稱還是厄密,並且當它是時使用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的印刷精度數字。

3

什麼,你遇到的是數值不穩定由於浮點精度的限制。

需要注意的是:

(1)MATLAB也回到負值,但打印格式設置爲short,你沒有看到存儲在內存雙的全精度。使用format long g打印更多小數點

(2)numpy的linalg.eig返回的所有虛部都接近機器精度。因此你應該將它們視爲零。