Я пытаюсь реализовать первую производную от многомерного нормального распределения в R на основе rcpp
реализации многомерного нормального распределения, размещенного here и here.первая производная от многомерного нормального/гауссова с rcpp и RcppArmadillo
Вот быстрое внедрение R
mvnormDeriv = function(..., mu=rep(0,length(list(...))), sigma=diag(length(list(...)))) {
if(sd(laply(list(...),length))!=0)
stop("The vectors not same length.")
fn = function(x) -1 * c((1/sqrt(det(2*pi*sigma))) * exp(-0.5*t(x-mu)%*%solve(sigma)%*%(x-mu))) * solve(sigma,(x-mu))
out = t(apply(cbind(...),1,fn))
colnames(out) = c('x', 'y')
return(out[,1])
}
и некоторые тестовые данные с эталоном:
set.seed(123456789)
sigma = rWishart(1, 2, diag(2))
means = rnorm(2)
X = rmvnorm(10000, means, sigma[,,1])
x1 = X[,1]
x2 = X[,2]
benchmark(mvnormDeriv(x1,x2,mu=means,sigma=sigma),
order="relative", replications=5)[,1:4]
Формулу можно найти в матрице поваренной книге (2012), формула 346.
Я не смог изменить реализацию rcpp
многомерного нормали с here. Вот какой код, который я использовал, чтобы попробовать
// [[Rcpp::export]]
arma::vec dmvnormDeriv_arma(arma::mat x, SEXP mu_sexp, arma::mat sigma, bool log = false) {
// create Rcpp vector and matrix from SEXP arguments
Rcpp::NumericVector mu_rcpp(mu_sexp);
// create views for arma objects(reuses memory and avoids extra copy)
arma::vec mu_vec(mu_rcpp.begin(), mu_rcpp.size(), false);
arma::rowvec mu(mu_rcpp.begin(), mu_rcpp.size(), false);
// return(mu_vec);
arma::vec distval = Mahalanobis(x, mu, sigma);
double logdet = sum(arma::log(arma::eig_sym(sigma)));
double log2pi = std::log(2.0 * M_PI);
arma::vec val = exp(-((x.n_cols * log2pi + logdet + distval)/2));
// x.each_row() -= mu;
// arma::vec val2 = solve(sigma, x.row(1));
// arma::vec retval = -1 * val(1) * solve(sigma, x.row(1)-mu_vec);
return(val);
}
Это не полный, конечно. Любые идеи, как я могу реализовать часть * solve(sigma,(x-mu))
в rcpp
или с Armadillo
? У меня проблемы с обработкой разных типов переменных и выполнение решения для каждой строки x.
Разве это не 'решить()' просто (возможно Matlab-) сокращение для 'инв()'? В этом случае вы можете взять это прямо из документов Armadillo. [И мы собираемся обновить сообщение галереи, на которое вы ссылались; следите за этим. И затем отправьте один с этим :)] –
Спасибо, я добавил решение ниже. Я отправлю что-то для галереи, если это интересно. Дайте мне знать, если у вас есть предложения по улучшению. – user2503795
Немного OT, но вы упомянули, используя Cookbook Matrix с 2012 года, можете ли вы предоставить ссылку в вопросе? Это довольно сложно найти. По теме, это может иметь значение для того, чтобы сделать вопрос немного более самодостаточным. Спасибо! – Jotaf