вызов R встроенной функции в RCPP, скорость и имя проблемы - PullRequest
0 голосов
/ 23 сентября 2019

Я пытаюсь вызвать функцию SVD в RCPP.Мне нужно повторно вызывать SVD в моих кодах для больших толстых / тонких матриц.Жаль, что я могу получить эффективность.Я могу вызвать функцию SVD из R базы.Я полагаю, что svd в базе R написан на Fortran / C ++?У меня есть три вопроса:

  1. Поскольку я вызываю svd из базы R, я, вероятно, не получаю ту же скорость, по сравнению с тем, если я пишу коды C ++ в RCPP для SVD, правильно?

  2. Я также рассмотрел fast.svd из пакета corpcor.Имя функции - La.svd.Как я могу импортировать функцию, имя которой имеет "."в RCPP?RCPP не разрешает имена с ".".

  3. Если мне нужно реализовать svd в RCPP, есть ли другие способы реализовать это, кроме импорта из пакетов R?

спасибо.

Обновление: я написал функцию, использующую RcppAmadilo для SVD, неоднократно вызывал ее в основной функции и обнаружил, что она работает намного медленнее, чем при использовании встроенной функции SVD.Любая помощь по причине?Спасибо.

#include <RcppArmadillo.h>
//[[Rcpp::depends("RcppArmadillo")]]

using namespace Rcpp;

/*svd function*/

//[[Rcpp::export]]
List dcSVD(const arma::mat X) { 
    arma::mat u, v;
    arma::vec d;
    arma::svd(u, d, v, X, "standard");

    Rcpp::NumericMatrix u1=Rcpp::wrap(u);
    Rcpp::NumericMatrix v1=Rcpp::wrap(v);

    List ret=List::create(u1(_,0),d,v1(_,0));
    return (ret);
   }

/* main function using built-in svd */

List NMFCPP(NumericMatrix f, int loop) {

  //initiate Lagrangian multiplie

  Function svd = Environment("package:base")["svd"];


  NumericMatrix Lambda(f.nrow(),f.ncol());
  NumericMatrix fitted(f.nrow(),f.ncol());
  NumericMatrix res(f.nrow(),f.ncol());
  NumericMatrix fprime(f.nrow(),f.ncol());

 // order 1 singular value decomposition

  int i, j, k;    
  int nv=1;
  int nu=1;

  List modelsvd = svd(f, nv, nu);

  NumericVector d=modelsvd[0];
  NumericVector u=modelsvd[1];
  NumericVector v=modelsvd[2];

  for (i=0;i<f.nrow();i++){
    for (j=0;j<f.ncol();j++){
      fitted(i,j)=d[0]*u[i]*v[j];
      res(i,j)=fitted(i,j)-f(i,j);
    }
  } 


 //iterate over the NMF-OA process

  for (k=0;k<loop;k++){

        for (i=0;i<f.nrow();i++){
          for (j=0;j<f.ncol();j++){
             Lambda(i,j)=Lambda(i,j)-1/sqrt(loop)*res(i,j);
             if(Lambda(i,j)<0) Lambda(i,j)=0;
             fprime(i,j)=f(i,j)+Lambda(i,j);
           }
        } 

        modelsvd = svd(fprime, nv = 1, nu = 1);    

        d=modelsvd[0];
        u=modelsvd[1];
        v=modelsvd[2];

        for (i=0;i<f.nrow();i++){
            for (j=0;j<f.ncol();j++){
                fitted(i,j)=d[0]*u[i]*v[j];
                res(i,j)=fitted(i,j)-f(i,j);
            }
        }
  }

   List results = List::create(modelsvd, fitted, res, Lambda);
   return results;
}


/* main function using RcppAmadillo svd */
// [[Rcpp::export]]
List NMFCPP2(NumericMatrix f, int loop) {

  //initiate Lagrangian multiplie    

  NumericMatrix Lambda(f.nrow(),f.ncol());
  NumericMatrix fitted(f.nrow(),f.ncol());
  NumericMatrix res(f.nrow(),f.ncol());
  NumericMatrix fprime(f.nrow(),f.ncol());

 // order 1 singular value decomposition

  int i, j, k;    
//  int nv=1;
//  int nu=1;

  //List modelsvd = svd(f, nv, nu);

  List modelsvd = dcSVD(as<arma::mat>(f));

  NumericVector d=modelsvd[1];
  NumericVector u=modelsvd[0];
  NumericVector v=modelsvd[2];

  for (i=0;i<f.nrow();i++){
    for (j=0;j<f.ncol();j++){
      fitted(i,j)=d[0]*u[i]*v[j];
      res(i,j)=fitted(i,j)-f(i,j);
    }
  } 


 //iterate over the NMF-OA process

  for (k=0;k<loop;k++){

        for (i=0;i<f.nrow();i++){
          for (j=0;j<f.ncol();j++){
             Lambda(i,j)=Lambda(i,j)-1/sqrt(loop)*res(i,j);
             if(Lambda(i,j)<0) Lambda(i,j)=0;
             fprime(i,j)=f(i,j)+Lambda(i,j);
           }
        } 

        modelsvd = dcSVD(as<arma::mat>(fprime));

        d=modelsvd[1];
        u=modelsvd[0];
        v=modelsvd[2];

        for (i=0;i<f.nrow();i++){
            for (j=0;j<f.ncol();j++){
                fitted(i,j)=d[0]*u[i]*v[j];
                res(i,j)=fitted(i,j)-f(i,j);
            }
        }
  }

   List results = List::create(modelsvd, fitted, res, Lambda);
   return results;
}

Мои коды R:

x=matrix(rnorm(4000,10,1),4,1000)

a=proc.time()
results0=NMFCPP2(x,1000)
proc.time()-a
a=proc.time()
results1=NMFCPP(x,1000)
proc.time()-a

a=proc.time()
results1=NMF(x,10000)
proc.time()-a

Но функция, использующая RcppAmadillo SVD (NMFCPP2), намного медленнее, чем использование встроенного SVD (NMFCPP).

> a=proc.time()
> results0=NMFCPP2(x,1000)
> proc.time()-a
   user  system elapsed 
 11.665   1.187  12.885 
> a=proc.time()
> results1=NMFCPP(x,1000)
> proc.time()-a
   user  system elapsed 
  0.351   0.018   0.370 

Есть мысли по причине?спасибо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...