Ich arbeite an der Implementierung einer Wahrscheinlichkeitsdichtefunktion eines multivariaten Gaußschen in C ++, und ich bin fest, wie die Fälle am besten zu behandeln, wo Dimension & gt; 2.
Das PDF eines Gaussian kann als
geschrieben werden
wobei (A) 'oder A' die Transponierte der 'Matrix' darstellt, die durch Subtrahieren des Mittelwerts von allen Elementen von x erzeugt wird. In dieser Gleichung ist k die Anzahl der Dimensionen, die wir haben, und Sigma repräsentiert die Kovarianzmatrix, die eine k x k -Matrix ist. Schließlich | X | bedeutet die Determinante der Matrix X.
Im univariaten Fall ist die Implementierung der PDF-Datei trivial. Selbst im bivariaten (k = 2) Fall ist es trivial. Wenn wir jedoch über zwei Dimensionen hinausgehen, ist die Implementierung viel schwieriger.
Im bivariaten Fall hätten wir
wobei rho die Korrelation zwischen x und y ist, wobei die Korrelation gleich
ist
In diesem Fall könnte ich Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>
verwenden, um die erste Gleichung zu implementieren, oder einfach alles selbst mit der zweiten Gleichung berechnen, ohne von der vereinfachten linearen Algebra-Schnittstelle von Eigen zu profitieren.
Meine Gedanken für einen Versuch im multivariaten Fall würden wahrscheinlich damit beginnen, die obigen Gleichungen auf den multivariaten Fall zu erweitern.
mit
Meine Fragen sind:
boost::multi_array
für die
n-dimensionale Array, oder sollte ich stattdessen versuchen, Eigen zu nutzen? Ich bin hier ein wenig außerhalb meines Elements, aber einige Gedanken:
Erstens, aus einer Programmiersicht ist die Bestandsantwort "Profil". Das heißt, kodieren Sie zuerst den klareren Weg. Dann profiliere deine Ausführung, um zu sehen, ob sich die Optimierung lohnt. IMHO ist es wahrscheinlich klarer, eine Matrixbibliothek zu verwenden, um näher an der ursprünglichen Mathematik zu bleiben.
Aus einer mathematischen Sicht: Ich bin ein wenig zweifelhaft in Bezug auf die Formel, die Sie für den multivariaten Fall bereitstellen. Es sieht nicht richtig für mich aus. Der Ausdruck Z sollte eine quadratische Form sein und Ihr Z nicht. Es sei denn, ich verpasse etwas.
Hier ist eine Option, die Sie nicht erwähnt haben, aber könnte sinnvoll sein. Vor allem, wenn Sie das PDF mehrere Male für eine einzelne Distribution auswerten. Beginnen Sie mit der Berechnung der Hauptkomponentenbasis Ihrer Distribution. Das heißt, eine Eigenbasis für Σ. Die Richtungen der Hauptkomponenten sind orthogonal. In der Hauptkomponentenbasis sind die Kreuzkovarianzen alle 0, daher hat das PDF eine einfache Form. Wenn Sie eine Bewertung vornehmen möchten, ändern Sie die Basis der Eingabe in die Hauptkomponentenbasis und führen Sie dann die einfachere PDF-Berechnung dafür durch.
Der Gedanke ist, dass Sie die Änderung der Basismatrix und der Hauptkomponenten einmal im Voraus berechnen können und dann nur eine einzige Matrixmultiplikation (die Änderung der Basis) pro Auswertung durchführen müssen, anstatt der zwei Matrixmultiplikationen, die zur Auswertung benötigt werden die (x-μ)' Σ (x-μ)
in der Standardbasis.
Ich habe im Grunde genommen den exp
-Teil der Gleichung für den dreidimensionalen Fall in diese Frage . Ich habe zuerst eine Computer-Vision-Bibliothek namens OpenCV verwendet. Aber ich bemerkte, dass die C ++ - Schnittstelle sehr langsam war. Danach habe ich die C-Schnittstelle ausprobiert, die etwas schneller war. Schließlich entschied ich mich, Flexibilität und Lesbarkeit zu ignorieren, also implementierte ich es ohne Bibliotheken und es war viel schneller.
Was ich sagen möchte, ist Folgendes: Wenn die Leistung wichtig ist, sollten Sie in Erwägung ziehen, spezielle Fälle für die meistverwendete Anzahl von Dimensionen mit möglichst wenig Overhead zu implementieren. Andernfalls wählen Sie Wartbarkeit über die Geschwindigkeit.
Disclaimer: Ich weiß nichts über die Geschwindigkeit von Eigen
oder boost::multi_array
(worauf zielt diese Frage wahrscheinlich wirklich?).
Tags und Links c++ boost eigen statistics