我正在尝试计算几个 (5-500) 特征向量,这些特征向量对应于大型对称方形稀疏矩阵(高达 30000x30000)的最小特征值,其中非零值小于 0.1%。
我目前在 shift-invert 模式 (sigma=0.0) 下使用 scipy.sparse.linalg.eigsh,我通过有关该主题的各种帖子发现这是首选解决方案。但是,在大多数情况下,解决问题最多需要 1 小时。另一方面,如果我要求最大的特征值(在我的系统上为亚秒),则该函数非常快,这是文档中预期的。
由于我在工作中更熟悉 Matlab,所以我尝试在 Octave 中解决这个问题,使用 eigs (sigma=0) 在短短几秒钟内(低于 10 秒)给了我相同的结果。由于我想对包括特征向量计算在内的算法进行参数扫描,因此在 python 中也能获得这种时间增益。
我首先更改了参数(尤其是容差),但在时间尺度上并没有太大变化。
我在 Windows 上使用 Anaconda,但试图将 scipy 使用的 LAPACK/BLAS(这是一个巨大的痛苦)从 mkl(默认 Anaconda)切换到 OpenBlas(根据文档由 Octave 使用),但看不到变化表现。
我无法弄清楚,使用的 ARPACK 是否有改变(以及如何改变)?
我将以下代码的测试用例上传到以下 dropbox 文件夹:
https://www.dropbox.com/sh/l6aa6izufzyzqr3/AABqij95hZOvRpnnjRaETQmka?dl=0
在 Python 中
import numpy as np
from scipy.sparse import csr_matrix, csc_matrix, linalg, load_npz
M = load_npz('M.npz')
evals, evecs = linalg.eigsh(M,k=6,sigma=0.0)
在 Octave :
M=dlmread('M.txt');
M=spconvert(M);
[evecs,evals] = eigs(M,6,0);
任何帮助是appriciated !
我根据评论和建议尝试了一些其他选项:
Octave :
eigs(M,6,0)
和 eigs(M,6,'sm')
给我同样的结果:[1.8725e-05 1.0189e-05 7.5622e-06 7.5420e-07 -1.2239e-18 -2.5674e-16]
而
eigs(M,6,'sa',struct('tol',2))
收敛到[1.0423 2.7604 6.1548 11.1310 18.0207 25.3933]
快得多,但前提是容差值大于 2,否则它根本不会收敛并且值相差很大。
Python:
eigsh(M,k=6,which='SA')
和 eigsh(M,k=6,which='SM')
两者都不收敛(未达到收敛的 ARPACK 错误)。只有 eigsh(M,k=6,sigma=0.0)
给出一些特征值(大约一个小时后),对于最小的特征值与 Octave 不同(甚至发现了 1 个额外的小值):[3.82923317e-17 3.32269886e-16 2.78039665e-10 7.54202273e-07 7.56251500e-06 1.01893934e-05]
如果容差足够高,我也可以从
eigsh(M,k=6,which='SA',tol='1')
得到结果。 , 接近其他获得的值[4.28732218e-14 7.54194948e-07 7.56220703e-06 1.01889544e-05, 1.87247350e-05 2.02652719e-05]
再次使用不同数量的小特征值。计算时间仍然接近30分钟。
虽然不同的非常小的值可能是可以理解的,因为它们可能代表 0 的倍数,不同的多重性让我感到困惑。
此外,SciPy 和 Octave 似乎存在一些根本差异,但我还无法弄清楚。
最佳答案
我知道这现在已经过时了,但我遇到了同样的问题。您是否在这里评论 ( https://docs.scipy.org/doc/scipy/reference/tutorial/arpack.html )?
似乎当您将 sigma 设置为低数 (0) 时,您应该设置 which='LM',即使您想要低值。这是因为设置 sigma 会将您想要的值(在这种情况下为低)转换为高,因此您仍然可以利用“LM”方法,这些方法可以更快地获得所需的值(低特征值) )。
关于python - 寻找大稀疏矩阵的最小特征向量,在 SciPy 中比在 Octave 中慢 100 倍以上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59416098/