Dies ist der Code, den meine alte Antwort von einem anderen Thread hierher verschoben hat .
Ich habe lange Zeit eine quadratische symmetrische Matrix paarweiser Mahalanobis-Abstände in SPSS mithilfe eines Hat-Matrix-Ansatzes berechnet, bei dem ein lineares Gleichungssystem gelöst wird (das schneller ist als das Invertieren der Kovarianzmatrix).
Ich bin kein R-Benutzer, also habe ich gerade versucht, dieses Rezept hier in SPSS zusammen mit "meinem" Rezept auf der Basis von 1000 Fällen mit 400 Variablen zu reproduzieren , und ich habe meinen Weg erheblich schneller gefunden.
H
H (n-1)X ( X′X )- 1X′X
Zentrieren Sie also die Spalten der Datenmatrix, berechnen Sie die Hutmatrix, multiplizieren Sie sie mit (n-1) und führen Sie die der doppelten Zentrierung entgegengesetzte Operation aus. Sie erhalten die Matrix der quadratischen Mahalanobis-Abstände.
"Doppelte Zentrierung" ist die geometrisch korrekte Umwandlung von quadratischen Abständen (wie Euklidisch und Mahalanobis) in Skalarprodukte, die aus dem geometrischen Schwerpunkt der Datenwolke definiert werden . Diese Operation basiert implizit auf dem Kosinussatz . Stellen Sie sich vor, Sie haben eine Matrix aus quadratischen euklidischen Abständen zwischen Ihren multivariaten Datenpunkten. Sie ermitteln den Schwerpunkt (multivariates Mittel) der Wolke und ersetzen jeden paarweisen Abstand durch das entsprechende Skalarprodukt (Skalarprodukt), das auf den Abständen basierthh2h1h2cos
In unserer Einstellungen ist die „double-Zentrat“ Matrix spezifisch die Hut - Matrix (multipliziert mit n-1), nicht euklidische Skalarprodukt, und die sich ergebende Matrix quadrierte Abstand wird somit die quadrierten Matrix Mahalanobis - Distanz, nicht euklidische Distanzmatrix quadriert.
HH (n-1)H= {H,H,...}
D2m a h a l= H+ H′- 2 H ( n - 1 )
Der Code in SPSS und Speed Probe ist unten.
Dieser erste Code entspricht der @ahfoss-Funktion fastPwMahal
der angegebenen Antwort . Es ist mathematisch äquivalent dazu. Aber ich berechne die gesamte symmetrische Distanzmatrix (über Matrixoperationen), während @ahfoss ein Dreieck der symmetrischen Matrix (Element für Element) berechnet.
matrix. /*Matrix session in SPSS;
/*note: * operator means matrix multiplication, &* means usual, elementwise multiplication.
get data. /*Dataset 1000 cases x 400 variables
!cov(data%cov). /*compute usual covariances between variables [this is my own matrix function].
comp icov= inv(cov). /*invert it
call svd(icov,u,s,v). /*svd
comp isqrcov= u*sqrt(s)*t(v). /*COV^(-1/2)
comp Q= data*isqrcov. /*Matrix Q (see ahfoss answer)
!seuclid(Q%m). /*Compute 1000x1000 matrix of squared euclidean distances;
/*computed here from Q "data" they are the squared Mahalanobis distances.
/*print m. /*Done, print
end matrix.
Time elapsed: 3.25 sec
Das Folgende ist meine Modifikation, um es schneller zu machen:
matrix.
get data.
!cov(data%cov).
/*comp icov= inv(cov). /*Don't invert.
call eigen(cov,v,s2). /*Do sdv or eigen decomposition (eigen is faster),
/*comp isqrcov= v * mdiag(1/sqrt(s2)) * t(v). /*compute 1/sqrt of the eigenvalues, and compose the matrix back, so we have COV^(-1/2).
comp isqrcov= v &* (make(nrow(cov),1,1) * t(1/sqrt(s2))) * t(v). /*Or this way not doing matrix multiplication on a diagonal matrix: a bit faster .
comp Q= data*isqrcov.
!seuclid(Q%m).
/*print m.
end matrix.
Time elapsed: 2.40 sec
X ( X′X )- 1X′( X′X )- 1X′solve(X'X,X')
matrix.
get data.
!center(data%data). /*Center variables (columns).
comp hat= data*solve(sscp(data),t(data))*(nrow(data)-1). /*hat matrix, and multiply it by n-1 (i.e. by df of covariances).
comp ss= diag(hat)*make(1,ncol(hat),1). /*Now using its diagonal, the leverages (as column propagated into matrix).
comp m= ss+t(ss)-2*hat. /*compute matrix of squared Mahalanobis distances via "cosine rule".
/*print m.
end matrix.
[Notice that if in "comp ss" and "comp m" lines you use "sscp(t(data))",
that is, DATA*t(DATA), in place of "hat", you get usual sq.
euclidean distances]
Time elapsed: 0.95 sec