Я пытаюсь вызвать функцию SVD в RCPP.Мне нужно повторно вызывать SVD в моих кодах для больших толстых / тонких матриц.Жаль, что я могу получить эффективность.Я могу вызвать функцию SVD из R базы.Я полагаю, что svd в базе R написан на Fortran / C ++?У меня есть три вопроса:
Поскольку я вызываю svd из базы R, я, вероятно, не получаю ту же скорость, по сравнению с тем, если я пишу коды C ++ в RCPP для SVD, правильно?
Я также рассмотрел fast.svd из пакета corpcor.Имя функции - La.svd.Как я могу импортировать функцию, имя которой имеет "."в RCPP?RCPP не разрешает имена с ".".
Если мне нужно реализовать 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
Есть мысли по причине?спасибо.