2013-02-28 6 views
12

Ich bin mit der Eigen-Bibliothek in C++ zu berechnen: I zur Zeit der Kovarianzmatrix selbst bin Berechnung wie folge:Eigen: Gibt es eine eingebaute Möglichkeit, Probe Kovarianz

Eigen::MatrixXd covariance_matrix = Eigen::MatrixXd::Constant(21, 21, 0); 
data mean = calc_mean(all_data) 
for(int j = 0; j < 21; j++){ 
    for(int k = 0; k < 21; k++){ 
     for(std::vector<data>::iterator it = all_data.begin(); it!= all_data.end(); it++){ 
      covariance_matrix(j,k) += ((*it)[j] - mean[j]) * ((*it)[k] - mean[k]); 
     } 
     covariance_matrix(j,k) /= all_data.size() - 1; 
    } 
} 

Gibt es einen eingebauten/optimierteren Weg zu Mach das mit der Eigenen Bibliothek? Zum Beispiel, wenn ich meine Daten in einem MatrixXd wo jede Zeile ist eine Beobachtung und jede Spalte ein Feature?

Dank

Antwort

6

Wenn jede Zeile eine Beobachtung ist, können Sie die Matrixformulierung für die Probe Kovarianzmatrix verwenden, wie auf wikipedia (http://en.wikipedia.org/wiki/Sample_mean_and_sample_covariance#Sample_covariance)

Sample covariance, source: wikipedia article linked above

gezeigt.

Dies ist ziemlich einfach zu schreiben in Bezug auf Eigen Matrix Multiplikationen usw. Ob es leistungsfähiger wird ist nicht offensichtlich für mich, ich vermute, dass der Optimierer eine wirklich gute Arbeit machen müsste (sicher sein, mindestens zu verwenden -O2). Es kann sich lohnen, es zu versuchen und zu profilieren.

43

Ausdrücke Mit Eigen wird SIMD und Cache-optimierte Algorithmen nutzen, also ja es auf jeden Fall schneller sein sollte, und in jedem Fall viel einfacher zu schreiben:

MatrixXd centered = mat.rowwise() - mat.colwise().mean(); 
MatrixXd cov = (centered.adjoint() * centered)/double(mat.rows() - 1); 

Darüber hinaus „Daten“ unter der Annahme ist ein typedef für ein Doppel [21], dann können Sie die Karte <> verwenden, um Ihr std :: vector als Eigen-Objekt anzuzeigen:

Map<Matrix<double,Dynamic,21,RowMajor> > mat(&(all_data[0][0], all_data.size(), 21); 
+5

Vorsicht für 'mat.rows() == 1 '. –