R程序中非常大的矩阵的svd

Posted

技术标签:

【中文标题】R程序中非常大的矩阵的svd【英文标题】:svd of very large matrix in R program 【发布时间】:2013-06-25 12:32:20 【问题描述】:

我在一个 txt 文件中有一个 60 000 x 60 000 的矩阵,我需要得到这个矩阵的 svd。我使用 R,但我不知道 R 是否可以生成它。

【问题讨论】:

欢迎来到***。您可能会受益于在此处查看有关提出好问题的指南:***.com/help/how-to-ask。特别是,请提供一个最小的、可重复的答案,并解释您迄今为止为解决自己的问题所做的尝试。 可能不会。 n <- 60e3; x <- matrix(0, ncol=n, nrow=n) 引发错误。 (在 R-2.15.3 中) @Andrie:在我的机器上:错误:无法分配大小为 13.4 Gb 的向量。所以可能只是有足够的内存的问题。至少在 R 3.x 上,我认为我们可以有长数组。 @asb 这是一个加载的“仅”。如果你需要 13.4Gb 来创建矩阵,我认为你至少需要两倍的空间来做任何有意义的事情。也许三倍。 (假设没有使用 ff 或 bigmemory 之类的基于磁盘的解决方案。) 我认为组合 bigmemory + irlba 是要走的路(或 scidb 但我发现很难在我的 linux 机器上安装它)。 【参考方案1】:

我认为可以使用irlba 包和bigmemorybigalgebra 计算(部分)svd,而无需使用大量内存。

首先让我们创建一个 20000 * 20000 的矩阵并保存到一个文件中

require(bigmemory)
require(bigalgebra)
require(irlba)

con <- file("mat.txt", open = "a")
replicate(20, 
    x <- matrix(rnorm(1000 * 20000), nrow = 1000)
    write.table(x, file  = 'mat.txt', append = TRUE,
            row.names = FALSE, col.names = FALSE)
)

file.info("mat.txt")$size
## [1] 7.264e+09   7.3 Gb
close(con)

然后你可以使用bigmemory::read.big.matrix读取这个矩阵

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

str(bigm)
## Formal class 'big.matrix' [package "bigmemory"] with 1 slots
##   ..@ address:<externalptr>

dim(bigm)
## [1] 20000 20000

bigm[1:3, 1:3]
##            [,1]     [,2]     [,3]
## [1,] -0.3623255 -0.58463 -0.23172
## [2,] -0.0011427  0.62771  0.73589
## [3,] -0.1440494 -0.59673 -1.66319

现在我们可以使用优秀的irlba 包,如包小插图中所述。

第一步包括定义可以与big.matrix对象一起使用的矩阵乘法运算符,然后使用irlba::irlba函数

### vignette("irlba", package = "irlba") # for more info

matmul <- function(A, B, transpose=FALSE) 
    ## Bigalgebra requires matrix/vector arguments
    if(is.null(dim(B))) B <- cbind(B)

    if(transpose)
        return(cbind((t(B) %*% A)[]))

    cbind((A %*% B)[])


dim(bigm)

system.time(
S <- irlba(bigm, nu = 2, nv = 2, matmul = matmul)
)

##    user  system elapsed 
## 169.820   0.923 170.194


str(S)
## List of 5
##  $ d    : num [1:2] 283 283
##  $ u    : num [1:20000, 1:2] -0.00615 -0.00753 -0.00301 -0.00615 0.00734 ...
##  $ v    : num [1:20000, 1:2] 0.020086 0.012503 0.001065 -0.000607 -0.006009 ...
##  $ iter : num 10
##  $ mprod: num 310

我忘记设置种子以使其可复制,但我只是想表明在 R 中可以做到这一点。

编辑

如果您使用的是新版本的包irlba,上述代码会抛出错误,因为函数irlbamatmult 参数已重命名为mult。因此,您应该更改这部分代码

S <- irlba(bigm, nu = 2, nv = 2, matmul = matmul)

S <- irlba(bigm, nu = 2, nv = 2, mult = matmul)

我要感谢 @FrankD 指出这一点。

【讨论】:

+1 用于显示方法,看起来很棒...但是... 60e3*60e3 怎么样?这是数据的 9 倍。我想知道 BigO 在这个问题上是什么?有任何想法吗? :-) @SimonO101 从理论上讲,这应该适用于更大的数据,但只会花费更多时间(现在需要多少时间?)。我会尽快更新它,我们会对 BigO 有所了解 只是说irlba中的matmul参数被重命名为mult,这会导致上面的代码抛出错误。 仅供参考:“此处解释”中的链接 (illposed.net/irlb.html) 不再有效。 @JohnnyStrings 谢谢,我想我们现在可以参考包小插图。我将编辑我的答案。再次感谢【参考方案2】:

在 R 3.x+ 中,您 可以 构造一个该大小的矩阵,向量大小的上限是 2^53(或者可能是 2^53-1 ),从 2^31- 1 和以前一样,这就是安德烈在他过时的安装上抛出错误的原因。每个数字元素通常需要 10 个字节。无论如何:

> 2^53 < 10*60000^2
[1] FALSE  # so you are safe on that account.

它也适合 64GB(但不适合 32GB):

> 64000000000 < 10*60000^2
[1] FALSE

通常,要进行任何严肃的工作,您至少需要 3 倍于最大对象的大小,因此即使使用新的扩展向量/矩阵,这似乎也很接近。

【讨论】:

with R version 3.0.0 (2013-04-03)## Platform: x86_64-w64-mingw32/x64 (64-bit) 我得到 ## Error: cannot allocate vector of size 26.8 Gb 。我需要升级到 3.0.1+ 吗? +1 因为他的 R 安装已经过时了。哈! :-) 我想这可能不是 Andrie 失败的唯一原因。在我使用了 6 年的 Mac 上,它也可能会失败,因为它的 RAM 已达到 32GB。 所以我得到的唯一点是贬低cmets?这有多蹩脚?

以上是关于R程序中非常大的矩阵的svd的主要内容,如果未能解决你的问题,请参考以下文章

R中非常大的稀疏矩阵的列重新缩放

R中非常大的数据集处理和机器学习的推荐包[关闭]

奇异分解(SVD) 案例--用户与商家稀疏矩阵

Powershell 中非常大的 XML 文件

C/C++ 中非常大的静态数组的算术运算

Kivy PyInstaller 在 Linux 中非常大的包大小