web-dev-qa-db-fra.com

Sci-kit apprendre à imprimer des étiquettes pour la matrice de confusion?

J'utilise donc sci-kit pour classer certaines données. J'ai 13 valeurs/catégories différentes pour classer les données. Maintenant, j'ai pu utiliser la validation croisée et imprimer la matrice de confusion. Cependant, il ne montre que le TP et FP etc sans les étiquettes de classe, donc je ne sais pas quelle classe est quoi. Ci-dessous mon code et ma sortie:

def classify_data(df, feature_cols, file):
    nbr_folds = 5
    RANDOM_STATE = 0
    attributes = df.loc[:, feature_cols]  # Also known as x
    class_label = df['task']  # Class label, also known as y.
    file.write("\nFeatures used: ")
    for feature in feature_cols:
        file.write(feature + ",")
    print("Features used", feature_cols)

    sampler = RandomOverSampler(random_state=RANDOM_STATE)
    print("RandomForest")
    file.write("\nRandomForest")
    rfc = RandomForestClassifier(max_depth=2, random_state=RANDOM_STATE)
    pipeline = make_pipeline(sampler, rfc)
    class_label_predicted = cross_val_predict(pipeline, attributes, class_label, cv=nbr_folds)
    conf_mat = confusion_matrix(class_label, class_label_predicted)
    print(conf_mat)
    accuracy = accuracy_score(class_label, class_label_predicted)
    print("Rows classified: " + str(len(class_label_predicted)))
    print("Accuracy: {0:.3f}%\n".format(accuracy * 100))
    file.write("\nClassifier settings:" + str(pipeline) + "\n")
    file.write("\nRows classified: " + str(len(class_label_predicted)))
    file.write("\nAccuracy: {0:.3f}%\n".format(accuracy * 100))
    file.writelines('\t'.join(str(j) for j in i) + '\n' for i in conf_mat)

#Output
Rows classified: 23504
Accuracy: 17.925%
0   372 46  88  5   73  0   536 44  317 0   200 127
0   501 29  85  0   136 0   655 9   154 0   172 67
0   97  141 78  1   56  0   336 37  429 0   435 198
0   135 74  416 5   37  0   507 19  323 0   128 164
0   247 72  145 12  64  0   424 21  296 0   304 223
0   190 41  36  0   178 0   984 29  196 0   111 43
0   218 13  71  7   52  0   917 139 177 0   111 103
0   215 30  84  3   71  0   1175    11  55  0   102 62
0   257 55  156 1   13  0   322 184 463 0   197 160
0   188 36  104 2   34  0   313 99  827 0   69  136
0   281 80  111 22  16  0   494 19  261 0   313 211
0   207 66  87  18  58  0   489 23  157 0   464 239
0   113 114 44  6   51  0   389 30  408 0   338 315

Comme vous pouvez le voir, vous ne pouvez pas vraiment savoir quelle colonne est quoi et l'impression est également "mal alignée", donc c'est difficile à comprendre.

Existe-t-il également un moyen d'imprimer les étiquettes?

9
fall2

D'après doc , il semble qu'il n'y ait pas une telle option pour imprimer les lignes et les étiquettes des colonnes de la matrice de confusion. Cependant, vous pouvez spécifier l'ordre des étiquettes à l'aide de l'argument labels=...

Exemple:

from sklearn.metrics import confusion_matrix

y_true = ['yes','yes','yes','no','no','no']
y_pred = ['yes','no','no','no','no','no']
print(confusion_matrix(y_true, y_pred))
# Output:
# [[3 0]
#  [2 1]]
print(confusion_matrix(y_true, y_pred, labels=['yes', 'no']))
# Output:
# [[1 2]
#  [0 3]]

Si vous souhaitez imprimer la matrice de confusion avec des étiquettes, vous pouvez essayer pandas et définir les index et columns des DataFrame.

import pandas as pd
cmtx = pd.DataFrame(
    confusion_matrix(y_true, y_pred, labels=['yes', 'no']), 
    index=['true:yes', 'true:no'], 
    columns=['pred:yes', 'pred:no']
)
print(cmtx)
# Output:
#           pred:yes  pred:no
# true:yes         1        2
# true:no          0        3

Ou

unique_label = np.unique([y_true, y_pred])
cmtx = pd.DataFrame(
    confusion_matrix(y_true, y_pred, labels=unique_label), 
    index=['true:{:}'.format(x) for x in unique_label], 
    columns=['pred:{:}'.format(x) for x in unique_label]
)
print(cmtx)
# Output:
#           pred:no  pred:yes
# true:no         3         0
# true:yes        2         1
14
pe-perry

Il est important de s'assurer que la façon dont vous étiquetez vos lignes et colonnes de matrice de confusion correspond exactement à la façon dont sklearn a codé les classes. Le véritable ordre des étiquettes peut être révélé à l'aide de l'attribut .classes_ du classificateur. Vous pouvez utiliser le code ci-dessous pour préparer une trame de données de matrice de confusion.

labels = rfc.classes_
conf_df = pd.DataFrame(confusion_matrix(class_label, class_label_predicted, columns=labels, index=labels))
conf_df.index.name = 'True labels'

La deuxième chose à noter est que votre classificateur ne prévoit pas bien les étiquettes. Le nombre d'étiquettes correctement prédites est indiqué sur la diagonale principale de la matrice de confusion. Vous avez des valeurs non nulles à travers la matrice et certaines classes n'ont pas été prédites du tout - les colonnes qui sont toutes nulles. Il peut être judicieux d'exécuter le classificateur avec ses paramètres par défaut, puis d'essayer de les optimiser.

3
KRKirov

Puisque la matrice de confusion est juste une matrice numpy, elle ne contient aucune information de colonne. Ce que vous pouvez faire est de convertir votre matrice en trame de données, puis d'imprimer cette trame de données.

import pandas as pd
import numpy as np

def cm2df(cm, labels):
    df = pd.DataFrame()
    # rows
    for i, row_label in enumerate(labels):
        rowdata={}
        # columns
        for j, col_label in enumerate(labels): 
            rowdata[col_label]=cm[i,j]
        df = df.append(pd.DataFrame.from_dict({row_label:rowdata}, orient='index'))
    return df[labels]

cm = np.arange(9).reshape((3, 3))
df = cm2df(cm, ["a", "b", "c"])
print(df)

L'extrait de code provient de https://Gist.github.com/nickynicolson/202fe765c99af49acb20ea9f77b6255e

Production:

   a  b  c
a  0  1  2
b  3  4  5
c  6  7  8
0
Seljuk Gülcan

Il apparaît que vos données ont 13 classes différentes, c'est pourquoi votre matrice de confusion a 13 lignes et colonnes. De plus, vos classes ne sont en aucun cas étiquetées, juste des entiers d'après ce que je peux voir.

Si ce n'est pas le cas et que vos données d'entraînement ont des étiquettes réelles, vous pouvez transmettre une liste d'étiquettes uniques à confusion_matrix

conf_mat = confusion_matrix(class_label, class_label_predicted, df['task'].unique())
0
Talha A.

Une autre meilleure façon de procéder consiste à utiliser la fonction de tableau croisé dans les pandas.

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

ou

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

0
singhkuljeet004