Ich muss den Mahalanobis-Abstand in R zwischen jedem Beobachtungspaar in einer Matrix von Kovariaten berechnen. Ich benötige eine effiziente Lösung, dh es werden nur Abstände berechnet und vorzugsweise in C / RCpp / Fortran usw. implementiert. Ich gehe davon aus, dass , die Populationskovarianzmatrix, unbekannt ist, und verwende die Stichprobe Kovarianzmatrix an seiner Stelle.Σ
Diese Frage interessiert mich besonders, da es anscheinend keine "Konsensus" -Methode zur paarweisen Berechnung von Mahalanobis-Abständen in R gibt, dh sie ist weder in der dist
Funktion noch in der cluster::daisy
Funktion implementiert . Die mahalanobis
Funktion berechnet keine paarweisen Abstände ohne zusätzliche Arbeit vom Programmierer.
Dies wurde hier bereits paarweise nach Mahalanobis Entfernung in R gefragt , aber die Lösungen dort scheinen falsch zu sein.
Hier ist eine korrekte, aber furchtbar ineffiziente Methode (da Entfernungen berechnet werden):
set.seed(0)
x0 <- MASS::mvrnorm(33,1:10,diag(c(seq(1,1/2,l=10)),10))
dM = as.dist(apply(x0, 1, function(i) mahalanobis(x0, i, cov = cov(x0))))
Das ist einfach genug, um mich in C zu programmieren, aber ich bin der Meinung, dass dieses Basic eine bereits vorhandene Lösung haben sollte. Ist dort eines?
Es gibt andere Lösungen, die zu kurz kommen: HDMD::pairwise.mahalanobis()
Berechnet Abstände, wenn nur eindeutige Abstände erforderlich sind. scheint vielversprechend zu sein, aber ich möchte nicht, dass meine Funktion von einem Paket kommt , das davon abhängt , was die Fähigkeit anderer stark einschränkt, meinen Code auszuführen. Sofern diese Implementierung nicht perfekt ist, schreibe ich lieber meine eigene. Hat jemand Erfahrung mit dieser Funktion?compositions::MahalanobisDist()
rgl
quelle
Antworten:
Ausgehend von Ahfoss '"Succint" -Lösung habe ich die Cholesky-Zerlegung anstelle der SVD verwendet.
Es sollte schneller sein, da das Vorwärtslösen eines Dreiecksystems schneller ist als die dichte Matrixmultiplikation mit der inversen Kovarianz ( siehe hier ). Hier sind die Benchmarks für die Lösungen von ahfoss und whuber in verschiedenen Umgebungen:
Cholesky scheint also gleichmäßig schneller zu sein.
quelle
Die Standardformel für den quadratischen Mahalanobis-Abstand zwischen zwei Datenpunkten lautet
wobei ein p × 1- Vektor ist, der der Beobachtung i entspricht . Typischerweise wird die Kovarianzmatrix aus den beobachteten Daten geschätzt. Ohne die Matrixinversion zu zählen, erfordert diese Operation p 2 + p Multiplikationen und p 2 + 2 p Additionen, die jeweils n ( n - 1 ) / 2 Mal wiederholt werden .xich p × 1 ich p2+ p p2+ 2 p n ( n - 1 ) / 2
Betrachten Sie die folgende Ableitung:
wo . Man beachte, dassxTiΣ-1 istqich= Σ- 12xich . Dies beruht auf der Tatsache, dassΣ-1xTichΣ- 12= ( Σ- 12xich)T= qTich ist symmetrisch, was aufgrund der Tatsache gilt, dass für jede symmetrische diagonalisierbare MatrixA=PEPT,Σ- 12 A = PEPT
Wenn wir und beachten, dass Σ - 1 symmetrisch ist, sehen wir, dass Σ - 1A = Σ- 1 Σ- 1 muss auch symmetrisch sein. WennXist dien×pMatrix von Beobachtungen undQist dien×pMatrixso dass dieithReihe vonQistQi, dannQkann kurzbündig ausgedrückt werdenXΣ-1Σ- 12 X n × p Q. n × p icht h Q. qich Q. . Dies und die vorherigen Ergebnisse implizieren diesXΣ- 12
Die einzigen Operationen, die n ( n - 1 ) / 2 malberechnet werden,sind p Multiplikationen und 2 p Additionen (im Gegensatz zu den p 2 + p Multiplikationen und p 2 + 2 p
quelle
pair.diff()
funktioniert, und auch ein numerisches Beispiel mit Ausdrucken aller Schritte Ihrer Funktion angeben ? Vielen Dank.Versuchen wir das Offensichtliche. Von
es folgt, dass wir den Vektor berechnen können
in Zeit und der MatrixO ( p2)
in , höchstwahrscheinlich unter Verwendung integrierter schneller (parallelisierbarer) Array-Operationen, und bilden Sie dann die Lösung alsO ( p n2+ p2n )
wobei das äußere Produkt in Bezug auf + ist : ( a ⊕ b ) i j = a i + b j .⊕ + ( a ⊕ b )ich j= aich+ bj.
EineΣ = Var ( X) h
R
Implementierung entspricht genau der mathematischen Formulierung (und setzt damit voraus, dass tatsächlich invertierbar ist , wenn hier h invers geschrieben wird ):Beachten Sie aus Gründen der Kompatibilität mit den anderen Lösungen, dass nur die eindeutigen nicht diagonalen Elemente zurückgegeben werden und nicht die gesamte quadratische Distanzmatrix (symmetrisch, null auf der Diagonale). Scatterplots zeigen, dass die Ergebnisse mit denen von übereinstimmen
fastPwMahal
.In C oder C ++ kann RAM wiederverwendet werden und berechnet im laufenden Betrieb , erübrigt jegliche Notwendigkeit zur Zwischenlagerung von u ⊕ u .u ⊕ u u ⊕ u
Timing-Studien mit Bereich von 33 bis 5000 und p im Bereich von 10 bis 100 zeigen, dass diese Implementierung 1,5- bis 5- mal schneller ist als in diesem Bereich. Die Verbesserung wird besser, wenn p und n zunehmen. Folglich können wir erwarten , dass wir für kleinere p überlegen sind . Die Gewinnschwelle liegt bei p = 7 für n ≥ 100n 33 5000 p 10 100 1.5 5 p n p p = 7 n ≥ 100 . Ob sich die gleichen Rechenvorteile dieser einfachen Lösung auch auf andere Implementierungen beziehen, hängt davon ab, wie gut sie vektorisierte Array-Operationen nutzen.
fastPwMahal
fastPwMahal
quelle
apply
undouter
... zu verlieren, außer zu brechenRcpp
.R
mir einig, dass darin anscheinend nichts zu gewinnen ist.Wenn Sie die Mahalanobis- Beispielentfernung berechnen möchten , gibt es einige algebraische Tricks, die Sie ausnutzen können. Sie alle führen dazu, paarweise euklidische Entfernungen zu berechnen. Nehmen wir also an, wir können sie dafür verwendenX n × p p O ( n p )
dist()
. Lassen bezeichnen die n × p Datenmatrix, die wir annehmen , so zentriert werden , dass ihre Spalten Mittelwert 0 und Rang haben p , so dass die Probe Kovarianzmatrix nichtsingulär ist. (Zentrieren erfordert O ( n p ) Operationen.) Dann wird die Probe Kovarianzmatrix S = X T X / n .Die paarweise Mahalanobis Probenabstände von ist das gleiche wie die paarweise euklidischen Distanzen von X L für jede Matrix L erfüllen L L T = S - 1 , zum Beispiel der Quadratwurzel oder Cholesky - Faktor. Dies folgt aus einer linearen Algebra und führt zu einem Algorithmus, der die Berechnung von S , S - 1 und eine Cholesky - Zerlegung erfordert . Die Komplexität im ungünstigsten Fall ist O ( n p 2 + p 3 ) .X
Tiefer beziehen sich diese Abstände zwischen den Probenhauptkomponenten auf Abstände . Let X = U D V T den SVD bezeichnet X . Dann S = V D 2 V TX X= UD VT X und S - 1 / 2 = V D - 1 V T n 1 / 2 . So X S - 1 / 2 = U V T n 1
Hier ist eine R-Implementierung der zweiten Methode, die ich auf dem iPad, mit dem ich diese Antwort schreibe, nicht testen kann.
quelle
Dies ist eine sehr viel prägnantere Lösung. Es basiert immer noch auf der Ableitung mit der Kovarianzmatrix der Quadratwurzel (siehe meine andere Antwort auf diese Frage), verwendet jedoch nur die Basis R und das Statistikpaket. Es scheint etwas schneller zu sein (ungefähr 10% schneller in einigen Benchmarks, die ich ausgeführt habe). Beachten Sie, dass es die Mahalanobis-Distanz im Gegensatz zur quadratischen Maha-Distanz zurückgibt.
Diese Funktion erfordert eine inverse Kovarianzmatrix und gibt kein Entfernungsobjekt zurück. Ich vermute jedoch, dass diese abgespeckte Version der Funktion für das Stapeln von Exchange-Benutzern allgemeiner nützlich ist.
quelle
SQRT
durch die Cholesky-Zerlegung verbessert werdenchol(invCovMat)
.Wenn Sie nur die Fortran77-Funktionen in der Benutzeroberfläche verwenden, ist Ihr Unterprogramm für andere Benutzer noch portabel genug.
quelle
Es gibt eine sehr einfache Möglichkeit, dies mit dem R-Paket "biotools" zu tun. In diesem Fall erhalten Sie eine quadratische Mahalanobis-Matrix.
quelle
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.
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 basierth h2 h1h2cos
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.
H= {H,H,...}
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.Das Folgende ist meine Modifikation, um es schneller zu machen:
solve(X'X,X')
quelle
Die von Ihnen veröffentlichte Formel berechnet nicht das, was Sie zu berechnen glauben (eine U-Statistik).
In dem Code, den ich gepostet habe, verwende ich
cov(x1)
als Skalierungsmatrix (dies ist die Varianz der paarweisen Unterschiede der Daten). Sie verwendencov(x0)
(dies ist die Kovarianzmatrix Ihrer Originaldaten). Ich denke, das ist ein Fehler von Ihrer Seite. Der springende Punkt bei der Verwendung der paarweisen Unterschiede ist, dass Sie nicht davon ausgehen müssen, dass die multivariate Verteilung Ihrer Daten symmetrisch um ein Symmetriezentrum ist (oder dass Sie dieses Symmetriezentrum für diese Angelegenheit schätzen müssen, dacrossprod(x1)
es proportional zu istcov(x1)
). Offensichtlichcov(x0)
verlieren Sie das, indem Sie verwenden.Dies wird ausführlich in dem Artikel erklärt, auf den ich in meiner ursprünglichen Antwort verwiesen habe.
quelle
Matteo Fasiolo
und (nehme ich an)whuber
in diesem Thread verifiziert . Dein ist anders. Ich wäre daran interessiert zu verstehen, was Sie berechnen, aber es unterscheidet sich deutlich von der Mahalanobis-Distanz, wie sie normalerweise definiert wird.cov(x0)