私が構築しているアプリケーションでは、残差を得るために大きなデータセットに対して線形回帰を実行する必要があります。たとえば、1つのデータセットは100万x 20,000次元以上です。小さなデータセットの場合は、RcppArmadillo
パッケージのfastLm
を使用していました。時間が経つにつれて、それらのデータセットも100万行を超えるようになります。SparseQR for Least Squares
私の解決策は、スパース行列とEigenを使用することでした。 RcppEigenでSparseQRを使用する良い例が見つかりませんでした。何度も読んでいます(例:rcpp-gallery、stackoverflow、rcpp-dev mailinglist、eigen docs、rcpp-gallery、stackoverflowなど)私は次のコードを書いています。
(NB:私の最初のC++プログラム - 素敵な:)してください - 改善するために何かアドバイスは歓迎される)
// [[Rcpp::depends(RcppEigen)]]
#include <RcppEigen.h>
using namespace Rcpp;
using namespace Eigen;
using Eigen::Map;
using Eigen::SparseMatrix;
using Eigen::MappedSparseMatrix;
using Eigen::VectorXd;
using Eigen::SimplicialCholesky;
// [[Rcpp::export]]
List sparseLm_eigen(const SEXP Xr,
const NumericVector yr){
typedef SparseMatrix<double> sp_mat;
typedef MappedSparseMatrix<double> sp_matM;
typedef Map<VectorXd> vecM;
typedef SimplicialCholesky<sp_mat> solver;
const sp_mat Xt(Rcpp::as<sp_matM>(Xr).adjoint());
const VectorXd Xty(Xt * Rcpp::as<vecM>(yr));
const solver Ch(Xt * Xt.adjoint());
if(Ch.info() != Eigen::Success) return "failed";
return List::create(Named("betahat") = Ch.solve(Xty));
}
これがために、たとえば動作します。
library(Matrix)
library(speedglm)
Rcpp::sourceCpp("sparseLm_eigen.cpp")
data("data1")
data1$fat1 <- factor(data1$fat1)
mm <- model.matrix(formula("y ~ fat1 + x1 + x2"), dat = data1)
sp_mm <- as(mm, "dgCMatrix")
y <- data1$y
res1 <- sparseLm_eigen(sp_mm, y)$betahat
res2 <- unname(coefficients(lm.fit(mm, y)))
abs(res1 - res2)
大規模なデータセットでは(これは予想通り)失敗します。私の最初の目的は、SparseQR
をソルバーとして使用することでしたが、その実装方法はわかりません。
私の質問 - RcppEigenで疎行列のQR分解を実装するのに助けてくれる人がいますか?
スパースQRソルバーの使用ここでは詳述されていますhttps://eigen.tuxfamily.org/dox/group__TopicSparseSystems.html – coatless
@コートレス私はEigenのドキュメントを読んできました。正式な数学やプログラミング教育がないので、読んで理解することは非常に難しいです。 Armadilloのドキュメントは本当に好きですが、現在のところ、SuperLUライブラリがない高密度マトリクスでは最も効果的です。 SuperLUのインストールは現在のところ問題にはなりません。 – tstev