J'essaie de calculer quelques (5-500) vecteurs propres correspondant aux plus petites valeurs propres de grandes matrices creuses symétriques carrées (jusqu'à 30000x30000) avec moins de 0,1% des valeurs étant non nulles.
J'utilise actuellement scipy.sparse.linalg.eigsh en mode inversion de décalage (sigma = 0.0), ce que j'ai compris à travers divers articles sur le sujet est la solution préférée. Cependant, il faut jusqu'à 1h pour résoudre le problème dans la plupart des cas. D'un autre côté, la fonction est très rapide, si je demande les valeurs propres les plus élevées (sous-secondes sur mon système), ce qui était attendu de la documentation.
Comme je suis plus familier avec Matlab du travail, j'ai essayé de résoudre le problème dans Octave, ce qui m'a donné le même résultat en utilisant eigs (sigma = 0) en quelques secondes (moins de 10s). Étant donné que je veux faire un balayage des paramètres de l'algorithme, y compris le calcul du vecteur propre, ce type de gain de temps serait également formidable en python.
J'ai d'abord changé les paramètres (en particulier la tolérance), mais cela n'a pas beaucoup changé dans les délais.
J'utilise Anaconda sur Windows, mais j'ai essayé de changer le LAPACK / BLAS utilisé par scipy (ce qui était une énorme douleur) de mkl (Anaconda par défaut) à OpenBlas (utilisé par Octave selon la documentation), mais je n'ai pas pu voir de changement dans performance.
Je n'ai pas pu déterminer s'il y avait quelque chose à changer dans l'ARPACK utilisé (et comment)?
J'ai téléchargé un testcase pour le code ci-dessous dans le dossier déroulant suivant: https://www.dropbox.com/sh/l6aa6izufzyzqr3/AABqij95hZOvRpnnjRaETQmka?dl=0
En 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)
En octave:
M=dlmread('M.txt');
M=spconvert(M);
[evecs,evals] = eigs(M,6,0);
Toute aide est appréciée!
Quelques options supplémentaires que j'ai essayées sur la base des commentaires et suggestions:
Octave:
eigs(M,6,0)
et eigs(M,6,'sm')
donnez-moi le même résultat:
[1.8725e-05 1.0189e-05 7.5622e-06 7.5420e-07 -1.2239e-18 -2.5674e-16]
tout eigs(M,6,'sa',struct('tol',2))
converge vers
[1.0423 2.7604 6.1548 11.1310 18.0207 25.3933]
beaucoup plus rapide, mais uniquement si les valeurs de tolérance sont supérieures à 2, sinon elles ne convergent pas du tout et les valeurs sont fortement différentes.
Python:
eigsh(M,k=6,which='SA')
et les eigsh(M,k=6,which='SM')
deux ne convergent pas (erreur ARPACK sur aucune convergence atteinte). eigsh(M,k=6,sigma=0.0)
Donne seulement quelques valeurs propres (après presque une heure), qui sont différentes de l'octave pour les plus petites (même 1 petite valeur supplémentaire est trouvée):
[3.82923317e-17 3.32269886e-16 2.78039665e-10 7.54202273e-07 7.56251500e-06 1.01893934e-05]
Si la tolérance est suffisamment élevée, j'obtiens également des résultats eigsh(M,k=6,which='SA',tol='1')
qui se rapprochent des autres valeurs obtenues
[4.28732218e-14 7.54194948e-07 7.56220703e-06 1.01889544e-05, 1.87247350e-05 2.02652719e-05]
encore une fois avec un nombre différent de petites valeurs propres. Le temps de calcul est encore proche de 30min. Alors que les différentes valeurs très petites peuvent être compréhensibles, car elles peuvent représenter des multiples de 0, la multiplicité différente me déconcerte.
De plus, il semble y avoir des différences fondamentales dans SciPy et Octave, que je ne peux pas encore comprendre.