@amoeba hatte ausgezeichnete Antworten auf PCA Fragen, darunter diese auf Bezug von SVD zu PCA. Bei der Beantwortung Ihrer genauen Frage werde ich drei Punkte ansprechen:
- Mathematisch gibt es keinen Unterschied, ob Sie PCA direkt in der Datenmatrix oder in ihrer Kovarianzmatrix berechnen
- Der Unterschied liegt lediglich in der numerischen Präzision und Komplexität. Das Anwenden von SVD direkt auf die Datenmatrix ist numerisch stabiler als auf die Kovarianzmatrix
- SVD kann auf die Kovarianzmatrix angewendet werden, um PCA durchzuführen oder Eigenwerte zu erhalten. Tatsächlich ist es meine bevorzugte Methode zur Lösung von Eigenproblemen
Es stellt sich heraus, dass SVD insbesondere für maschinelles Lernen stabiler ist als typische Verfahren zur Zerlegung von Eigenwerten. Beim maschinellen Lernen kommt es leicht zu hochkollinearen Regressoren. SVD funktioniert in diesen Fällen besser.
Hier ist Python-Code, um den Punkt zu demonstrieren. Ich habe eine hochkollineare Datenmatrix erstellt, ihre Kovarianzmatrix erhalten und versucht, deren Eigenwerte zu ermitteln. SVD funktioniert immer noch, während die gewöhnliche Eigenzerlegung in diesem Fall fehlschlägt.
import numpy as np
import math
from numpy import linalg as LA
np.random.seed(1)
# create the highly collinear series
T = 1000
X = np.random.rand(T,2)
eps = 1e-11
X[:,1] = X[:,0] + eps*X[:,1]
C = np.cov(np.transpose(X))
print('Cov: ',C)
U, s, V = LA.svd(C)
print('SVDs: ',s)
w, v = LA.eig(C)
print('eigen vals: ',w)
Ausgabe:
Cov: [[ 0.08311516 0.08311516]
[ 0.08311516 0.08311516]]
SVDs: [ 1.66230312e-01 5.66687522e-18]
eigen vals: [ 0. 0.16623031]
Aktualisieren
Als Antwort auf Federico Polonis Kommentar hier der Code mit Stabilitätsprüfungen von SVD gegen Eig an 1000 Zufallsstichproben derselben Matrix oben. In vielen Fällen zeigt Eig einen kleinen Eigenwert von 0 an, was zur Singularität der Matrix führen würde, und SVD tut dies hier nicht. SVD ist bei einer kleinen Eigenwertbestimmung etwa doppelt so genau, was je nach Problem möglicherweise wichtig ist oder nicht.
import numpy as np
import math
from scipy.linalg import toeplitz
from numpy import linalg as LA
np.random.seed(1)
# create the highly collinear series
T = 100
p = 2
eps = 1e-8
m = 1000 # simulations
err = np.ones((m,2)) # accuracy of small eig value
for j in range(m):
u = np.random.rand(T,p)
X = np.ones(u.shape)
X[:,0] = u[:,0]
for i in range(1,p):
X[:,i] = eps*u[:,i]+u[:,0]
C = np.cov(np.transpose(X))
U, s, V = LA.svd(C)
w, v = LA.eig(C)
# true eigen values
te = eps**2/2 * np.var(u[:,1])*(1-np.corrcoef(u,rowvar=False)[0,1]**2)
err[j,0] = s[p-1] - te
err[j,1] = np.amin(w) - te
print('Cov: ',C)
print('SVDs: ',s)
print('eigen vals: ',w)
print('true small eigenvals: ',te)
acc = np.mean(np.abs(err),axis=0)
print("small eigenval, accuracy SVD, Eig: ",acc[0]/te,acc[1]/te)
Ausgabe:
Cov: [[ 0.09189421 0.09189421]
[ 0.09189421 0.09189421]]
SVDs: [ 0.18378843 0. ]
eigen vals: [ 1.38777878e-17 1.83788428e-01]
true small eigenvals: 4.02633695086e-18
small eigenval, accuracy SVD, Eig: 2.43114702041 3.31970128319
Hier Code funktioniert der Code. Anstatt die zufällige Kovarianzmatrix zum Testen der Routinen zu generieren, generiere ich die zufällige Datenmatrix mit zwei Variablen:
wobei - unabhängige einheitliche Zufallsvariablen. Die Kovarianzmatrix lautet also
wobei - Varianzen der Uniformen und der Korrelationskoeffizienten zwischen Sie.u , v ( σ 2 1 σ 2 1 + ε & rgr; σ 1 σ 2 σ 2 1 + ε & rgr; σ 1 σ 2 σ 2 1 + 2 ε & rgr; σ 1
x1=ux2=u+εv
u,v(σ21σ21+ερσ1σ2σ21+ερσ1σ2σ21+2ερσ1σ2+ε2σ22σ2)
σ21,σ22,ρ
Sein kleinster Eigenwert:
Der kleine Eigenwert kann nicht durch einfaches Einstecken des in die Formel berechnet werden, da die Genauigkeit begrenzt ist. Sie müssen ihn also erweitern:
λ=12(σ22ε2−σ42ε4+4σ32ρσ1ε3+8σ22ρ2σ21ε2+8σ2ρσ31ε+4σ41−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−√+2σ2ρσ1ε+2σ21)
ελ≈σ22ε2(1−ρ2)/2
Ich führe Simulationen der Realisierungen der Datenmatrix aus, berechne die Eigenwerte der simulierten Kovarianzmatrix und die Fehler .λ j e j = λ - λ jj=1,…,mλ^jej=λ−λ^j