web-dev-qa-db-ja.com

Pythonで固有値/ベクトルを見つける最も速い方法は何ですか?

現在、仕事をするnumpyを使用しています。しかし、私は数千の行/列を持つ行列を扱っているので、この図は数万になるまで、この種の計算をより速く実行できるパッケージが存在するのだろうか?

38
yurib
  • **行列がスパースの場合、scipy.sparseのコンストラクターを使用して行列をインスタンス化し、spicy.sparseの類似のeigenvector/eigenvalueメソッドを使用します.linalg。パフォーマンスの観点から、これには2つの利点があります。

    • spicy.sparseコンストラクターから構築されたマトリックスは、スパースに比例して小さくなります。

    • 固有値/固有ベクトル法 スパース行列の場合(eigseigsh)はオプションの引数を受け入れますkこれは、返される固有ベクトル/固有値のペアの数です。ほぼ常に、分散の> 99%を説明するために必要な数は、列の数よりもはるかに少なく、検証することができますex post;言い換えると、すべての固有ベクトル/固有値のペアを計算して返さないようにメソッドに指示することができます-分散を考慮するために必要な(通常)小さなサブセットを超えて、残りが必要になる可能性は低いです。

  • SciPyscipy.linalg、同じ名前のNumPyライブラリの代わりに。これらの2つのライブラリは同じ名前を持ち、同じメソッド名を使用します。しかし、パフォーマンスには違いがあります。この違いは、numpy.linalgが、類似のLAPACKルーチンのless忠実なラッパーであり、移植性と利便性(つまり、NumPy設計目標に準拠するために、NumPyライブラリ全体をFortranコンパイラなしで構築する必要があります) 。一方、linalginSciPyはLAPACKのより完全なラッパーであり、f2pyを使用します

  • ユースケースに適した関数を選択する;言い換えれば、必要以上に機能する関数を使用しないでください。 scipy.linalgには、固有値を計算する関数がいくつかあります。ただし、固有値を計算する関数を慎重に選択することにより、パフォーマンスが向上するはずです。例えば:

    • scipy.linalg.eigboth固有値と固有ベクトルを返します
    • scipy.linalg.eigvalsは、固有値のみを返します。マトリックスの固有値のみが必要な場合は、do使用しないlinalg.eig、使用する代わりにlinalg.eigvals
    • (転置に等しい)実数値の正方対称行列がある場合は、scipy.linalg.eigshを使用します
  • Scipyビルドの最適化SciPyビルド環境の準備は、主にSciPyのsetup.pyスクリプト。おそらくパフォーマンス面で最も重要なオプションは、[〜#〜] atlas [〜#〜]またはAccelerate/vecLibなどの最適化されたLAPACKライ​​ブラリを識別することです。 SciPyがそれらを検出し、それらに対して構築できるように、フレームワーク(OS Xのみ?)現在使用しているリグに応じて、SciPyビルドを最適化してから再インストールすると、パフォーマンスが大幅に向上します。 SciPyコアチームからの追加のメモは here です。

これらの関数は大きな行列で機能しますか?

そう思うべきです。これらは産業用の強度マトリックス分解法であり、類似のFortran[〜#〜] lapack [〜#〜]の薄いラッパーです。 ルーチン。

Linalgライブラリのほとんどのメソッドを使用して、列の数が通常約5〜50で、行の数が通常500,000を超える行列を分解しました。 [〜#〜] svd [〜#〜]eigenvalueメソッドも、この行列の処理に問題はないようです。サイズ。

SciPyライブラリlinalgを使用すると、このライブラリのいくつかのメソッドのいずれかを使用して、1回の呼び出しで固有ベクトルと固有値を計算できます。 eigeigvalsh、およびeigh

>>> import numpy as NP
>>> from scipy import linalg as LA

>>> A = NP.random.randint(0, 10, 25).reshape(5, 5)
>>> A
    array([[9, 5, 4, 3, 7],
           [3, 3, 2, 9, 7],
           [6, 5, 3, 4, 0],
           [7, 3, 5, 5, 5],
           [2, 5, 4, 7, 8]])

>>> e_vals, e_vecs = LA.eig(A)
52
doug

行列がスパースの場合、scipyのスパース固有値関数を使用してみてください。これはより高速です。

http://docs.scipy.org/doc/scipy/reference/sparse.linalg.html

また、pythonバインディングがあり、mpiを使用して並列計算を実行できるSLEPcなどの特殊なパッケージをチェックアウトすることもできます。

http://code.google.com/p/slepc4py/

9
JoshAdel