Comprendre comment Numpy fait SVD


13

J'ai utilisé différentes méthodes pour calculer à la fois le rang d'une matrice et la solution d'un système matriciel d'équations. Je suis tombé sur la fonction linalg.svd. En comparant cela à mes propres efforts pour résoudre le système avec l'élimination gaussienne, cela semble être à la fois plus rapide et plus précis. J'essaie de comprendre comment cela est possible.

Pour autant que je sache, la fonction linalg.svd utilise un algorithme QR pour calculer les valeurs propres de ma matrice. Je sais comment cela fonctionne mathématiquement, mais je ne sais pas comment Numpy parvient à le faire si rapidement et sans perdre beaucoup de précision.

Donc ma question: comment fonctionne la fonction numpy.svd, et plus précisément, comment parvient-elle à le faire rapidement et avec précision (par rapport à l'élimination gaussienne)?


2
numpy utilise la routine Lapack dgesddpour les SVD à valeur réelle. Donc, votre vraie question est probablement "comment fonctionne Lapack dgesdd?", Et c'est assez hors sujet pour stackoverflow.
talonmies

Si vous êtes vraiment curieux, je vous suggère d'examiner la source LAPACK.

Merci pour vos commentaires et mes excuses, je suis hors sujet.
RobVerheyen

Ce post est un cross-post de Stack Overflow . La publication croisée est généralement déconseillée sur les sites Stack Exchange. Le protocole standard pour republier une question sur un autre site consiste à fermer, supprimer ou migrer le message d'origine avant de tenter de republier sur un autre site. (Si vous migrez la question, elle est automatiquement
republiée

Je suis désolé, je n'étais pas au courant du protocole. J'espère que je pourrai toujours obtenir une réponse.
RobVerheyen

Réponses:


15

Il y a un certain nombre de problèmes dans votre question.

N'utilisez pas d'élimination gaussienne (factorisation LU) pour calculer le rang numérique d'une matrice. La factorisation LU n'est pas fiable à cet effet en arithmétique à virgule flottante. Utilisez plutôt une décomposition QR révélatrice de rang (comme xGEQPXou xGEPQYdans LAPACK, où x est C, D, S ou Z, bien que ces routines soient difficiles à retrouver; voir la réponse de JedBrown sur une question connexe ), ou utilisez un SVD (décomposition de valeurs singulières, comme xGESDDou xGESVD, où x est à nouveau C, D, S ou Z). Le SVD est un algorithme plus précis et fiable pour la détermination du rang numérique, mais il nécessite plus d'opérations en virgule flottante.

Cependant, pour résoudre un système linéaire, la factorisation LU (avec pivotement partiel, qui est l'implémentation standard dans LAPACK) est extrêmement fiable dans la pratique. Il existe certains cas pathologiques pour lesquels la factorisation LU avec pivotement partiel est instable (voir la leçon 22 en Algèbre linéaire numériquepar Trefethen et Bau pour plus de détails). La factorisation QR est un algorithme numérique plus stable pour résoudre des systèmes linéaires, c'est probablement pourquoi il vous donne des résultats aussi précis. Cependant, cela nécessite plus d'opérations en virgule flottante que la factorisation LU par un facteur 2 pour les matrices carrées (je crois; JackPoulson peut me corriger à ce sujet). Pour les systèmes rectangulaires, la factorisation QR est un meilleur choix car elle donnera des solutions des moindres carrés à des systèmes linéaires surdéterminés. SVD peut également être utilisé pour résoudre des systèmes linéaires, mais il sera plus coûteux que la factorisation QR.

janneb a raison que numpy.linalg.svd est un wrapper xGESDDdans LAPACK. Les décompositions de valeurs singulières se déroulent en deux étapes. Premièrement, la matrice à décomposer est réduite à une forme bidiagonale. L'algorithme utilisé pour réduire à la forme bidiagonale dans LAPACK est probablement l'algorithme de Lawson-Hanson-Chan, et il utilise la factorisation QR à un moment donné. La leçon 31 en Algèbre linéaire numérique de Trefethen et Bau donne un aperçu de ce processus. Ensuite, xGESDDutilise un algorithme de division et de conquête pour calculer les valeurs singulières et les vecteurs singuliers gauche et droit à partir de la matrice bidiagonale. Pour obtenir des informations sur cette étape, vous devrez consulter Matrix Computations de Golub et Van Loan, ou Applied Numerical Linear Algebra de Jim Demmel.

Enfin, vous ne devez pas confondre les valeurs singulières avec les valeurs propres . Ces deux ensembles de quantités ne sont pas identiques. Le SVD calcule les valeurs singulières d'une matrice. Le calcul numérique de Cleve Moler avec MATLAB donne un bon aperçu des différences entre les valeurs singulières et les valeurs propres . En général, il n'y a pas de relation évidente entre les valeurs singulières d'une matrice donnée et ses valeurs propres, sauf dans le cas des matrices normales , où les valeurs singulières sont la valeur absolue des valeurs propres.


Je pense que "non apparenté" est assez fort pour la relation entre les valeurs propres et les valeurs singulières. La relation est assez obscure à moins que vous ne connaissiez la décomposition complète de Jordan de votre matrice, mais vous pouvez utiliser l'une pour obtenir des estimations de l'autre si vous avez des informations (ou si vous êtes prêt à faire des hypothèses) sur ladite décomposition de Jordan.
Dan

Que suggéreriez-vous à la place?
Geoff Oxberry

Tout d'abord, merci pour la réponse détaillée. J'ai découvert que je ne peux pas utiliser la décomposition LU pour déterminer le classement de la matrice à la dure. Votre réponse semble impliquer que la factorisation QR serait en fait une méthode plus rapide pour résoudre mon problème, n'est-ce pas? Y a-t-il un avantage distinct à utiliser SVD? J'étais bien conscient du fait que les valeurs singulières ne sont pas des valeurs propres. Je faisais allusion au fait que des valeurs singulières peuvent être calculées comme des valeurs propres de la matrice multipliées par sa transposition à partir de la gauche. Je suis désolé, ce n'était pas clair.
RobVerheyen

Je pourrais ajouter que la matrice que je résous est en fait singulière. En fait, le rang de la matrice ne représente qu'environ la moitié de la taille de la matrice. Peut-être que cela rend une méthode plus préférable?
RobVerheyen

1
@RobVerheyen: QR sera plus lent que LU, mais considérablement plus précis. SVD sera encore plus lent que QR, mais SVD est considéré comme la méthode la plus fiable pour déterminer le rang numérique (par exemple, MATLAB utilise le SVD dans sa rankfonction). Il y a aussi un peu de discrétion lors de l'utilisation de l'une ou l'autre approche; dans l'approche SVD, le rang numérique est le nombre de valeurs singulières au-dessus d'un seuil spécifié (généralement très petit). (L'approche QR est similaire, mais remplace les valeurs singulières par des entrées diagonales de la matrice R.)
Geoff Oxberry

8

En raison du libellé de votre question, je suppose que votre matrice est carrée. Les routines SVD de LAPACK, telles que zgesvd , procèdent essentiellement en trois étapes pour les matrices carrées:

  1. Calculer implicitement des matrices unitaires UUNE et VUNE, en tant que produits de Householder se transforme, de sorte que la matrice générale UNE est réduit à une vraie matrice bidiagonale supérieure B: =UUNEHUNEVUNE. A la sortie de ce sous-programme, les vecteurs Householder (normalisés pour que leur première entrée soit implicitement un) pourUUNE et VUNE sont respectivement stockés dans les parties de Ben dessous et à droite de la principale et de la super-diagonale. Cette étape nécessiteO(n3) travail.
  2. A variation on an algorithm for computing the eigenvalue decomposition of a real symmetric tridiagonal matrix is used to compute a bidiagonal SVD. Though the best-known algorithm for real symmetric tridiagonal EVP's (MRRR) is not yet, to my knowledge, stable for the bidiagonal SVD, there is an interesting discussion here. LAPACK currently uses a divide and conquer approach for the bidiagonal SVD. The bidiagonal SVD yields {UB,VB,Σ} such that B=UBΣVBH. This step will require O(n2) work when MRRR is made stable for SVD, but currently requires as much as O(n3) work.
  3. This step is trivial. Since UABVAH=A, A=(UAUB)Σ(VAVB)H, so that the SVD can be explicitly formed after applying the Householder transforms which implicitly define UA and VA to UB and VB, respectively. This step required O(n3) work.

7

numpy.linalg.svd is a wrapper around {Z,D}GESDD from LAPACK. LAPACK, in turn, is very carefully written by some of the world's foremost experts in numerical linear algebra. Indeed, it'd be very surprising if someone not intimately familiar with the field would succeed in beating LAPACK (either in speed or accuracy).

As for why QR is better than Gaussian elimination, that is probably more appropriate for /scicomp//


Thank you for the answer and the reference. I'll try it over there.
RobVerheyen
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.