работа с большой матрицей

Мне приходится работать с объектами 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?


person Sara V.    schedule 08.02.2017    source источник


Ответы (2)


С big.matrix объектами я нашел 2 решения, обеспечивающих хорошую производительность:

  • запрограммируйте функцию в Rcpp для того, что вам конкретно нужно. Здесь 2 вложенных цикла for сделают свое дело. Но все, что нужно, перекодировать нельзя.
  • используйте функцию R для блоков столбцов вашего big.matrix и объедините результаты. Это легко сделать и использует только код R.

В вашем случае с количеством столбцов в 10000 раз больше:

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 работает очень быстро, но требует наличия всей матрицы в ОЗУ, тогда как 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))
person F. Privé    schedule 09.02.2017

Я не знаю, самый ли это способ сделать это, попробовав:

biganalytics::apply(x, 2, function(x) {sqrt(sum(x^2))})
person dax90    schedule 08.02.2017