現在、仕事をするnumpyを使用しています。しかし、私は数千の行/列を持つ行列を扱っており、後でこの数値は数万に達するため、この種の計算をより高速に実行できるパッケージが存在するかどうか疑問に思っていました.
2 に答える
**マトリックスがスパースの場合、scipy.sparseのコンストラクターを使用してマトリックスをインスタンス化し、 spy.sparse.linalgで類似の固有ベクトル/固有値メソッドを使用します。パフォーマンスの観点から、これには 2 つの利点があります。
Spicy.sparse コンストラクターから構築されたマトリックスは、スパース度に比例して小さくなります。
スパース行列 ( eigs、eigsh )の固有値/固有ベクトル メソッドは、オプションの引数kを受け入れます。これは、返される固有ベクトル/固有値のペアの数です。ほとんどの場合、差異の >99% を説明するために必要な数は、事後的に確認できる列の数よりもはるかに少なくなります。つまり、すべての固有ベクトル/固有値のペアを計算して返さないようにメソッドに指示できます。分散を考慮するために必要な (通常は) 小さなサブセットを超えて、残りが必要になる可能性はほとんどありません。
同じ名前のNumPyライブラリの代わりに、SciPyの線形代数ライブラリscipy.linalgを使用します。これら 2 つのライブラリは同じ名前を持ち、同じメソッド名を使用します。それでも性能には差があります。この違いは、numpy.linalgが 類似の LAPACK ルーチンのラッパーであり、移植性と利便性 (つまり、 NumPyライブラリ全体を Fortran を使用せずに構築する必要があるというNumPyの設計目標に準拠するため) のパフォーマンスを犠牲にするため、信頼性の低いラッパーであるという事実によって引き起こされます。コンパイラ)。 一方、SciPyのlinalgは、LAPACK のはるかに完全なラッパーであり、f2py。
ユースケースに適した機能を選択してください。つまり、必要以上の機能を使用しないでください。scipy.linalgには、 固有値を計算する関数がいくつかあります。違いは大きくありませんが、固有値を計算する関数を慎重に選択することで、パフォーマンスが向上するはずです。例えば:
- scipy.linalg.eigは固有値と固有ベクトルの両方を返します
- scipy.linalg.eigvalsは、固有値のみを返します。したがって、行列の固有値のみが必要な場合は、 linalg.eig を使用せず、代わりにlinalg.eigvalsを使用してください。
- 実数値の正方対称行列 (その転置に等しい) がある場合は、scipy.linalg.eigshを使用します
Scipy ビルドを最適化するSciPy ビルド環境の準備は、主に SciPy のsetup.pyスクリプトで行われます。おそらく、パフォーマンスに関して最も重要なオプションは、 ATLASや Accelerate/vecLib フレームワーク (OS X のみ?) などの最適化された LAPACK ライブラリを識別して、SciPy がそれらを検出し、それらに対してビルドできるようにすることです。現在使用しているリグによっては、SciPy ビルドを最適化してから再インストールすると、パフォーマンスが大幅に向上する可能性があります。SciPy コア チームからの追加メモはこちら.
これらの関数は大きな行列で機能しますか?
そう思うはずです。これらは、産業用強度の行列分解方法であり、類似の Fortran LAPACKルーチンに対するシン ラッパーにすぎません。
linalg ライブラリのほとんどのメソッドを使用して、列数が通常約 5 ~ 50 で、行数が通常 500,000 を超える行列を分解しました。SVD法も固有値法も、このサイズの行列の処理に問題があるようには見えません。
SciPyライブラリlinalgを使用すると、このライブラリのいくつかのメソッドeig、eigvalsh、およびeighのいずれかを使用して、1 回の呼び出しで固有ベクトルと固有値を計算できます。
>>> 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)
行列がスパースの場合は、scipy のスパース固有値関数を使用してみると、より高速になるはずです。
http://docs.scipy.org/doc/scipy/reference/sparse.linalg.html
SLEPc のような特殊なパッケージをチェックすることもできます。これには Python バインディングがあり、mpi を使用して並列計算を行うことができます。