celestialgod

RcppParallel LOOCV

Nov 1st, 2015
326
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
R 3.27 KB | None | 0 0
  1. library(Rcpp)
  2. library(RcppArmadillo)
  3. library(RcppParallel)
  4.  
  5. sourceCpp(code = '
  6. // [[Rcpp::plugins(cpp11)]]
  7. // [[Rcpp::depends(RcppArmadillo, RcppParallel)]]
  8. #include <RcppArmadillo.h>
  9. #include <RcppParallel.h>
  10. using namespace RcppParallel;
  11. using namespace arma;
  12. using namespace Rcpp;
  13.  
  14. double fastMSE_RcppArma(vec y, mat X, vec yTest, mat XTest)
  15. {
  16.  vec coef = solve(join_rows(ones<vec>(y.n_elem), X), y);
  17.  return as_scalar(pow(yTest - join_rows(ones<vec>(yTest.n_elem), XTest)*coef, 2));
  18. }
  19.  
  20. struct MSE_Compute: public Worker {
  21.  mat& X;
  22.  vec& y;
  23.  uvec& index;
  24.  vec& mse;
  25.  MSE_Compute(mat& X, vec& y, uvec& index, vec& mse):
  26.    X(X), y(y), index(index), mse(mse) {}
  27.  void operator()(std::size_t begin, std::size_t end)
  28.  {
  29.    for (uword row_index = begin; row_index < end; row_index++)
  30.    {
  31.      mse(row_index) = fastMSE_RcppArma(y.elem(find(index != row_index)),
  32.        X.rows(find(index != row_index)), y.elem(find(index == row_index)),
  33.        X.rows(find(index == row_index)));
  34.    }
  35.  }
  36. };
  37.  
  38. // [[Rcpp::export]]
  39. NumericVector fastLOOCV(NumericVector yr, NumericMatrix Xr)
  40. {
  41.  int n = Xr.nrow(), p = Xr.ncol();
  42.  mat X(Xr.begin(), n, p, false);
  43.  if (yr.size() != n)
  44.    Rcpp::stop("The size of y must be equal to the number of rows of X." );
  45.  vec y(yr.begin(), n, false),
  46.  mse = zeros<vec>(n);
  47.  uvec index = linspace<uvec>(0, y.n_elem - 1, y.n_elem);
  48.  MSE_Compute mseResults(X, y, index, mse);
  49.  parallelFor(0, n, mseResults);
  50.  return wrap(mse);
  51. }
  52.  
  53. // [[Rcpp::export]]
  54. NumericVector fastLOOCV_noRP(NumericVector yr, NumericMatrix Xr)
  55. {
  56.  int n = Xr.nrow(), p = Xr.ncol();
  57.  mat X(Xr.begin(), n, p, false);
  58.  if (yr.size() != n)
  59.    Rcpp::stop("The size of y must be equal to the number of rows of X." );
  60.  vec y(yr.begin(), n, false),
  61.  mse = zeros<vec>(n);
  62.  uvec index = linspace<uvec>(0, y.n_elem - 1, y.n_elem);
  63.  for (uword row_index = 0; row_index < y.n_elem; row_index++)
  64.  {
  65.    mse(row_index) = fastMSE_RcppArma(y.elem(find(index != row_index)),
  66.        X.rows(find(index != row_index)), y.elem(find(index == row_index)),
  67.        X.rows(find(index == row_index)));
  68.  }
  69.  return wrap(mse);
  70. }')
  71.  
  72. LOOCV_R <- function(y, X){
  73.   mses <- vector('numeric', length(y))
  74.   for (i in seq_along(y))
  75.   {
  76.     lmCoefs <- coef(lm(y[-i] ~ X[-i, ]))
  77.     mses[i] <- mean((y[i] - c(1, X[i, ]) %*% lmCoefs)**2)
  78.   }
  79.   return(mses)
  80. }
  81.  
  82. set.seed(10)
  83. N <- 2000
  84. p <- N/5
  85. X <- matrix(rnorm(N*p), N)
  86. lm_coef <- replicate(p, rnorm(1, rnorm(1, 2, 3), rgamma(1,10,2)))
  87. addingCol = matrix(sample(p, p, TRUE), p/2, 2)
  88. addingCol = addingCol[addingCol[ ,1] != addingCol[ ,2], ]
  89. for (i in 1:ncol(addingCol))
  90.   X[ , addingCol[i,1]] = X[ , addingCol[i,1]] + X[ , addingCol[i,2]]
  91. y <- 9 + rowSums(sweep(X, 2, lm_coef, '*')) + rnorm(N, 0, 10)
  92.  
  93. st <- proc.time()
  94. mses_R <- LOOCV_R(y, X)
  95. proc.time() - st
  96. #    user  system elapsed
  97. #  372.58   11.23  388.93
  98.  
  99. st <- proc.time()
  100. mses_cpp1 <- fastLOOCV_noRP(y, X)
  101. proc.time() - st
  102. #    user  system elapsed
  103. #  180.85   18.54  101.63
  104. all.equal(mses_R, as.vector(mses_cpp1)) # TRUE
  105.  
  106. st <- proc.time()
  107. mses_cpp2 <- fastLOOCV(y, X)
  108. proc.time() - st
  109. #    user  system elapsed
  110. #  351.96  179.52    73.7
  111. all.equal(mses_R, as.vector(mses_cpp2)) # TRUE
  112.  
  113. # environment: RRO-3.3.1 on my machine with [email protected]
Advertisement
Add Comment
Please, Sign In to add comment