Comment puis-je interpréter la matrice de confusion Sklearn


24

J'utilise une matrice de confusion pour vérifier les performances de mon classificateur.

J'utilise Scikit-Learn, je suis un peu confus. Comment interpréter le résultat de

from sklearn.metrics import confusion_matrix
>>> y_true = [2, 0, 2, 2, 0, 1]
>>> y_pred = [0, 0, 2, 2, 0, 2]
>>> confusion_matrix(y_true, y_pred)
array([[2, 0, 0],
       [0, 0, 1],
       [1, 0, 2]])

Comment puis-je décider si ces valeurs prédites sont bonnes ou non.


1
Oubliez d'abord sklearn, c'est un hareng rouge. La source de votre malentendu semble plus fondamentale. Jetez un œil ici: en.wikipedia.org/wiki/Confusion_matrix . Concentrez-vous sur le récit de l'exemple 3 * 3 sur la page wikipedia. Cela résoudra très probablement votre confusion.
Zhubarb

Réponses:


47

La matrice de confusion est un moyen de tabuler le nombre d'erreurs de classification, c'est-à-dire le nombre de classes prédites qui se sont retrouvées dans une mauvaise classe de classification basée sur les vraies classes.

Alors que sklearn.metrics.confusion_matrix fournit une matrice numérique, je trouve plus utile de générer un `` rapport '' en utilisant ce qui suit:

import pandas as pd
y_true = pd.Series([2, 0, 2, 2, 0, 1, 1, 2, 2, 0, 1, 2])
y_pred = pd.Series([0, 0, 2, 1, 0, 2, 1, 0, 2, 0, 2, 2])

pd.crosstab(y_true, y_pred, rownames=['True'], colnames=['Predicted'], margins=True)

ce qui se traduit par:

Predicted  0  1  2  All
True                   
0          3  0  0    3
1          0  1  2    3
2          2  1  3    6
All        5  2  5   12

Cela nous permet de voir que:

  1. Les éléments diagonaux indiquent le nombre de classifications correctes pour chaque classe: 3, 1 et 3 pour les classes 0, 1 et 2.
  2. Les éléments hors diagonale fournissent les erreurs de classification: par exemple, 2 de la classe 2 ont été classés de manière erronée comme 0, aucune de la classe 0 n'a été classée de manière erronée comme 2, etc.
  3. Le nombre total de classifications pour chaque classe à la fois y_trueet y_pred, à partir des sous - totaux « Tous »

Cette méthode fonctionne également pour les étiquettes de texte, et pour un grand nombre d'échantillons dans l'ensemble de données peut être étendu pour fournir des rapports de pourcentage.

import numpy as np
import pandas as pd

# create some data
lookup = {0: 'biscuit', 1:'candy', 2:'chocolate', 3:'praline', 4:'cake', 5:'shortbread'}
y_true = pd.Series([lookup[_] for _ in np.random.random_integers(0, 5, size=100)])
y_pred = pd.Series([lookup[_] for _ in np.random.random_integers(0, 5, size=100)])

pd.crosstab(y_true, y_pred, rownames=['True'], colnames=['Predicted']).apply(lambda r: 100.0 * r/r.sum())

La sortie est alors:

Predicted     biscuit  cake      candy  chocolate    praline  shortbread
True                                                                    
biscuit     23.529412    10  23.076923  13.333333  15.384615    9.090909
cake        17.647059    20   0.000000  26.666667  15.384615   18.181818
candy       11.764706    20  23.076923  13.333333  23.076923   31.818182
chocolate   11.764706     5  15.384615   6.666667  15.384615   13.636364
praline     17.647059    10  30.769231  20.000000   0.000000   13.636364
shortbread  17.647059    35   7.692308  20.000000  30.769231   13.636364

où les chiffres représentent maintenant le pourcentage (plutôt que le nombre de cas) des résultats qui ont été classés.

Bien noter, que la sklearn.metrics.confusion_matrixsortie peut être visualisée directement en utilisant:

import matplotlib.pyplot as plt
conf = sklearn.metrics.confusion_matrix(y_true, y_pred)
plt.imshow(conf, cmap='binary', interpolation='None')
plt.show()

4
Bienvenue sur notre site! J'apprécie le soin et la qualité que vous avez mis dans votre première réponse ici.
whuber

1
Le premier exemple ne fonctionne plus, du moins à partir de pandas-0.13.1. Je viens de passer à pandas-0.16.0, et j'obtiens toujours la même erreur:AssertionError: arrays and names must have the same length
chbrown

1
@chbrown: il semble que quelque chose ait changé chez les pandas qui doivent être un tableau ou une série. J'ai mis à jour l'exemple de code à utiliser y_pred = pd.Series(...). Cela devrait fonctionner maintenant.
achennu

5

Sur l'axe des confusion, la matrice de confusion a les valeurs réelles et sur l'axe des abscisses les valeurs données par le prédicteur. Par conséquent, les comptes sur la diagonale sont le nombre de prédictions correctes. Et les éléments de la diagonale sont des prédictions incorrectes.

Dans ton cas:

>>> confusion_matrix(y_true, y_pred)
    array([[2, 0, 0],  # two zeros were predicted as zeros
           [0, 0, 1],  # one 1 was predicted as 2
           [1, 0, 2]]) # two 2s were predicted as 2, and one 2 was 0

C'est un peu déroutant (vous avez dit "# 1 1 était prédit comme 2" - alors qu'en diagonale est 0), j'ai une matrice de 50K élément c'est un peu difficile de projeter toutes les valeurs. Y a-t-il une métrique pour me donner ces résultats directement? (Je veux dire si je reçois une bonne matrice de confusion ou non).
user3378649

1
Vous pouvez regarder les éléments sur la diagonale, ce sont vos prédictions correctes, les éléments hors diagonale sont de mauvaises prédictions. Voilà un début.
Akavall

J'ai obtenu deux résultats différents. Dans la cible, nous avons deux étiquettes «0» ou «1». Pouvez-vous nous donner un indice sur la façon d'interpréter ces résultats? - confusion_matrix: [[0 85723] [0 77]] - confusion_matrix: [[85648 75] [75 2]]
user3378649

1

Je voudrais préciser graphiquement la nécessité de comprendre cela. C'est une matrice simple qui doit être bien comprise avant de tirer des conclusions. Voici donc une version explicative simplifiée des réponses ci-dessus.

        0  1  2   <- Predicted
     0 [2, 0, 0]  
TRUE 1 [0, 0, 1]  
     2 [1, 0, 2] 

# At 0,0: True value was 0, Predicted value was 0, - 2 times predicted
# At 1,1: True value was 1, Predicted value was 1, - 0 times predicted
# At 2,2: True value was 2, Predicted value was 2, - 2 times predicted
# At 1,2: True value was 1, Predicted value was 2, - 1 time predicted
# At 2,0: True value was 2, Predicted value was 0, - 1 time predicted...
...Like that

4
Pourriez-vous modifier cela pour dire comment vous pensez que cela va au-delà des réponses déjà données?
mdewey

1
Hey! Je viens de faire référence à la réponse d'Akavall. Il a mentionné la réflexion impliquée. Je viens d'expliquer sa réponse, qui a tendance à être correcte, d'une meilleure manière sans doute.
Pranzell

@Pranzell Pourriez-vous s'il vous plaît partager votre code pour dessiner un si beau tableau basé sur du texte?
fu DL
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.