web-dev-qa-db-fra.com

quel est le moyen le plus rapide pour trouver des valeurs / vecteurs propres en python?

Actuellement, j'utilise numpy qui fait le travail. Mais, comme je traite des matrices avec plusieurs milliers de lignes/colonnes et plus tard ce chiffre atteindra des dizaines de milliers, je me demandais s'il existait un package capable d'effectuer ce type de calculs plus rapidement?

38
yurib
  • ** si votre matrice est clairsemée, instanciez votre matrice en utilisant un constructeur de scipy.sparse puis utilisez les méthodes analogues de vecteur propre/valeur propre dans spicy.sparse.linalg =. Du point de vue des performances, cela présente deux avantages:

    • votre matrice, construite à partir du constructeur spicy.sparse, sera plus petite proportionnellement à sa rareté.

    • les méthodes valeur propre/vecteur propre pour les matrices clairsemées ( eigs, eigsh) acceptent un argument optionnel, k qui est le nombre de paires vecteur propre/valeur propre que vous souhaitez renvoyer. Presque toujours, le nombre requis pour tenir compte de> 99% de la variance est bien inférieur au nombre de colonnes, que vous pouvez vérifier ex post; en d'autres termes, vous pouvez dire à la méthode de ne pas calculer et renvoyer toutes les paires de vecteurs propres/valeurs propres - au-delà du (généralement) petit sous-ensemble requis pour tenir compte de la variance, il est peu probable que vous ayez besoin du reste.

  • utilisez la bibliothèque d'algèbre linéaire dans SciPy, scipy.linalg, au lieu de la bibliothèque NumPy du même nom. Ces deux bibliothèques ont le même nom et utilisent les mêmes noms de méthode. Pourtant, il y a une différence de performances. Cette différence est due au fait que numpy.linalg est un moins wrapper fidèle sur les routines LAPACK analogues qui sacrifient certaines performances pour la portabilité et la commodité (c'est-à-dire, pour se conformer à l'objectif de conception NumPy que la bibliothèque entière NumPy doit être construite sans compilateur Fortran). linalg in SciPy d'autre part est un wrapper beaucoup plus complet sur LAPACK et qui utilise f2py.

  • sélectionnez la fonction appropriée à votre cas d'utilisation; en d'autres termes, n'utilisez pas une fonction qui fait plus que ce dont vous avez besoin. Dans scipy.linalg il y a plusieurs fonctions pour calculer les valeurs propres; les différences ne sont pas importantes, bien qu'en choisissant soigneusement la fonction pour calculer les valeurs propres, vous devriez voir une amélioration des performances. Par exemple:

    • scipy.linalg.eig renvoie les deux les valeurs propres et les vecteurs propres
    • scipy.linalg.eigvals, retourne uniquement les valeurs propres. Donc, si vous n'avez besoin que des valeurs propres d'une matrice, alors ne le faites pas utilisez linalg.eig, utilisez linalg.eigvals à la place .
    • si vous avez une matrice symétrique carrée à valeur réelle (égale à sa transposition), utilisez scipy.linalg.eigsh
  • optimisez votre build Scipy La préparation de votre environnement de build SciPy se fait en grande partie dans SciPy setup.py script. Peut-être que l'option la plus importante en termes de performances consiste à identifier les bibliothèques LAPACK optimisées telles que ATLAS ou Accelerate/vecLib framework (OS X uniquement?) Afin que SciPy puisse les détecter et construire contre eux. Selon la configuration dont vous disposez actuellement, l'optimisation de votre build SciPy puis sa réinstallation peuvent vous permettre d'augmenter considérablement les performances. Les notes supplémentaires de l'équipe principale de SciPy sont ici .

Ces fonctions fonctionneront-elles pour les grandes matrices?

Je devrais le penser. Ce sont des méthodes de décomposition matricielle de force industrielle, et qui ne sont que de minces enveloppes sur le Fortran analogue [~ # ~] lapack [~ # ~] routines.

J'ai utilisé la plupart des méthodes de la bibliothèque linalg pour décomposer des matrices dans lesquelles le nombre de colonnes est généralement compris entre environ 5 et 50 et dans lesquelles le nombre de lignes dépasse généralement 500 000. Ni les méthodes [~ # ~] svd [~ # ~] ni les méthodes eigenvalue ne semblent avoir de problème pour gérer les matrices de cette taille.

En utilisant la bibliothèque SciPy linalg vous pouvez calculer des vecteurs propres et des valeurs propres, avec un seul appel, en utilisant l'une des méthodes de cette bibliothèque, eig, eigvalsh, et 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

Si vos matrices sont clairsemées, vous pouvez essayer d'utiliser la fonction de valeurs propres clairsemées de scipy, qui devrait être plus rapide:

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

Vous pouvez également consulter des packages spécialisés comme SLEPc, qui a des liaisons python et peut effectuer des calculs en parallèle à l'aide de mpi:

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

9
JoshAdel