我有一些大的(对称真实的)稀疏矩阵,我想计算一些最大和最小(按幅度)的特征值。我查看了Armadillo,但它链接到ARPACK库,它是用Fortran编写的。作为Widnows用户,我没有方便的Fortran编译器,因此我决定使用预编译为Windows的ARPACK R包。
我的矩阵以MatrixMarket格式存储,在R中,我按如下方式读取:
library(Matrix)
f <- file("file://./lambda.mtx", "r")
str(m <- readMM(f))
close(f)
# read sparse matrix
矩阵是对称的,只有下半部分实际存储在mtx文件中。我尝试过使用对称矩阵,但我无处可去。所以我写了以下(对我来说很可怕)代码,以形成稀疏矩阵的两半:
str(A <- sparseMatrix(c(m@i, m@j), c(m@j, m@i), index1 = FALSE, x = c(m@x, m@x), giveCsparse = TRUE, use.last.ij = TRUE))
# do not treat it as symmetric, this doubles the memory but avoids
# conversion to a full matrix in eigs() so it is a good deal ...
str(nnzM <- length(m@x))
str(nnzA <- A@p[A@Dim[2] + 1])
if(nnzM * 2 - m@Dim[2] != nnzA) {
stop("failed to form full matrix A")
}
if(A@x[1] != m@x[1]) {
if(A@x[1] == 2 * m@x[1])
warning("failed to form full matrix A: diagonal elements added")
else
warning("failed to form full matrix A: bad diagonal value")
}
# make sure the repeated values of the diagonal were eliminated instead of added (use.last.ij = TRUE)
最后,我使用rARPACK计算特征值:
library(rARPACK)
str(le <- eigs(A, k = 5, which = "LM", opts = list(retvec = FALSE))) # or dsyMatrix
str(se <- eigs(A, k = 5, sigma = 0, opts = list(retvec = FALSE))) # or dsyMatrix
le$values[1]
se$values[se$nconv]
这适用于小矩阵。但是在大型矩阵中,我在bad_alloc
中收到了eigs()
个错误。请注意,我正在运行64位版本的R,并且框中有16 GB的RAM(有问题的稀疏矩阵是174515 x 174515,非零有9363966,mtx(文本格式)刚刚超过300 MB)
在我使用对称稀疏矩阵之前,我有记忆问题。我的猜测是矩阵格式不好,仍然会在某处转换为密集矩阵。否则我不知道怎么会需要这么多的记忆。任何帮助将不胜感激,这是我迄今为止用R写的第一个也是唯一一个。
根据要求,我可以在某处上传矩阵并共享链接。我可以在Matlab中计算同一矩阵的特征值,但这主要是一个手动过程,我必须将矩阵转移到另一台机器(也是16 GB的RAM,但Matlab是32位,所以理论上它有更多限制工作空间),当我在澳大利亚时,机器碰巧在欧洲,所以它需要永远。如果可能的话,我更喜欢在我的本地机器上使用R.
修改
复制问题所需的所有数据和脚本都在https://sourceforge.net/projects/slamfrontend/files/data/eigenvalues/。此外,该进程实际上在它死前会分配大约12 GB的内存。
编辑2
这是脚本的输出。它实际上在计算最小特征值时崩溃,最大特征值快速计算并且没有崩溃:
E:\my-projects\Robotics\MonaschGit\wdir>"C:\Program Files\R\R-3.2.2\bin\x64\R" --no-save -q --slave 0<get_lambda_eigenvalues.R
Formal class 'dsTMatrix' [package "Matrix"] with 7 slots
..@ i : int [1:9363966] 0 1 2 3 4 5 6 1 2 3 ...
..@ j : int [1:9363966] 0 0 0 0 0 0 0 1 1 1 ...
..@ Dim : int [1:2] 174515 174515
..@ Dimnames:List of 2
.. ..$ : NULL
.. ..$ : NULL
..@ x : num [1:9363966] 1.62e+08 -2.49e+01 -2.49e+06 2.19e+07 1.79e+09 ...
..@ uplo : chr "L"
..@ factors : list()
Formal class 'dgCMatrix' [package "Matrix"] with 6 slots
..@ i : int [1:18553417] 0 1 2 3 4 5 6 7 8 9 ...
..@ p : int [1:174516] 0 14362 28724 43086 57448 71810 86172 100534 115525 130516 ...
..@ Dim : int [1:2] 174515 174515
..@ Dimnames:List of 2
.. ..$ : NULL
.. ..$ : NULL
..@ x : num [1:18553417] 1.62e+08 -2.49e+01 -2.49e+06 2.19e+07 1.79e+09 ...
..@ factors : list()
int 9363966
int 18553417
List of 4
$ values : num [1:5] 1.38e+11 1.31e+11 1.30e+11 1.22e+11 1.16e+11
$ vectors: NULL
$ nconv : int 5
$ niter : int 60
Error: std::bad_alloc
Execution halted
这也可能意味着该问题与用于最小特征值的移位和反转模式有关。它是否实际上反转了过程中的矩阵?如果是这样,我可以看出它为什么会耗尽内存,这种矩阵的反转将是完全密集的。