簡體   English   中英

為什么我的Rcpp代碼比glmnet的慢很多?

[英]Why is my Rcpp code is much slower than glmnet's?

我從站點編輯了套索代碼,以將其用於多個lambda值。 我將lassoshooting包用於一個lambda值(此包適用於一個lambda值),並將glmnet用於多個lambda值進行比較。

系數估算值是不同的,這是可以預期的,這是因為進行了標准化並將其縮放回原始比例。 這超出范圍,在這里並不重要。

對於一個參數情況,套索射擊速度提高了1.5倍。

兩種方法都將我的代碼中的所有100個lambda值都用於多個lambda情況。 但是glmnet比我的cpp代碼快7.5倍。 當然,我希望glmnet更快,但是這個數目似乎太多了。 這是正常現象還是我的代碼錯誤?



編輯

我還附加了lshoot函數,該函數計算R循環中的系數路徑。 這也勝過我的cpp代碼。

我可以改善我的cpp代碼嗎?

C ++代碼:

// [[Rcpp::depends(RcppArmadillo)]]

#include <RcppArmadillo.h>
using namespace Rcpp;
using namespace arma;


// [[Rcpp::export]]
vec softmax_cpp(const vec & x, const vec & y) {
  return sign(x) % max(abs(x) - y, zeros(x.n_elem));
}

// [[Rcpp::export]]
mat lasso(const mat & X, const vec & y, const vec & lambda,
           const double tol = 1e-7, const int max_iter = 10000){
  int p = X.n_cols; int lam = lambda.n_elem;
  mat XX = X.t() * X;
  vec Xy = X.t() * y;
  vec Xy2 = 2 * Xy;
  mat XX2 = 2 * XX;
  mat betas = zeros(p, lam); // to store the betas

  vec beta = zeros(p); // initial beta for each lambda

  bool converged = false;
  int iteration = 0;
  vec beta_prev, aj, cj;

  for(int l = 0; l < lam; l++){
    while (!converged && (iteration < max_iter)){

      beta_prev = beta;

      for (int j = 0; j < p; j++){
        aj = XX2(j,j);
        cj = Xy2(j) - dot(XX2.row(j), beta) + beta(j) * XX2(j,j);
        beta(j) = as_scalar(softmax_cpp(cj / aj, as_scalar(lambda(l)) / aj));
      }
      iteration = iteration + 1;
      converged =  norm(beta_prev - beta, 1) < tol;  
    }
    betas.col(l) = beta;
    iteration = 0;
    converged = false;
  }
  return betas;
}

R代碼:

library(Rcpp)
library(rbenchmark)
library(glmnet)
library(lassoshooting)

sourceCpp("LASSO.cpp")

library(ElemStatLearn)
X <- as.matrix(prostate[,-c(9,10)])
y <- as.matrix(prostate[,9])
lambda_one <- 0.1
benchmark(cpp=lasso(X,y,lambda_one),
          lassoshooting=lassoshooting(X,y,lambda_one)$coefficients,
          order="relative", replications=100)[,1:4]

################################################
lambda <- seq(0,10,len=100)

benchmark(cpp=lasso(X,y,lambda),
          glmn=coef(glmnet(X,y,lambda=lambda)),
          order="relative", replications=100)[,1:4]

    ####################################################

編輯

lambda <- seq(0,10,len=100)

lshoot <- function(lambda){
  betas <- matrix(NA,8,100)
  for(l in 1:100){
    betas[, l] <- lassoshooting(X,y,lambda[l])$coefficients
  }
  return(betas)
}

benchmark(cpp=lasso(X,y,lambda),
          lassoshooting_loop=lshoot(lambda),
          order="relative", replications=300)[,1:4]

一種參數情況的結果:

           test replications elapsed relative
2 lassoshooting          300    0.06      1.0
1           cpp          300    0.09      1.5

多參數情況的結果:

  test replications elapsed relative
2 glmn          300    0.70    1.000
1  cpp          300    5.24    7.486

lassoshooting循環和cpp的結果:

                test replications elapsed relative
2 lassoshooting_loop          300    4.06    1.000
1                cpp          300    6.38    1.571

軟件包{glmnet}使用熱啟動和特殊規則來丟棄大量預測變量,這使得非常快地擬合整個“正則化路徑”。

他們的論文

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM