私はC++でEigenライブラリを使用しています。現在、次のように共分散行列を自分で計算しています。
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;
}
}
Eigenライブラリでこれを行うための組み込み/より最適化された方法はありますか?たとえば、データをMatrixXd
に保存すると、各行は観測値であり、各列は特徴ですか?
ありがとう
各行が観測値である場合、ウィキペディアに示されているように、サンプル共分散行列の行列定式化を使用できます( http://en.wikipedia.org/wiki/Sample_mean_and_sample_covariance#Sample_covariance )
。
これは、固有行列の乗算などの観点から書くのはかなり簡単です。パフォーマンスが向上するかどうかは私にはわかりませんが、オプティマイザーは本当に良い仕事をしなければならないのではないかと思います(少なくとも-O2を使用してください)。それを試してプロファイリングする価値があるかもしれません。
Eigen式を使用すると、SIMDとキャッシュに最適化されたアルゴリズムが活用されるため、確かに高速であり、いずれにせよ、記述ははるかに簡単です。
MatrixXd centered = mat.rowwise() - mat.colwise().mean();
MatrixXd cov = (centered.adjoint() * centered) / double(mat.rows() - 1);
さらに、「data」がdouble [21]のtypedefであると仮定すると、Map <>機能を使用して、std :: vectorを固有オブジェクトとして表示できます。
Map<Matrix<double,Dynamic,21,RowMajor> > mat(&(all_data[0][0], all_data.size(), 21);