【问题标题】:operating with big.matrix使用 big.matrix 操作
【发布时间】:2017-02-08 11:28:29
【问题描述】:

我必须使用 big.matrix 对象,并且我无法计算某些函数。让我们考虑以下 big.matrix:

# create big.matrix object
x <- as.big.matrix(
      matrix( sample(1:10, 20, replace=TRUE), 5, 4,
           dimnames=list( NULL, c("a", "b", "c", "d")) ) )

> x
An object of class "big.matrix"
Slot "address":
<pointer: 0x00000000141beee0>

对应的矩阵对象为:

# create matrix object

x2<-x[,]

> x2
     a b  c  d
[1,] 6 9  5  3
[2,] 3 6 10  8
[3,] 7 1  2  8
[4,] 7 8  4 10
[5,] 6 3  6  4

如果我用矩阵对象计算这个操作,它可以工作:

sqrt(slam::col_sums(x2*x2))

> sqrt(slam::col_sums(x2*x2))
       a        b        c        d 
13.37909 13.82027 13.45362 15.90597 

虽然如果我使用 big.matrix 对象(实际上是我必须使用的),但它不起作用:

sqrt(biganalytics::colsum(x*x))

问题是2:*操作(创建矩阵每个元素的平方),它会产生错误:

x * x 中的错误:将非数字参数转换为二元运算符

以及产生错误的 sqrt 函数:

sqrt(x) 中的错误:数学函数的非数字参数。

如何使用 big.matrix 对象计算此操作?

【问题讨论】:

    标签: r r-bigmemory bigdata


    【解决方案1】:

    使用 big.matrix 对象,我发现了 2 个提供良好性能的解决方案:

    • 在 Rcpp 中针对您的具体需要编写一个函数。在这里,2 个嵌套的 for 循环就可以了。然而,您无法重新编码所需的一切。
    • big.matrix 的列块上使用 R 函数并聚合结果。这很容易做到,并且只使用 R 代码。

    在您的情况下,列数增加 10,000 倍:

    require(bigmemory)
    
    x <- as.big.matrix(
      matrix( sample(1:10, 20000, replace=TRUE), 5, 40000,
              dimnames=list( NULL, rep(c("a", "b", "c", "d"), 10000) ) ) )
    
    print(system.time(
      true <- sqrt(colSums(x[,]^2))
    ))
    
    print(system.time(
      test1 <- biganalytics::apply(x, 2, function(x) {sqrt(sum(x^2))})
    ))
    print(all.equal(test1, true))
    

    所以,colSums 非常快,但需要 RAM 中的所有矩阵,而 biganalytics::apply 很慢,但内存效率高。一个折衷方案是使用这样的东西:

    CutBySize <- function(m, block.size, nb = ceiling(m / block.size)) {
      int <- m / nb
    
      upper <- round(1:nb * int)
      lower <- c(1, upper[-nb] + 1)
      size <- c(upper[1], diff(upper))
    
      cbind(lower, upper, size)
    }
    
    seq2 <- function(lims) seq(lims["lower"], lims["upper"])
    
    require(foreach)
    big_aggregate <- function(X, FUN, .combine, block.size = 1e3) {
      intervals <- CutBySize(ncol(X), block.size)
    
      foreach(k = 1:nrow(intervals), .combine = .combine) %do% {
        FUN(X[, seq2(intervals[k, ])])
      }
    }
    
    print(system.time(
      test2 <- big_aggregate(x, function(X) sqrt(colSums(X^2)), .combine = 'c')
    ))
    print(all.equal(test2, true))
    

    编辑: 现在在包 bigstatsr 中实现:

    print(system.time(
      test2 <- bigstatsr::big_apply(x, a.FUN = function(X, ind) {
        sqrt(colSums(X[, ind]^2))
      }, a.combine = 'c')
    ))
    print(all.equal(test2, true))
    

    【讨论】:

      【解决方案2】:

      我不知道这是否是最快的方法,请尝试:

      biganalytics::apply(x, 2, function(x) {sqrt(sum(x^2))})
      

      【讨论】:

        猜你喜欢
        • 2012-01-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-06
        • 2014-12-17
        • 2015-01-13
        • 2012-11-27
        相关资源
        最近更新 更多