2015-02-25 1 views
2

Par définition, une matrice carrée ayant un déterminant nul ne devrait pas être inversible. Cependant, pour une raison quelconque, après avoir généré une matrice de covariance, je prends l'inverse avec succès, mais prendre le déterminant de la matrice de covariance se termine par une sortie de 0.0.numpy: Possible d'inverser la matrice des déterminants zéro?

Qu'est-ce qui pourrait éventuellement ne pas fonctionner? Ne devrais-je pas faire confiance à la sortie du déterminant, ou ne devrais-je pas faire confiance à la matrice de covariance inverse? Ou les deux?

Snippet de mon code:

cov_matrix = np.cov(data) 
adjusted_cov = cov_matrix + weight*np.identity(cov_matrix.shape[0]) # add small weight to ensure cov_matrix is non-singular 
inv_cov = np.linalg.inv(adjusted_cov) # runs with no error, outputs a matrix 
det = np.linalg.det(adjusted_cov) # ends up being 0.0 
+0

Pourriez-vous nous montrer un exemple d'entrée et de sortie? Votre commentaire implique que vous essayez de rendre la matrice non-singulière, ce qui signifierait que la matrice devrait avoir un inverse valide. – BobChao87

+0

Erreurs d'arrondi? –

+0

Hmm, mon dataset est constitué de 28x28 images où j'utilise des pixels bruts comme caractéristiques, donc la sortie d'entrée serait trop grande pour être copiée, je pense (matrices de covariance 784x487). Je crois que l'ajout du poids entraîne une inversion valide - cependant, pourquoi le déterminant est-il alors nul? Si je n'ajoute pas le poids, j'obtiens l'erreur singulière d'algèbre lin. L'erreur d'arrondi s'appliquerait-elle au déterminant, où il arrondit à 0,0? – kk415kk

Répondre

3

Le numerical inversion of matrices ne comporte pas le calcul du déterminant. (Cramer's formula pour l'inverse n'est pas pratique pour les grandes matrices.) Ainsi, le fait que le déterminant évalue à 0 (en raison de la précision insuffisante des flotteurs) n'est pas un obstacle pour la routine d'inversion de matrice.

Faisant suite aux commentaires par BobChao87, voici un test simplifié (console Python 3.4, numpy importés comme np)

A = 0.2*np.identity(500) 
np.linalg.inv(A) 

sortie: une matrice avec 5 sur la diagonale principale, qui est la bonne inverse de A.

np.linalg.det(A) 

Résultat: 0,0, car le déterminant (0,2^500) est trop petit pour être représenté en double précision.

Une solution possible est une sorte de pre-conditioning (ici, juste redimensionnement): avant de calculer le déterminant, multiplier la matrice par un facteur qui rendra ses entrées plus proches de 1 en moyenne. Dans mon exemple, np.linalg.det(5*A) renvoie 1.

Bien sûr, en utilisant le facteur 5 ici est la triche, mais np.linalg.det(3*A) renvoie également une valeur non nulle (environ 1.19e-111). Si vous essayez np.linalg.det(2**k*A) pour k passant par des entiers positifs modestes, vous en frapperez probablement un qui retournera non nul. Alors vous saurez que le déterminant de la matrice originale était d'environ 2 ** (- k * n) fois la sortie, où n est la taille de la matrice.