哪个是并行化余弦距离的最佳方法?

时间:2016-11-13 21:12:18

标签: r parallel-processing

当我尝试使用大型数据集(~600,000行)计算余弦距离时,我的R会话在超时超时后崩溃

对于小型数据集,我的代码可以运行,这就是一个例子:

library(lsa)
relevant.data <- as.matrix(mtcars)
cosine(t(relevant.data))

我已经阅读了本网站上的一些帖子来并行化余弦函数,但没有运气。

是否存在一种非常有效的方法?

您是否建议使用rccp这样的帖子? Parallel cosine distance using clusterapply in R

如果计算类似相关矩阵的东西是低效的。你有什么建议?

1 个答案:

答案 0 :(得分:2)

Rcpp中对其进行编码可能会给您足够的购买,因此您不需要额外的并行化麻烦。下面的示例(但我不知道它将如何在您的系统上/具有实际大小的问题:长度为1e8的向量(相当于10,000×10,000矩阵)需要763Mb,因此甚至存储问题的结果60 ^ 2倍大(如果我正确计算的话,= 2.75Tb)可能很难......)。

x <- as.matrix(mtcars)
library(lsa)

来自lsa的功能:

cosine(as.matrix(mtcars))

略微剥离R代码:

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版本,略微修改自here

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);
           }")

测试平等:

identical(cosR(x),unname(cosine(x)))
all.equal(cosCpp(x),cosR(x))

library(microbenchmark)
microbenchmark(cosine(x),cosR(x),cosCpp(x))
## Unit: nanoseconds
##       expr    min      lq       mean  median      uq      max neval cld
##  cosine(x) 460046 1181837 2069604.51 1530719 2528021  8757989   100   b
##    cosR(x) 542414 1096448 1915011.12 1331277 2321596 11740233   100   b
##  cosCpp(x)      7   12472   35827.76   17999   30556   644551   100  a 

Rcpp版本约为1331277/17999 =快74倍,并且可能(?)也可以解决内存问题。