gpt4 book ai didi

r - 通过 ARMA_64BIT_WORD 定义的 RcppArmadillo 中的大型矩阵

转载 作者:行者123 更新时间:2023-12-01 06:11:45 49 4
gpt4 key购买 nike

在上一篇博文 Large SpMat object with RcppArmadillo 中,我决定使用 Rcpp 来计算一个大矩阵(~600,000 行 x 11 列)

我已经安装了 RcppRcppArmadillo

> sessionInfo()
R version 3.3.1 (2016-06-21)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: OS X 10.11.6 (El Capitan)

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] stats graphics grDevices utils datasets methods base

other attached packages:
[1] RcppArmadillo_0.7.500.0.0 Rcpp_0.12.7 cluster_2.0.4 skmeans_0.2-8
[5] ggdendro_0.1-20 ggplot2_2.1.0 lsa_0.73.1 SnowballC_0.5.1
[9] data.table_1.9.6 jsonlite_1.1 purrr_0.2.2 stringi_1.1.2
[13] dplyr_0.5.0 plyr_1.8.4

loaded via a namespace (and not attached):
[1] assertthat_0.1 slam_0.1-38 MASS_7.3-45 chron_2.3-47 grid_3.3.1 R6_2.2.0 gtable_0.2.0
[8] DBI_0.5-1 magrittr_1.5 scales_0.4.0 tools_3.3.1 munsell_0.4.3 clue_0.3-51 colorspace_1.2-7
[15] tibble_1.2

使用 mtcars 之类的示例,这很完美:
library(lsa)    
x <- as.matrix(mtcars)
cosine(t(x))

这是来自 cosinelsa 函数:
cosR <- function(x) {
co <- array(0, c(ncol(x), ncol(x)))
## f <- colnames(x)
## dimnames(co) <- list(f, f)
for (i in 2:ncol(x)) {
for (j in 1:(i - 1)) {
co[i,j] <- crossprod(x[,i], x[,j])/
sqrt(crossprod(x[,i]) * crossprod(x[,j]))
}
}
co <- co + t(co)
diag(co) <- 1
return(as.matrix(co))
}
Rcpp 中的等价物是这样的:
library(Rcpp)
library(RcppArmadillo)
cppFunction(depends='RcppArmadillo',
code="NumericMatrix cosCpp(NumericMatrix Xr) {
int n = Xr.nrow(), k = Xr.ncol();
arma::mat X(Xr.begin(), n, k, false); // reuses memory and avoids extra copy
arma::mat Y = arma::trans(X) * X; // matrix product
arma::mat res = Y / (arma::sqrt(arma::diagvec(Y)) * arma::trans(arma::sqrt(arma::diagvec(Y))));
return Rcpp::wrap(res);
}")

您可以检查两个函数是否等效
all.equal(cosCpp(x),cosR(x))
[1] TRUE

但是当我在加载 Rcpp 后用我的数据运行它时,我得到:
x <- as.matrix(my_data)
x <- t(my_data)
y <- cosCpp(x)
error: Mat::init(): requested size is too large
Error in eval(substitute(expr), envir, enclos) :
Mat::init(): requested size is too large

在@Coatless 的建议 + @gvegayon 帖子 + 数小时的阅读后更新 解决方案

我将我的功能修改为:
sourceCpp("/myfolder/my_function.cpp")
my_function.cpp 的内容是
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
using namespace Rcpp;

// [[Rcpp::export]]
arma::sp_mat cosine_rcpp(
const arma::mat & X
) {

int k = X.n_cols;

arma::sp_mat ans(k,k);

for (int i=0;i<k;i++)
for (int j=i;j<k;j++) {
// X(i) x X(j)' / sqrt(sum(X^2) * sum(Y^2))
ans.at(i,j) = arma::norm_dot(X.col(i), X.col(j));

}

return ans;
}

然后我跑
cosine_rcpp(x)

最佳答案

由于 RcppArmadillo 目录中的内容,

  • Rcpp 是一个 /src -only 包。要启用 C++11,请使用 // [[Rcpp::plugins(cpp11)]]
  • ARMA_64BIT_WORD 未定义。要定义它,请在 #define ARMA_64BIT_WORD 1 之前添加 #include <RcppArmadillo.h>

  • 使用 sourceCpp() 的示例实现
    #define ARMA_64BIT_WORD 1
    #include <RcppArmadillo.h>
    // [[Rcpp::depends(RcppArmadillo)]]
    // [[Rcpp::plugins(cpp11)]]

    // [[Rcpp::export]]
    arma::mat cosCpp(const arma::mat& X) {

    arma::mat Y = arma::trans(X) * X; // matrix product
    arma::mat res = Y / (arma::sqrt(arma::diagvec(Y)) * arma::trans(arma::sqrt(arma::diagvec(Y))));

    return res;
    }

    要在 /src/Makevars{.win} 中为包定义它,请使用:
    PKG_CPPFLAGS = -DARMA_64BIT_WORD=1

    关于r - 通过 ARMA_64BIT_WORD 定义的 RcppArmadillo 中的大型矩阵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40592054/

    49 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com