我正在尝试在图像上使用光谱聚类。我首先计算亲和度矩阵,然后尝试获得特征向量。但是,在7056x7056矩阵上,eig()调用时间过长。关于如何改进这个的任何建议?也许我应该使用不同形式的亲和力?
import matplotlib.pyplot as plt
import numpy as np
Img = plt.imread("twoObj.bmp")
Img2 = Img.flatten()
(n,) = Img2.shape
A = np.subtract.outer(Img2, Img2)
V,D = np.linalg.eig(A)
答案 0 :(得分:4)
使用np.linalg.eigh
进行快速简便的优化。 (如果你只想要特征值,可以np.linalg.eigvalsh
。)
因为你有一个对称矩阵(假设你取绝对值),你可以“告诉”numpy以这种方式使用更有效的算法。
import numpy as np
x = np.random.random(1000)
A = np.subtract.outer(x, x)
A = np.abs(A)
w, v = np.linalg.eigh(A)
比较时间,eigh
需要约5.3秒,而eig
需要约23.4秒。
np.linalg.eig
等的性能将在很大程度上取决于numpy链接到哪个库。使用经过大量优化的blas库(例如ATLAS或Intel的MKL)可能会产生非常显着的差异,尤其是在这种情况下。
此外,根据numpy的构建方式,(例如,fortran编译器是否可用)scipy.linalg.eigh
等可能更快。 scipy和numpy也有可能与不同的blas库相关联,尽管这种可能性不大。
答案 1 :(得分:2)
首先,根据您构建矩阵A
的方式。它将是一个反对称(又称偏斜对称)矩阵,它的排名将是(非常可能)2。
也许你应该只采用对应于两个最大特征值的特征向量。然而,特征值可能很复杂。
无论如何,使用svd
(奇异值分解)实际上可能更直接。
请随时详细说明您的目标。
答案 2 :(得分:2)
来自 scipy.sparse 的linalg模块有三个函数,在这种情况下你经常会有所帮助(即使你的矩阵不稀疏)。总而言之,为这些函数提供动力的解决方案技术更适合于使用更大的矩阵进行计算(即,这些函数包含不同的底层fortran例程,其中包括ARPACK,SEEUPD。)
这是查看scipy.sparse中类似函数的另一个原因。如果算法不被强制寻找所有特征向量/特征值(你几乎从不需要,并且当然不需要你的特定用途),那么大量的计算工作就会幸免。 scipy.sparse.linalg中的特征值函数为您提供显式控制。特别是,scipy.sparse.linalg中的eigs函数接受一个参数“k”,它是你想要的特征值/特征值的数量。
答案 3 :(得分:1)