大きな対称正方スパース行列(最大30000x30000)の最小固有値に対応する少数(5-500)の固有ベクトルを計算しようとしています。値の0.1%未満が非ゼロです。
私は現在scipy.sparse.linalg.eigshをシフトインバートモード(sigma = 0.0)で使用しています。これは、トピックに関するさまざまな投稿でわかった解決策です。ただし、ほとんどの場合、問題を解決するのに最大1時間かかります。一方、ドキュメントから予想された最大固有値(私のシステムではサブ秒)を要求すると、関数は非常に高速になります。
私は仕事でMatlabに慣れているので、Octaveで問題を解決しようとしました。これにより、eigs(sigma = 0)を使用して数秒(サブ10秒)で同じ結果が得られました。固有ベクトルの計算を含むアルゴリズムのパラメータースイープを実行したいので、Pythonでもそのような時間の増加が得られるでしょう。
最初にパラメーター(特に許容誤差)を変更しましたが、タイムスケールではあまり変わりませんでした。
私はWindowsでAnacondaを使用していますが、scipyが使用するLAPACK / BLAS(これは非常に苦痛でした)をmkl(デフォルトのAnaconda)からOpenBlas(ドキュメントに従ってOctaveが使用)に切り替えようとしましたが、変更を確認できませんでしたパフォーマンス。
使用したARPACKに変更点があるかどうか(およびその方法)はわかりませんでした。
以下のコードのテストケースを次のドロップボックスフォルダーにアップロードしました:https ://www.dropbox.com/sh/l6aa6izufzyzqr3/AABqij95hZOvRpnnjRaETQmka?dl=0
Pythonで
import numpy as np
from scipy.sparse import csr_matrix, csc_matrix, linalg, load_npz
M = load_npz('M.npz')
evals, evecs = linalg.eigsh(M,k=6,sigma=0.0)
オクターブで:
M=dlmread('M.txt');
M=spconvert(M);
[evecs,evals] = eigs(M,6,0);
どんな助けもappriciated!
コメントと提案に基づいて試したいくつかの追加オプション:
オクターブ:
eigs(M,6,0)
とeigs(M,6,'sm')
私は同じ結果を与えます:
[1.8725e-05 1.0189e-05 7.5622e-06 7.5420e-07 -1.2239e-18 -2.5674e-16]
にeigs(M,6,'sa',struct('tol',2))
収束しながら
[1.0423 2.7604 6.1548 11.1310 18.0207 25.3933]
はるかに高速ですが、許容値が2を超える場合のみ、それ以外の場合はまったく収束せず、値は大きく異なります。
Pythonの:
eigsh(M,k=6,which='SA')
とeigsh(M,k=6,which='SM')
の両方が(無収束のARPACKエラーに達して)収束しません。eigsh(M,k=6,sigma=0.0)
(ほぼ1時間後)いくつかの固有値のみを提供します。これは、最小値のオクターブとは異なります(1つの追加の小さな値でも見つかります)。
[3.82923317e-17 3.32269886e-16 2.78039665e-10 7.54202273e-07 7.56251500e-06 1.01893934e-05]
許容誤差が十分に高い場合、からも結果がeigsh(M,k=6,which='SA',tol='1')
得られます。これは、他の取得された値に近づきます
[4.28732218e-14 7.54194948e-07 7.56220703e-06 1.01889544e-05, 1.87247350e-05 2.02652719e-05]
ここでも、小さな固有値の数が異なります。計算時間はまだほぼ30分です。非常に小さなさまざまな値は理解できるかもしれませんが、それらは0の倍数を表す可能性があるため、異なる多重度は私を困惑させます。
さらに、SciPyとOctaveにはいくつかの根本的な違いがあるようですが、まだわかりません。