Python 性能问题、使用亲和矩阵的聚类、特征值

Python 性能问题、使用亲和矩阵的聚类、特征值,python,image-processing,numpy,linear-algebra,Python,Image Processing,Numpy,Linear Algebra,我尝试在图像上使用光谱聚类。我首先计算亲和矩阵,然后尝试得到特征向量。但是,在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, I

我尝试在图像上使用光谱聚类。我首先计算亲和矩阵,然后尝试得到特征向量。但是,在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)

首先,根据您如何构建矩阵
A
。它将是一个反对称(又称斜对称)矩阵,它的秩(很可能)为2

也许你应该只取对应于两个最大特征值的特征向量。然而,特征值很可能是复杂的

无论如何,使用
svd
(奇异值分解)实际上可能会更简单


请随时详细说明您的目标。

一个简单快捷的优化方法是使用
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)
比较计时,
eih
需要约5.3秒,而
eig
需要约23.4秒

np.linalg.eig
等的性能将强烈依赖于numpy链接到的库。使用高度优化的blas库(例如ATLAS或Intel的MKL)可能会产生非常显著的差异,尤其是在这种情况下


此外,取决于numpy的构建方式,(例如,是否有fortran编译器可用)
scipy.linalg.eigh
等可能更快。scipy和numpy也有可能被链接到不同的blas库,尽管这是不太可能的。

scipy.sparse中的linalg模块有三个功能,在这种情况下(即使你的矩阵不是稀疏的),你通常会帮上忙。总之,为这些函数提供动力的解决方案技术更适合使用更大的矩阵进行计算(即,这些函数包含不同的底层fortran例程、ARPACK、SEEUPD等)


下面是查看scipy.sparse中类似函数的另一个原因。如果算法不被迫寻找所有的特征向量/特征值(你几乎从不需要,当然也不需要用于你的特定用途),那么就可以节省大量的计算工作量。scipy.sparse.linalg中的特征值函数为您提供了对此的明确控制。特别是,scipy.sparse.linalg中的eigs函数接受一个参数“k”,它是您想要的特征值/特征值的数量。

根据著名数学家和LAPACK贡献者I.S.Dhillon的a,光谱聚类问题可以转化为所谓的核k-均值问题。这可以将计算量减少1000倍。他们已经在德克萨斯大学网站上实现了一个免费软件的算法。我还没试过,但看起来像真的一样。当然,与大型特征向量计算相比,SYSTEM()调用的开销是微不足道的。

我将开始一个新的问题,询问此方法的机制。