2015-01-05 49 views
15

考慮奇異值分解M = USV *。然後M * M的特徵值分解給出M * M = V(S * S)V * = VS * U * USV *。我希望通過展示由eigh函數返回的特徵向量是相同的svd功能恢復驗證與numpy的這種平等:用numpy的eigh和svd計算的特徵向量不匹配

import numpy as np 
np.random.seed(42) 
# create mean centered data 
A=np.random.randn(50,20) 
M= A-np.array(A.mean(0),ndmin=2) 

# svd 
U1,S1,V1=np.linalg.svd(M) 
S1=np.square(S1) 
V1=V1.T 

# eig 
S2,V2=np.linalg.eigh(np.dot(M.T,M)) 
indx=np.argsort(S2)[::-1] 
S2=S2[indx] 
V2=V2[:,indx] 

# both Vs are in orthonormal form 
assert np.all(np.isclose(np.linalg.norm(V1,axis=1), np.ones(V1.shape[0]))) 
assert np.all(np.isclose(np.linalg.norm(V1,axis=0), np.ones(V1.shape[1]))) 
assert np.all(np.isclose(np.linalg.norm(V2,axis=1), np.ones(V2.shape[0]))) 
assert np.all(np.isclose(np.linalg.norm(V2,axis=0), np.ones(V2.shape[1]))) 

assert np.all(np.isclose(S1,S2)) 
assert np.all(np.isclose(V1,V2)) 

最後斷言失敗。爲什麼?

+0

您可以添加對於所有對角線元素都是正數,即令M2 = M + a * I,其中a足夠大以使M2正半邊。那麼SVD和eigh應該更好地達成一致。 –

回答

14

只需使用小數字來調試您的問題。

開始A=np.random.randn(3,2)你有大小(50,20)

在我隨機的情況下大得多的矩陣,而不是,我發現

v1 = array([[-0.33872745, 0.94088454], 
    [-0.94088454, -0.33872745]]) 

v2

v2 = array([[ 0.33872745, -0.94088454], 
    [ 0.94088454, 0.33872745]]) 

,他們只對不同一個標誌,顯然,即使標準化爲單位模塊,向量也可能因符號而不同。

現在,如果你嘗試的伎倆

assert np.all(np.isclose(V1,-1*V2)) 

爲原來的大矩陣,失敗......一次,這是確定。會發生什麼是一些向量乘以-1,其他一些則沒有。

檢查向量之間平等的一個正確的方法是:

assert allclose(abs((V1*V2).sum(0)),1.) 

而事實上,得到的是如何工作的,你的感覺可以打印此量:

(V1*V2).sum(0) 

那的確是根據載體:+1-1

array([ 1., -1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 
    1., -1., 1., 1., 1., -1., -1.]) 

編輯:這將發生在大多數情況下,特別是如果從隨機矩陣開始。但是請注意,本次測試將有可能,如果失敗的一個或多個特徵值具有尺寸比1大的本徵空間,如下面他的評論中指出@Sven Marnach:

有可能不僅僅是矢量乘以其他方面的差異-1。 如果任何特徵值具有多維特徵空間,你 可能會得到固有空間的任意正交基,並 這樣的基地可能對彼此的arbitraty 一神教矩陣旋轉

+0

@matus好的,我迷路了:)但我相信你的判斷,所以我會刪除我的意見,不要混淆未來的讀者。乾杯! – BartoszKP

+0

除了向量乘以-1之外,可能還有其他差異。如果任何特徵值具有多維特徵空間,那麼可以得到該特徵空間的任意正交基,並且這樣的基可以通過任意一元矩陣相互旋轉。 –

+0

@SvenMarnach,這是一個非常有用的觀點。我將編輯這篇文章來指出這個警告 – gg349

相關問題