web-dev-qa-db-ja.com

k個の最大固有値と対応する固有ベクトルをnumpyで計算する最速の方法

大きなNxN密対称行列があり、k個の最大固有値に対応する固有ベクトルが必要です。それらを見つけるための最良の方法は何ですか(できればnumpyを使用しますが、それが唯一の方法である場合は一般的にblas/atlas/lapackを使用します)?一般に、Nはkよりはるかに大きい(たとえば、N> 5000、k <10)。

Numpyには、開始行列がスパースである場合にのみ、k個の最大固有値を見つける関数があるようです。

18
Anthony Bak

SciPyでは、eigvalsパラメーターを指定して linalg.eigh 関数を使用できます。

eigvals:タプル(lo、hi)返される最小および最大(昇順)の固有値と対応する固有ベクトルのインデックス:0 <= lo <hi <= M-1。省略した場合、すべての固有値と固有ベクトルが返されます。

あなたの場合、どちらを(N-k,N-1)に設定する必要があります。

15
Andy Hayden

実際、スパースルーチンは密な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
4
Giuliano