web-dev-qa-db-fra.com

Calculer le classement matriciel à l'aide de scipy

Je voudrais calculer le rang mathématique d'une matrice en utilisant scipy. La fonction la plus évidente numpy.rank calcule la dimension d'un tableau (ie. les scalaires ont la dimension 0, les vecteurs 1, les matrices 2, etc ...). Je sais que le numpy.linalg.lstsq le module a cette capacité, mais je me demandais si une telle opération fondamentale est intégrée quelque part dans la classe matricielle.

Voici un exemple explicite:

from numpy import matrix, rank
A = matrix([[1,3,7],[2,8,3],[7,8,1]])
print rank(A)

Cela donne 2 la dimension, où je cherche une réponse de 3.

41
Hooked

Numpy fournit numpy.linalg.matrix_rank():

>>> import numpy
>>> numpy.__version__
'1.5.1'
>>> A = numpy.matrix([[1,3,7],[2,8,3],[7,8,1]])
>>> numpy.linalg.matrix_rank(A)
3
57
Simon

Pour fournir un extrait de code approximatif aux personnes qui ont besoin de faire cela en pratique. N'hésitez pas à vous améliorer.

u, s, v = np.linalg.svd(A)
rank = np.sum(s > 1e-10)
14
Stefan van der Walt

Si numpy n'offre pas de fonction de classement, pourquoi n'écrivez-vous pas la vôtre?

Un moyen efficace de calculer le rang est via la décomposition de valeurs singulières - le rang de la matrice est égal au nombre de valeurs singulières non nulles.

def rank(A, eps=1e-12):
    u, s, vh = numpy.linalg.svd(A)
    return len([x for x in s if abs(x) > eps])

Notez que eps dépend de votre application - la plupart conviendront que 1e-12 correspond à zéro, mais vous pouvez assister à une instabilité numérique même pour eps = 1e-9.

En utilisant votre exemple, la réponse est trois. Si vous changez la deuxième ligne en [2, 6, 14] (dépendant linéairement de la première ligne), la réponse est deux (la valeur propre "zéro" est 4,9960E-16)

5
Escualo

Cette réponse est obsolète.

La réponse est non - il n'y a actuellement aucune fonction dédiée au calcul du rang matriciel d'un tableau/matrice dans scipy. En ajouter un a déjà été discuté auparavant, mais si cela doit arriver, je ne pense pas que ce soit encore le cas.

2
Mike Graham

scipy contient désormais une méthode interpolative efficace pour estimer le rang d'une matrice/LinearOperator à l'aide de méthodes aléatoires, qui peuvent souvent être suffisamment précises:

>>> from numpy import matrix
>>> A = matrix([[1,3,7],[2,8,3],[7,8,1]], dtype=float)  # doesn't accept int

>>> import scipy.linalg.interpolative as sli
>>> sli.estimate_rank(A, eps=1e-10)
3
1
jawknee

Je ne connais pas Numpy en particulier, mais il est peu probable que ce soit une opération intégrée sur une matrice; cela implique des calculs numériques assez intensifs (et des préoccupations associées concernant les erreurs d'arrondi à virgule flottante, etc.) et des sélections de seuil qui peuvent ou non être appropriées dans un contexte donné, et la sélection d'algorithmes est importante pour le calculer avec précision et rapidité.

Les choses qui sont intégrées dans les classes de base ont tendance à être des choses qui peuvent être effectuées de manière unique et directe, comme les multiplications matricielles au plus complexes.

1
Brooks Moses

Les fonctions d'algèbre linéaires sont généralement regroupées dans numpy.linalg. (Ils sont également disponibles auprès de scipy.linalg, qui a plus de fonctionnalités.) Cela permet le polymorphisme: les fonctions peuvent accepter n'importe quel type géré par SciPy.

Alors, oui, le numpy.linalg.lstsq function fait ce que vous demandez. Pourquoi est-ce insuffisant?

1
bignose