Ich versuche, wenige (5-500) Eigenvektoren zu berechnen, die den kleinsten Eigenwerten großer symmetrischer quadratischer Sparse-Matrizen (bis zu 30000 x 30000) entsprechen, wobei weniger als 0,1% der Werte ungleich Null sind.
Ich verwende derzeit scipy.sparse.linalg.eigsh im Shift-Invert-Modus (Sigma = 0.0), was ich durch verschiedene Beiträge zum Thema herausgefunden habe. Dies ist die bevorzugte Lösung. In den meisten Fällen dauert es jedoch bis zu 1 Stunde, um das Problem zu lösen. Andererseits ist die Funktion sehr schnell, wenn ich nach den größten Eigenwerten (Subsekunden auf meinem System) frage, die aus der Dokumentation erwartet wurden.
Da ich mit Matlab von der Arbeit aus besser vertraut bin, habe ich versucht, das Problem in Octave zu lösen, was mir das gleiche Ergebnis mit Eigs (Sigma = 0) in nur wenigen Sekunden (unter 10 Sekunden) brachte. Da ich einen Parameter-Sweep des Algorithmus einschließlich der Eigenvektorberechnung durchführen möchte, wäre diese Art von Zeitgewinn auch in Python großartig.
Ich habe zuerst die Parameter (insbesondere die Toleranz) geändert, aber das hat sich auf der Zeitskala nicht viel geändert.
Ich verwende Anaconda unter Windows, habe aber versucht, das von scipy verwendete LAPACK / BLAS (was ein großer Schmerz war) von mkl (Standard-Anaconda) auf OpenBlas (laut Dokumentation von Octave verwendet) umzustellen, konnte jedoch keine Änderung in feststellen Performance.
Ich konnte nicht herausfinden, ob (und wie) etwas an dem verwendeten ARPACK zu ändern war.
Ich habe einen Testfall für den folgenden Code in den folgenden Dropbox-Ordner hochgeladen: https://www.dropbox.com/sh/l6aa6izufzyzqr3/AABqij95hZOvRpnnjRaETQmka?dl=0
In 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)
In der Oktave:
M=dlmread('M.txt');
M=spconvert(M);
[evecs,evals] = eigs(M,6,0);
Jede Hilfe wird geschätzt!
Einige zusätzliche Optionen, die ich aufgrund der Kommentare und Vorschläge ausprobiert habe:
Oktave:
eigs(M,6,0)
und eigs(M,6,'sm')
gib mir das gleiche Ergebnis:
[1.8725e-05 1.0189e-05 7.5622e-06 7.5420e-07 -1.2239e-18 -2.5674e-16]
während eigs(M,6,'sa',struct('tol',2))
konvergiert zu
[1.0423 2.7604 6.1548 11.1310 18.0207 25.3933]
viel schneller, aber nur, wenn die Toleranzwerte über 2 liegen, sonst konvergiert es überhaupt nicht und die Werte sind stark unterschiedlich.
Python:
eigsh(M,k=6,which='SA')
und eigsh(M,k=6,which='SM')
beide konvergieren nicht (ARPACK-Fehler, wenn keine Konvergenz erreicht wurde). Nur eigsh(M,k=6,sigma=0.0)
gibt einige Eigenwerte (nach fast einer Stunde), die für die Kleinsten Oktave verschieden ist (sogar 1 zusätzlicher kleiner Wert gefunden wird ):
[3.82923317e-17 3.32269886e-16 2.78039665e-10 7.54202273e-07 7.56251500e-06 1.01893934e-05]
Wenn die Toleranz hoch genug ist, erhalte ich auch Ergebnisse eigsh(M,k=6,which='SA',tol='1')
, die den anderen erhaltenen Werten nahe kommen
[4.28732218e-14 7.54194948e-07 7.56220703e-06 1.01889544e-05, 1.87247350e-05 2.02652719e-05]
wieder mit einer anderen Anzahl kleiner Eigenwerte. Die Rechenzeit beträgt noch fast 30min. Während die verschiedenen sehr kleinen Werte verständlich sein mögen, da sie ein Vielfaches von 0 darstellen könnten, verwirrt mich die unterschiedliche Vielfalt.
Außerdem scheint es bei SciPy und Octave einige grundlegende Unterschiede zu geben, die ich noch nicht herausfinden kann.