Самый быстрый способ вычислить k наибольших собственных значений и соответствующих собственных векторов с numpy
Я имею большую плотную симметричную матрицу NxN и хочу, чтобы собственные векторы соответствовали k наибольшим собственным значениям. Какой лучший способ их найти (желательно, используя numpy, но, возможно, вообще используя blas/atlas/lapack, если это единственный способ пойти)? В общем случае N намного больше, чем k (например, N > 5000, k < 10).
У Numpy есть только функции для нахождения k наибольших собственных значений, если моя стартовая матрица разрежена.
Ответы
Ответ 1
В SciPy вы можете использовать функцию linalg.eigh с параметром eigvals
.
eigvals: tuple (lo, hi) Индексы наименьшего и наибольшего (в по возрастанию) собственные значения и соответствующие собственные векторы return: 0 <= lo < hi <= M-1. Если опустить, все собственные значения и возвращаются собственные векторы.
Что в вашем случае должно быть установлено (N-k,N-1)
.
Ответ 2
На самом деле разреженные подпрограммы работают и для плотных массивов numpy, я думаю, они используют некоторые
типа итерации подпространства Крылова, поэтому им нужно вычислить несколько матричных векторов
продуктов, что означает, что если ваш k < N, разреженные процедуры могут быть (незначительно?)
быстрее.
Проверьте документы
http://docs.scipy.org/doc/scipy/reference/tutorial/arpack.html
и следующий код (пойдите, чтобы взять хороший кофе с друзьями до его окончания)
import numpy as np
from time import clock
from scipy.linalg import eigh as largest_eigh
from scipy.sparse.linalg.eigen.arpack import eigsh as largest_eigsh
np.set_printoptions(suppress=True)
np.random.seed(0)
N=5000
k=10
X = np.random.random((N,N)) - 0.5
X = np.dot(X, X.T) #create a symmetric matrix
# Benchmark the dense routine
start = clock()
evals_large, evecs_large = largest_eigh(X, eigvals=(N-k,N-1))
elapsed = (clock() - start)
print "eigh elapsed time: ", elapsed
# Benchmark the sparse routine
start = clock()
evals_large_sparse, evecs_large_sparse = largest_eigsh(X, k, which='LM')
elapsed = (clock() - start)
print "eigsh elapsed time: ", elapsed