web-dev-qa-db-fra.com

Pourquoi numpy.linalg.solve () offre-t-il des inversions de matrice plus précises que numpy.linalg.inv ()?

Je ne comprends pas très bien pourquoi numpy.linalg.solve() donne la réponse plus précise, alors que numpy.linalg.inv() se décompose quelque peu, donnant (ce que je crois) des estimations.

Pour un exemple concret, je résous l'équation C^{-1} * dC désigne une matrice et d est un tableau vectoriel. Pour les besoins de la discussion, les dimensions de C sont de forme (1000,1000) Et d de forme (1,1000).

numpy.linalg.solve(A, b) résout l'équation A*x=b pour x, c'est-à-dire x = A^{-1} * b. Par conséquent, je pourrais soit résoudre cette équation en

(1)

inverse = numpy.linalg.inv(C)
result = inverse * d

ou (2)

numpy.linalg.solve(C, d)

La méthode (2) donne des résultats beaucoup plus précis. Pourquoi est-ce?

Que se passe-t-il exactement pour que l'un "fonctionne mieux" que l'autre?

24
ShanZhengYang

np.linalg.solve(A, b) ne pas calcule l'inverse de [~ # ~] a [~ # ~ ] . Au lieu de cela, il appelle l'une des routines gesv LAPACK , qui factorise d'abord [~ # ~] a [~ # ~] en utilisant LU décomposition, puis résout pour x en utilisant la substitution avant et arrière (voir ici ).

np.linalg.inv utilise la même méthode pour calculer l'inverse de [~ # ~] a [~ # ~] en résolvant pour A-1 dans A · A-1 = I [~ # ~] i [~ # ~] est l'identité *. L'étape de factorisation est exactement la même que ci-dessus, mais il faut plus d'opérations en virgule flottante pour résoudre A-1 (une matrice n × n ) que pour x (an n - vecteur long). De plus, si vous souhaitez ensuite obtenir x via l'identité A-1· B = x alors la multiplication supplémentaire de la matrice entraînerait encore plus d'opérations en virgule flottante, et donc des performances plus lentes et plus d'erreur numérique.

Il n'y a pas besoin de l'étape intermédiaire de calcul A-1 - il est plus rapide et plus précis d'obtenir x directement.


* Le bit de source pertinent pour inv est ici . Malheureusement, c'est un peu difficile à comprendre car il est basé sur un modèle C. La chose importante à noter est qu'une matrice d'identité est passée au solveur LAPACK en tant que paramètre B.

36
ali_m