2015-01-05 11 views
15

Tekil değer ayrışımı M = USV *. Daha sonra M * M'nin özdeğer ayrışması M * M = V (S * S) V * = VS * U * USV * verir. Ben eigh işlevi tarafından döndürülen özvektörler svd işlevi tarafından döndürülen aynıdır göstererek Numpy ile bu eşitliğin doğrulamak isteyen:Numpy'nin iç ve dışkısı ile hesaplanan özvektörler eşleşmiyor

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)) 

son onaylama işlemi başarısız olur. Niye ya?

+0

ekleyebilir tüm diyagonal elemanlara pozitif bir sayı, yani M2 = M + a * I yapar, burada M2 M2 pozitif semidefnite yapmak için yeterince büyüktür. Daha sonra SVD ve daha iyisi kabul etmeli. –

cevap

14

Sorununuzu ayıklamak için sadece küçük sayılarla oynayın.

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

onlar sadece farklılık: Benim rastgele durumda büyüklüğü (50,20)

ile çok daha büyük matris yerine A=np.random.randn(3,2) ile

Başlat, ben

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

ve v2 için bulmak Bir işaret ve açıkça, birim modülüne sahip olsa bile, vektör bir işaret için farklılık gösterebilir.

Şimdi yine, Tamam budur ... başarısız, orijinal büyük matris için kandırmasına

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

çalışırsanız. Ne olur, bazı vektörler -1 ile çarpıldı, bazıları değil.

vektörler arasındaki eşitlik denetlemek için doğru bir yoldur: gerçekten

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

ve bu miktar yazdırabilirsiniz bu sizi nasıl çalıştığını hissi almak için:

(V1*V2).sum(0) 

yani gerçektendir ya +1 veya -1 vektöre bağlı olarak:

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

DÜZENLEME: Çoğu durumda, özellikle rastgele bir matristen başlıyorsa bu gerçekleşir. Bir veya daha fazla özdeğerler 1 daha büyük boyutta bir eigenspace varsa aşağıda onun yorumunda @Sven Marnach tarafından belirttiği gibi bu test olasılıkla, başarısız olacağını ancak Uyarı:

sadece çarpılır vektörleri dışındaki farklar olabilir -1. özdeğerler herhangi bir çok boyutlu eigenspace varsa , sen o eigenspace bir keyfi ortonormal alabilirsiniz ve böyle bazlar bir arbitraty üniteryen matris tarafından birbirlerine karşı döndürülmüş olabilir

+0

@matus Tamam, kayboldum :) Ama kararınıza güveniyorum ve bu yüzden yorumlarımı gelecekteki okuyucuları karıştırmamak için kaldıracağım. Şerefe! – BartoszKP

+0

Sadece vektörlerin -1 ile çarpılmasından başka farklılıklar olabilir.Eğer özdeğerlerden herhangi biri çok boyutlu bir eigens alanına sahipse, bu uzaysal alanın keyfi bir ortonormal temeline sahip olabilirsiniz ve bu türden üsler birbiri ardına tekdüze bir matris ile birbirlerine doğru döndürülebilir. –

+0

@SvenMarnach, bu çok geçerli bir noktadır. Bu uyarıya dikkat çekmek için yayını düzenleyeceğim – gg349

İlgili konular