15

我找不到任何函数或包来计算 R 中bigmatrix(from library(bigmemory)) 的零空间或 (QR 分解)。例如:

library(bigmemory)

a <- big.matrix(1000000, 1000, type='double', init=0)

我尝试了以下但得到了显示的错误。如何找到bigmemory对象的零空间?

a.qr <- Matrix::qr(a)
# Error in as.vector(data) : 
#   no method for coercing this S4 class to a vector
q.null <- MASS::Null(a)
# Error in as.vector(data) : 
#   no method for coercing this S4 class to a vector
4

2 回答 2

10

如果要计算矩阵的完整 SVD,可以使用包bigstatsr按块执行计算。AFBM代表 Filebacked Big Matrix,是一个类似于package bigmemorybig.matrix的 filebacked对象的对象。

library(bigstatsr)
options(bigstatsr.block.sizeGB = 0.5)

# Initialize FBM with random numbers
a <- FBM(1e6, 1e3)
big_apply(a, a.FUN = function(X, ind) {
  X[, ind] <- rnorm(nrow(X) * length(ind))
  NULL
}, a.combine = 'c')

# Compute t(a) * a
K <- big_crossprodSelf(a, big_scale(center = FALSE, scale = FALSE))

# Get v and d where a = u * d * t(v) the SVD of a
eig <- eigen(K[])
v <- eig$vectors
d <- sqrt(eig$values)

# Get u if you need it. It will be of the same size of u
# so that I store it as a FBM.
u <- FBM(nrow(a), ncol(a))
big_apply(u, a.FUN = function(X, ind, a, v, d) {
  X[ind, ] <- sweep(a[ind, ] %*% v, 2, d, "/")
  NULL
}, a.combine = 'c', block.size = 50e3, ind = rows_along(u),
a = a, v = v, d = d)

# Verification
ind <- sample(nrow(a), 1000)
all.equal(a[ind, ], tcrossprod(sweep(u[ind, ], 2, d, "*"), v))

这在我的电脑上大约需要 10 分钟。

于 2017-09-23T14:17:50.390 回答
2

@Mahon @user20650 @F.Privė 为了清楚起见,我联系了 bigmemory 团队并询问

本质上,是否存在适用于大内存矩阵的 QR 函数(QR 分解)的实现?

我觉得弄清楚最初提出的问题很有用。@F.Privė - 很好的答案。希望您的回答和他们的回答将有助于将来指导人们。他们的回应如下:

感谢您的注意。目前没有 qr 分解的实现。理想情况下,您可以使用 Householder 反射(如果矩阵密集)或 Givens 旋转(如果矩阵稀疏)来实现这一点。

irlba 包bigmemory 兼容。它提供了截断的奇异值分解。因此,如果您的矩阵相对稀疏,您可以在矩阵的秩处截断。这可能是您最好的选择。如果您不知道排名,那么您可以使用该包迭代更新截断。

请注意,如果您的矩阵是(又高又瘦或又矮又胖),那么 SO 解决方案是可以的。然而,任何时候你求助于计算叉积,你都会失去一些数值稳定性。如果您打算反转矩阵,这可能是一个问题。

于 2017-09-21T15:41:47.310 回答