Проблемы с SVD большой матрицы с использованием bigmemory и irlba - PullRequest
0 голосов
/ 02 мая 2018

Я сейчас пытаюсь реализовать SVD очень большой матрицы, используя bigmemory и irlba. Насколько я понимаю, мне нужно настроить команду mult в пакете irlba, что я и сделал следующим образом:

mult <- function(A, B, transpose=FALSE) {
  if(is.null(dim(B))) B <- cbind(B)
  if(transpose)
    return(cbind((t(B) %*% A)[]))
  cbind((A %*% B)[])
}

Однако, это не работает для запуска SVD на большой матрице с использованием irlba:

irlbaObject <- irlba(big, nv = 10, mult = mult)

Для воспроизводимости вот пример большой матрицы, на которой я хочу сделать SVD:

big <- file("big.txt", open = "a")
replicate(20, {
  x <- matrix(rnorm(100 * 100), nrow = 10)
  write.table(x, file  = 'big.txt', append = TRUE,
              row.names = FALSE, col.names = FALSE)
})

big <- read.big.matrix("big.txt", separated = FALSE,
                        type = "double",
                        backingfile = "big.bk",
                        backingpath = "/tmp",
                        descriptorfile = "big.desc")

Это сообщение об ошибке, которое я получаю:

Error in A %*% B : requires numeric/complex matrix/vector arguments
Called from: cbind((A %*% B)[])

У кого-нибудь есть идеи, как избежать этой ошибки?

1 Ответ

0 голосов
/ 03 мая 2018

Это должно работать:

library(bigalgebra)
library(irlba)

## --> CHANGES HERE <--
setMethod("%*%", signature(x = "big.matrix", y = "numeric"),
          function(x, y) x %*% as.matrix(y))
setMethod("%*%", signature(x = "numeric", y = "big.matrix"),
          function(x, y) t(x) %*% y)
mult <- function(A, B) (A %*% B)[]

# Repdata
x <- matrix(rnorm(20 * 100 * 100), nrow = 20 * 10)
big <- as.big.matrix(x)
# Computation
irlbaObject <- irlba(big, nv = 10, mult = mult)
# Verification
svd <- svd(x, nu = 10, nv = 10)
plot(irlbaObject$u, svd$u)
plot(irlbaObject$v, svd$v)

Примечание 1: Я думаю, что алгоритм в irlba изменился и теперь использует только умножения матрицы на вектор.

Примечание 2: mult является устаревшим аргументом (он исчезнет в следующих версиях).

Примечание 3: Я не уверен, что это решение будет быстрым. Если вам нужен быстрый алгоритм для вычисления частичного SVD, попробуйте функцию big_randomSVD из пакета bigstatsr (заявление об отказе: я автор).

...