R和Rcpp中的多个多元法线密度值

时间:2018-12-06 12:00:41

标签: r

我有一个关于快速实施的问题。假设您有一个矩阵Ys,其中每行都引用一个源自多元正态分布的观测值向量,例如

    Ys = matrix(c(1.0,1.0,1.0,0.0,0.5,0.6,0.1,0.1,0.3), nrow = 3, ncol = 3) 

此外,还有一个矩阵Sigs,其中每一行都引用Ys中每个结果向量的方差协方差矩阵的对角元素,例如

    Sigs = matrix(c(1.0,0.5,0.1,0.2,0.3,0.4,0.3,0.7,0.8), nrow = 3, ncol = 3) 

我要做的是给定Sigs中相应行的对角线元素,计算Ys中每一行的密度值。

例如,可以在R中使用for循环

    colSigs = ncol(Sigs)
    res = rep(0,3)
    means = rep(0,colSigs)
    for (i in 1:nrow(Ys) ) {
            sigma = diag(Sigs[i,],colSigs)
            res[i] = mvtnorm::dmvnorm(Ys[i,],means,sigma)
    }

但是,在我的情况下,Y和Sig包含大约100,000行。因此,我编写了一个Rcpp函数,它的速度要快得多。但是,我想知道是否有一个花哨的技巧(一种更有效的方法),这样我就不必执行循环了?任何想法都欢迎。

----

编辑:我被要求添加Rcpp函数。在这里,您去了:

此函数计算在多元法线密度中出现的二次形式:

double dmvnorm_distance( arma::rowvec y, arma::mat Sigma )
    {
    int n = Sigma.n_rows;
    double res=0;
    double fac=1;
    for (int ii=0; ii<n; ii++){
        for (int jj=ii; jj<n; jj++){
            if (ii==jj){ fac = 1; } else { fac = 2;}
            res += fac *y(0,ii) * Sigma(ii,jj) * y(0,jj);
        }
    }
    return res;
}

此函数计算密度值:

double dmvnorm_rcpp(arma :: rowvec y,arma :: mat Sigma)     {

    int p = Sigma.n_rows;

    // inverse Sigma
    arma::mat Sigma1 = arma::inv(Sigma);
    // determinant Sigma
    double det_Sigma = arma::det(Sigma);
    // distance
    double dist = dmvnorm_distance( y, Sigma1);

    double pi1 = 3.14159265358979;
    double l1 = - p * std::log(2*pi1) - dist - std::log( det_Sigma );
    double ll = 0.5 * l1;

    return ll;
}

此函数包含for循环,并从R中调用:

Rcpp::NumericVector mvnorm_loop( arma::mat Ys, arma::mat SIGs )
{
    int n = Ys.n_rows;
    Rcpp::NumericVector out(n);

    for (int ii=0; ii<n; ii++){

         // get yi and diagonal entries
         arma::rowvec yi = Ys.row(ii);
         arma::rowvec si = SIGs.row(ii);; 

         // make Sigma
         arma::mat Sigma = arma::diagmat(si);

         // compute likelihood value       
         out[ii] = dmvnorm_rcpp( yi, Sigma );
    }

    return out;
}

因此,基本上的问题是,是否存在另一种方法可以在Rcpp中实现插入,从而使整个过程更快。

----

最好, 斯蒂芬

PS:我也在R中使用了apply,它比Rcpp循环功能慢。

0 个答案:

没有答案