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?
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
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.
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
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())
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)