我试图通过运行RcppEigen来加速我的慢速OLS估计。
我在Rcpp中有以下ols函数但是想在XX矩阵中乘以对角线,就像在下面的常规R情况下一样?
fastolsCpp <- '
const MapMatd X(as<MapMatd>(XX));
const MapVecd y(as<MapVecd>(yy));
const LLT<MatrixXd> llt(AtA(X));
const VectorXd betahat(llt.solve(X.adjoint() * y));
return wrap(betahat);
'
fastols <- cxxfunction(signature(XX = "matrix", yy = "numeric"), fastolsCpp, "RcppEigen",incl)
常规R
ols <- function (y, x) {
xrd<-crossprod(x)
xry<-crossprod(x, y)
diag(xrd)<-1.1*diag(xrd)
solve(xrd,xry)
Tks P
答案 0 :(得分:4)
这很简单:
library(RcppEigen)
library(inline)
set.seed(42)
x <- 1:10
y <- 3+2*x+rnorm(10)
incl <- '
using Eigen::LLT;
using Eigen::Lower;
using Eigen::Map;
using Eigen::MatrixXd;
using Eigen::VectorXd;
using Rcpp::as;
typedef Eigen::Map<Eigen::MatrixXd> MapMatd;
typedef Eigen::Map<Eigen::VectorXd> MapVecd;
inline MatrixXd AtA(const MapMatd& A) {
int n(A.cols());
return MatrixXd(n,n).setZero().selfadjointView<Lower>().rankUpdate(A.adjoint());
}
'
fastolsCpp <- '
const MapMatd X(as<MapMatd>(XX));
const MapVecd y(as<MapVecd>(yy));
MatrixXd A=AtA(X);
const int k=A.rows();
for (int i=0; i<k; i++) {
A(i,i) *= 1.1;
}
const LLT<MatrixXd> llt(A);
const VectorXd betahat(llt.solve(X.adjoint() * y));
return wrap(betahat);
'
fastols <- cxxfunction(signature(XX = "matrix", yy = "numeric"), fastolsCpp, "RcppEigen", incl)
all.equal(fastols(cbind(1,x), y),
c(ols(y, cbind(1,x))))
#[1] TRUE
library(microbenchmark)
microbenchmark(ols(y, cbind(1,x)), fastols(cbind(1,x), y))
# Unit: microseconds
# expr min lq median uq max neval
# ols(y, cbind(1, x)) 137.585 139.1775 140.571 148.2945 359.642 100
# fastols(cbind(1, x), y) 12.533 13.4830 15.904 16.1720 55.743 100