[PYTHON] Courbe ROC pour la classification multi-classes

Objectif

Un mémorandum pour dessiner des courbes ROC en lisant les valeurs prédites de classification multi-classes enregistrées au format xlsx ou csv avec des pandas Je pratique également l'écriture d'articles pour Qiita.

À propos de la courbe ROC

Je n'entrerai pas dans les bases dans cet article. En ce qui concerne l'histoire de la courbe ROC, l'article ici est facile à comprendre.

Changement de format d'étiquette

Vérifiez d'abord le format des données. pandas1.JPG --GT a des valeurs numériques de 0, 1, 2 et correspond à chaque étiquette. --C1, C2, C3: chaque étiquette C1 = 0,0, C2 = 1,0, C3 = 2,0 --M1, M2, M3: chaque modèle

La courbe ROC doit être convertie en 0, 1 binaire

from sklearn.preprocessing import label_binarize
y_test = label_binarize(df.iloc[:, 0], classes=[0,1,2])

Utilisez le label_binarize de sklearn pour la conversion binaire. binary.JPG C'est un peu long, donc seulement la partie supérieure. À la suite de la conversion binaire, C1 = [1, 0, 0], C2 = [0, 1, 0], C3 = [0, 0, 1].

Liste des valeurs prédites

Après avoir binarisé les étiquettes, les valeurs prédites pour chaque modèle doivent également être converties dans la liste correspondante.

M1_y_score = []
M2_y_score = []
M3_y_score = []
for i in df.index:
    M1_y_score.append(([df.iloc[i, 1], df.iloc[i, 2], df.iloc[i, 3]]))
    M2_y_score.append(([df.iloc[i, 4], df.iloc[i, 5], df.iloc[i, 6]]))
    M3_y_score.append(([df.iloc[i, 7], df.iloc[i, 8], df.iloc[i, 9]]))
M1_y_score = M1_y_score
M2_y_score = M2_y_score
M3_y_score = M3_y_score

Comme ça, j'ai exécuté le traitement en boucle et stocké la valeur prédite. À ce point,

from sklearn.metrics import roc_auc_score
auc_m1 = roc_auc_score(y_test, M1_y_score, multi_class="ovo")
print(auc_m1)

Vous pouvez trouver un AUC multi-classes en tapant. L'argument multi_class semble générer une erreur si vous ne définissez ni "ovo" ni "ovr". Pour plus de détails, consultez la documentation sklearn .

Calcul du FPR et du TPR

Cette partie vient de trébucher.

M1_fpr = dict()
M1_tpr = dict()
M1_roc_auc = dict()
M2_fpr = dict()
M2_tpr = dict()
M2_roc_auc = dict()
M3_fpr = dict()
M3_tpr = dict()
M3_roc_auc = dict()

Après avoir créé un dictionnaire vide pour stocker les données

n_class = 3
from sklearn.metrics import roc_curve, auc
for i in range(n_classes):
    M1_fpr[i], M1_tpr[i], _ = roc_curve(y_test[:, i], M1_y_score[:, i])
    M1_roc_auc[i] = auc(M1_fpr[i], M1_tpr[i])

    M2_fpr[i], M2_tpr[i], _ = roc_curve(y_test[:, i], M2_y_score[:, i])
    M2_roc_auc[i] = auc(M2_fpr[i], M2_tpr[i])

    M3_fpr[i], M3_tpr[i], _ = roc_curve(y_test[:, i], M3_y_score[:, i])
    M3_roc_auc[i] = auc(M3_fpr[i], M3_tpr[i])

Je parcourt le nombre d'étiquettes et stocke le fpr et le tpr de chaque modèle. error1.JPG J'obtiens une erreur pour une raison quelconque! C'est parce que je n'en ai pas fait un ndarray lors du stockage des valeurs prédites. Alors, changez un peu le code ci-dessus ...

M1_y_score = np.array(M1_y_score)
M2_y_score = np.array(M2_y_score)
M3_y_score = np.array(M3_y_score)

En en faisant un type ndarray, il est désormais possible de stocker des données dans un dictionnaire. Après cela, si vous codez selon le document officiel, c'est OK!

M1_all_fpr = np.unique(np.concatenate([M1_fpr[i] for i in range(n_classes)]))
M2_all_fpr = np.unique(np.concatenate([M2_fpr[i] for i in range(n_classes)]))
M3_all_fpr = np.unique(np.concatenate([M3_fpr[i] for i in range(n_classes)]))
M1_mean_tpr = np.zeros_like(M1_all_fpr)
M2_mean_tpr = np.zeros_like(M2_all_fpr)
M3_mean_tpr = np.zeros_like(M3_all_fpr)

for i in range(n_classes):
    M1_mean_tpr += np.interp(M1_all_fpr, M1_fpr[i], M1_tpr[i])
    M2_mean_tpr += np.interp(M2_all_fpr, M2_fpr[i], M2_tpr[i])
    M3_mean_tpr += np.interp(M3_all_fpr, M3_fpr[i], M3_tpr[i])

M1_mean_tpr /= n_classes
M2_mean_tpr /= n_classes
M3_mean_tpr /= n_classes

M1_fpr["macro"] = M1_all_fpr
M1_tpr["macro"] = M1_mean_tpr
M1_roc_auc["macro"] = auc(M1_fpr["macro"], M1_tpr["macro"])

M2_fpr["macro"] = M2_all_fpr
M2_tpr["macro"] = M2_mean_tpr
M2_roc_auc["macro"] = auc(M2_fpr["macro"], M2_tpr["macro"])

M3_fpr["macro"] = M3_all_fpr
M3_tpr["macro"] = M3_mean_tpr
M3_roc_auc["macro"] = auc(M3_fpr["macro"], M3_tpr["macro"])

Dessin de courbe ROC

Une fois cela fait, tout ce que vous avez à faire est de le représenter graphiquement en utilisant matplotlib.

import matplotlib.pyplot as plt
from matplotlib import cm
lw=1
colors = [cm.gist_ncar(190), cm.gist_ncar(30), cm.gist_ncar(10)]
sns.color_palette(colors)
sns.set_palette(colors, desat=1.0)

plt.figure(figsize=(6, 6))

plt.plot(M1_fpr["macro"], M1_tpr["macro"],
         label='M1',
         color=colors[0], 
         linestyle='-', 
         linewidth=2)

plt.plot(M2_fpr["macro"], M2_tpr["macro"],
         label='M2',
         color=colors[1], 
         linestyle='-', 
         linewidth=2)

plt.plot(M3_fpr["macro"], M3_tpr["macro"],
         label='M3',
         color=colors[2], 
         linestyle='-', 
         linewidth=2)

plt.plot([0, 1], [0, 1], 'k--', lw=lw)
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.legend(loc="lower right")
plt.show()

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784518/0a44adaf-50eb-9bd7-55bc-1a7a0adaf28b.jpeg ", width=50%)> J'ai pu dessiner une courbe ROC de classification multi-classes en utilisant des moyennes macro.

Recommended Posts

Courbe ROC pour la classification multi-classes
Tracer la courbe ROC pour la classification binaire avec Matplotlib
SVM (classification multi-classes)
Naive Bays (classification multi-classes)
Iris de classification multiclasse Keras
Méthode de voisinage K (classification multi-classes)
CNN (1) pour la classification des images (pour les débutants)
Courbe ROC et courbe PR-Comprendre comment évaluer les performances de classification ②-