web-dev-qa-db-fra.com

Matrice de confusion Scikit-learn

Je ne peux pas savoir si j'ai correctement configuré mon problème de classification binaire. J'ai étiqueté la classe positive 1 et le négatif 0. Cependant, je crois comprendre que par défaut scikit-learn utilise la classe 0 comme classe positive dans sa matrice de confusion (donc l'inverse de la façon dont je l'ai configurée). C'est déroutant pour moi. La ligne du haut, dans le paramètre par défaut de scikit-learn, est-elle la classe positive ou négative? Supposons la sortie de la matrice de confusion:

confusion_matrix(y_test, preds)
 [ [30  5]
    [2 42] ]

À quoi cela ressemblerait-il dans une matrice de confusion? Les instances réelles sont-elles les lignes ou les colonnes dans scikit-learn?

          prediction                        prediction
           0       1                          1       0
         -----   -----                      -----   -----
      0 | TN   |  FP        (OR)         1 |  TP  |  FP
actual   -----   -----             actual   -----   -----
      1 | FN   |  TP                     0 |  FN  |  TN
18
OAK

scikit learn trie les étiquettes dans l'ordre croissant, donc les 0 sont la première colonne/ligne et les 1 sont la deuxième

>>> from sklearn.metrics import confusion_matrix as cm
>>> y_test = [1, 0, 0]
>>> y_pred = [1, 0, 0]
>>> cm(y_test, y_pred)
array([[2, 0],
       [0, 1]])
>>> y_pred = [4, 0, 0]
>>> y_test = [4, 0, 0]
>>> cm(y_test, y_pred)
array([[2, 0],
       [0, 1]])
>>> y_test = [-2, 0, 0]
>>> y_pred = [-2, 0, 0]
>>> cm(y_test, y_pred)
array([[1, 0],
       [0, 2]])
>>> 

Ceci est écrit dans le docs :

labels: array, shape = [n_classes], facultatif Liste des labels pour indexer la matrice. Cela peut être utilisé pour réorganiser ou sélectionner un sous-ensemble d'étiquettes. Si aucun n'est indiqué , ceux qui apparaissent au moins une fois dans y_true ou y_pred sont utilisés dans l'ordre trié .

Ainsi, vous pouvez modifier ce comportement en fournissant des étiquettes à l'appel confusion_matrix

>>> y_test = [1, 0, 0]
>>> y_pred = [1, 0, 0]
>>> cm(y_pred, y_pred)
array([[2, 0],
       [0, 1]])
>>> cm(y_pred, y_pred, labels=[1, 0])
array([[1, 0],
       [0, 2]])

Et les valeurs réelles/prédites sont oredées comme dans vos images - les prédictions sont en colonnes et les valeurs réelles en lignes

>>> y_test = [5, 5, 5, 0, 0, 0]
>>> y_pred = [5, 0, 0, 0, 0, 0]
>>> cm(y_test, y_pred)
array([[3, 0],
       [2, 1]])
  • vrai: 0, prédit: 0 (valeur: 3, position [0, 0])
  • vrai: 5, prédit: 0 (valeur: 2, position [1, 0])
  • vrai: 0, prédit: 5 (valeur: 0, position [0, 1])
  • vrai: 5, prédit: 5 (valeur: 1, position [1, 1])
26
lejlot

En suivant l'exemple de wikipedia . Si un système de classification a été formé pour distinguer les chats des non-chats, une matrice de confusion résumera les résultats des tests de l'algorithme pour une inspection plus approfondie. En supposant un échantillon de 27 animaux - 8 chats et 19 non chats, la matrice de confusion résultante pourrait ressembler au tableau ci-dessous:

enter image description here

Avec sklearn

Si vous souhaitez conserver la structure de la matrice de confusion de Wikipédia, commencez par les valeurs prédites, puis la classe réelle.

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

Out[1]: 
array([[ 5,  2],
       [ 3, 17]], dtype=int64)

Une autre façon avec les pandas de tableau croisé

true = pd.Categorical(list(np.where(np.array(y_true) == 1, 'cat','non-cat')), categories = ['cat','non-cat'])
pred = pd.Categorical(list(np.where(np.array(y_pred) == 1, 'cat','non-cat')), categories = ['cat','non-cat'])

pd.crosstab(pred, true, 
            rownames=['pred'], 
            colnames=['Actual'], margins=False, margins_name="Total")

Out[2]: 
Actual   cat  non-cat
pred                 
cat        5        2
non-cat    3       17

J'espère que ça vous sert

3
Rafael Díaz

Réponse courte En classification binaire, lors de l'utilisation de l'argument labels,

confusion_matrix([0, 1, 0, 1], [1, 1, 1, 0], labels=[0,1]).ravel()

les étiquettes de classe, 0, et 1, sont considérés comme Negative et Positive, respectivement. Cela est dû à l'ordre impliqué par la liste et non à l'ordre alphanumérique.


Vérification: Considérez les étiquettes de classe déséquilibrées comme ceci: (en utilisant la classe de déséquilibre pour faciliter la distinction)

>>> y_true = [0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0]
>>> y_pred = [0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0]
>>> table = confusion_matrix(y_true, y_pred, labels=[0,1]).reval()

cela vous donnerait un tableau de confusion comme suit:

>>> table
array([12,  1,  2,  1])

ce qui correspond à:

              Actual
        |   1   |   0  |
     ___________________
pred  1 |  TP=1 | FP=1 |
      0 |  FN=2 | TN=12|

FN=2 signifie qu'il y a eu 2 cas où le modèle a prédit que l'échantillon était négatif (c'est-à-dire 0) mais le libellé réel était positif (c'est-à-dire 1), donc Faux Négatif est égal à 2.

De même pour TN=12, dans 12 cas, le modèle a correctement prédit la classe négative (0), donc True Negative est égal à 12.

De cette façon, tout s'additionne en supposant que sklearn considère la première étiquette (dans labels=[0,1] comme classe négative. Par conséquent, ici, 0, la première étiquette, représente la classe négative.

2
Azim

Réponse à l'appui:

Lorsque vous dessinez les valeurs de la matrice de confusion à l'aide de sklearn.metrics, sachez que l'ordre des valeurs est

[Vrai Négatif Faux positif] [Faux Négatif Vrai Positif]

Si vous interprétez mal les valeurs, dites TP pour TN, vos précisions et AUC_ROC correspondront plus ou moins, mais votre la précision, le rappel, la sensibilité et le score f1 prendront un coup et vous finirez avec des métriques complètement différentes. Cela vous fera porter un faux jugement sur les performances de votre modèle.

Assurez-vous d'identifier clairement ce que représentent le 1 et le 0 dans votre modèle. Cela dicte fortement les résultats de la matrice de confusion.

Expérience:

Je travaillais sur la prévision de la fraude (classification supervisée binaire), où la fraude était désignée par 1 et la non-fraude par 0. Mon modèle a été formé sur un ensemble de données à plus grande échelle parfaitement équilibré, donc pendant test de temps, les valeurs de la matrice de confusion ne semblaient pas suspectes lorsque mes résultats étaient de l'ordre [TP FP] [FN TN]

Plus tard, quand j'ai dû effectuer un test hors du temps sur un nouvel ensemble de tests déséquilibré, j'ai réalisé que l'ordre de confusion ci-dessus était mauvais et différent du celui mentionné sur la page de documentation de sklearn qui se réfère à l'ordre comme tn, fp, fn, tp. Brancher la nouvelle commande m'a fait réaliser la bévue et quelle différence cela avait causé dans mon jugement sur les performances du modèle.

1
Vinad