Travailler sur une algèbre matricielle ici. Parfois, j'ai besoin d'inverser une matrice qui peut être singulière ou mal conditionnée. Je comprends que c'est pythonique de simplement faire ceci:
try:
i = linalg.inv(x)
except LinAlgErr as err:
#handle it
mais je ne suis pas sûr à quel point c'est efficace. Cela ne serait-il pas mieux?
if linalg.cond(x) < 1/sys.float_info.epsilon:
i = linalg.inv(x)
else:
#handle it
Numpy.Linalg est-il simplement effectué avant le test que je proscrit?
Donc basé sur les entrées ici, je marque mon bloc de code d'origine avec le test explicite comme solution:
if linalg.cond(x) < 1/sys.float_info.epsilon:
i = linalg.inv(x)
else:
#handle it
Étonnamment, la fonction numpy.linalg.inv n'effectue pas ce test. J'ai vérifié le code et je l'ai trouvé sur toutes ses machinations, puis appelle simplement la routine de lapack - semble assez inefficace. De plus, j'aurais 2ème point fait par Davep: que l'inverse d'une matrice ne doit pas être calculée à moins que cela ne soit explicitement nécessaire.
Votre première solution attrape le cas où votre matrice est si singulière que NUMPY ne peut pas faire face à tout - potentiellement un cas extrême. Votre deuxième solution est meilleure, car elle attrape le cas où NUMPY donne une réponse, mais cette réponse est potentiellement corrompue par une erreur d'arrondi - cela semble beaucoup plus raisonnable.
Si vous essayez d'inverser des matrices mal conditionnées, vous devriez envisager d'utiliser décomposition de valeur singulière . Si utilisé soigneusement, il peut vous donner une réponse raisonnable dans laquelle les autres routines échouent.
Si vous ne voulez pas SVD, voyez également mon commentaire sur l'utilisation de Lu_Factor au lieu d'INV.
Vous devez calculer le numéro de condition de la matrice pour voir s'il est inversible.
import numpy.linalg
if numpy.isfinite(numpy.linalg.cond(A)):
B = numpy.linalg.inv(A)
else:
# handle it
Pourquoi ne pas simplement vérifier si le déterminant est non nul?
det = numpy.linalg.det(A)
if det != 0:
#proceed