如何优化对角矩阵的特征值/向量计算

时间:2020-11-06 23:25:45

标签: python numpy scipy

我正在尝试针对三对角矩阵的特征值/向量优化我的计算。我的代码目前大约需要30秒才能运行,而我需要更快地运行(大约1秒)。我目前正在使用scipy.sparse.linalg.eigsh方法来查找特征值/向量,但我认为应该有其他方法来加快速度。我将在下面发布我的代码,这样可以更轻松地了解我要执行的操作。任何建议都将受到欢迎,如果有任何不清楚的地方,请告诉我。

    H = (dx**-2)*diags([-1, 2, -1], [-1, 0, 1], shape=(N, N))
    H = sp.lil_matrix(H)
    H[0,0]=0.5*H[0,0]
    H[N-1,N-1]=0.5*H[N-1,N-1]
    lam, phi = eigsh(H, 400, which="SM")

1 个答案:

答案 0 :(得分:1)

您不太可能找到将这种计算速度提高30倍的简单方法。从this post的时序中可以看到,即使Google出色地优化的jax库也仅比scipy中基本SVD实现的管理速度少了3倍。由于SVD对于对称矩阵等效于eigsh,因此我们可以期望eigsh的加速率最多大约相同。

因此,即使是Google,也至少以传统方式无法加快计算速度。

但是,对于非常大的稀疏矩阵,有专门的随机算法,可以在适当的情况下以更大的因数加快处理速度。其中之一具有sklearn实现:sklearn.utils.extmath.randomized_svd。 (我相信它是基于here描述的算法,并且在algorithm='randomized'时也可能与sklearn.decomposition.TruncatedSVD相同。)

这是您的示例的略微修改版本,显示了如何使用它:

from scipy.sparse import diags, lil_matrix
from scipy.sparse.linalg import eigsh

from sklearn.utils.extmath import randomized_svd

N = 3200
k = 400
dx = 1.0

H = (dx**-2)*diags([-1, 2, -1], [-1, 0, 1], shape=(N, N))
H = lil_matrix(H)
H[0, 0] = 0.5*H[0, 0]
H[N-1, N-1] = 0.5*H[N-1, N-1]
# lam, phi = eigsh(H, k, which="SM")

U, s, V = randomized_svd(H, k)

在此,s包含奇异值(此处等于特征值),UV包含奇异矢量(此处等同于特征矢量)。从理论上讲,如果H是对称矩阵,则U应该与V.T相同。我发现本例并非如此,这让我有些疑惑...但是我还是继续将其发布,因为实际上这大约需要一秒钟,因此可能是一个解决方案为你。

但是,还有另外一个警告。您正在将which="SM"传递给eigsh,据我了解,这意味着您要索取400个最小的特征值。那真的是你想要的吗?在我所知道的几乎所有应用程序中,您都需要400个最大特征值。如果实际上您确实确实想要400个最小的特征值,那么这将不起作用,因为它依赖于这样一个事实,即使用随机矩阵投影更容易哄骗最大的特征值。

结果是,您将需要对此进行测试,以查看它是否确实提供了可以使用的结果。鉴于您到目前为止对问题的评价,这是一个有趣的解决方案。

相关问题