ソリューションはRcpp ギャラリーでオンラインになりました
RcppArmadillo の mvtnorm パッケージから dmvnorm を再実装しました。アルマジロはなんとなく好きですが、普通のRcppでも動くのではないでしょうか。dmvnorm からのアプローチはマハラノビス距離に基づいているため、そのための関数と多変量正規密度関数があります。
私のコードをお見せしましょう:
#include <RcppArmadillo.h>
#include <Rcpp.h>
// [[Rcpp::depends("RcppArmadillo")]]
// [[Rcpp::export]]
arma::vec mahalanobis_arma( arma::mat x , arma::mat mu, arma::mat sigma ){
int n = x.n_rows;
arma::vec md(n);
for (int i=0; i<n; i++){
arma::mat x_i = x.row(i) - mu;
arma::mat Y = arma::solve( sigma, arma::trans(x_i) );
md(i) = arma::as_scalar(x_i * Y);
}
return md;
}
// [[Rcpp::export]]
arma::vec dmvnorm ( arma::mat x, arma::mat mean, arma::mat sigma, bool log){
arma::vec distval = mahalanobis_arma(x, mean, sigma);
double logdet = sum(arma::log(arma::eig_sym(sigma)));
double log2pi = 1.8378770664093454835606594728112352797227949472755668;
arma::vec logretval = -( (x.n_cols * log2pi + logdet + distval)/2 ) ;
if(log){
return(logretval);
}else {
return(exp(logretval));
}
}
だから、私の大きな失望ではありません:
いくつかのデータをシミュレートする
sigma <- matrix(c(4,2,2,3), ncol=2)
x <- rmvnorm(n=5000000, mean=c(1,2), sigma=sigma, method="chol")
とベンチマーク
system.time(mvtnorm::dmvnorm(x,t(1:2),.2+diag(2),F))
user system elapsed
0.05 0.02 0.06
system.time(dmvnorm(x,t(1:2),.2+diag(2),F))
user system elapsed
0.12 0.02 0.14
いいえ!!!!!!:-(
[編集]
質問は次のとおりです。1) RcppArmadillo の実装がプレーンな R の実装よりも遅いのはなぜですか? 2) R 実装に勝る Rcpp/RcppArmadillo 実装を作成するにはどうすればよいですか?
[編集2]
mahalanobis_arma を mvtnorm::dmvnorm 関数に入れましたが、速度も低下します。