Читать книгу Praxiseinstieg Machine Learning mit Scikit-Learn, Keras und TensorFlow - Aurélien Géron - Страница 102
Die ROC-Kurve
ОглавлениеDie ROC-Kurve (Receiver Operating Characteristic) ist ein weiteres verbreitetes Hilfsmittel bei der binären Klassifikation. Sie ist der Relevanz-Sensitivitäts-Kurve sehr ähnlich, aber anstatt die Relevanz gegen die Sensitivität aufzutragen, zeigt die ROC-Kurve die Richtig-positiv-Rate (TNR) (ein anderer Name für Sensitivität) gegen die Falsch-positiv-Rate (FPR). Die FPR ist der Anteil negativer Datenpunkte, die fälschlicherweise als positiv eingestuft werden. Sie ist eins minus der Richtignegativ-Rate, dem Anteil der korrekt als negativ eingestuften Datenpunkte. Die TNR wird auch als Spezifität bezeichnet. Also wird bei der ROC-Kurve die Sensitivität gegen die 1-Spezifität aufgetragen.
Um eine ROC-Kurve zu plotten, müssen Sie zunächst mit der Funktion roc_curve() die TPR und die FPR bei unterschiedlichen Schwellenwerten berechnen:
from sklearn.metrics import roc_curve
fpr, tpr, thresholds = roc_curve(y_train_5, y_scores)
Anschließend plotten Sie mit Matplotlib die FPR gegen die TPR. Der folgende Code stellt die Abbildung in Abbildung 3-6 her:
def plot_roc_curve(fpr, tpr, label=None):
plt.plot(fpr, tpr, linewidth=2, label=label)
plt.plot([0, 1], [0, 1], 'k--') # diagonal gestrichelt
[...] # Achsenbeschriftungen und Raster hinzufügen
plot_roc_curve(fpr, tpr)
plt.show()
Auch hier gilt es, einen Kompromiss zu schließen: Je höher die Sensitivität (TPR), desto mehr falsch Positive (FPR) liefert der Klassifikator. Die gestrichelte Linie stellt die ROC-Kurve eines völlig zufälligen Klassifikators dar; ein guter Klassifikator entfernt sich so weit wie möglich von dieser Linie (in Richtung der linken oberen Ecke).
Abbildung 3-6: Diese ROC-Kurve plottet die FPR gegen die TPR für alle möglichen Schwellenwerte – der rote Punkt steht für das gewählte Verhältnis (bei 43,68% Sensitivität).
Klassifikatoren lassen sich vergleichen, indem man die Area under the Curve (AUC) bestimmt. Ein perfekter Klassifikator hat eine ROC AUC von genau 1, ein völlig zufälliger dagegen hat eine ROC AUC von 0,5. In Scikit-Learn gibt es eine Funktion zum Berechnen der ROC AUC:
>>> from sklearn.metrics import roc_auc_score
>>> roc_auc_score(y_train_5, y_scores)
0.9611778893101814
Da die ROC-Kurve der Relevanz-Sensitivitäts-Kurve (oder auch PR-Kurve, engl. Precision/Recall) recht ähnlich ist, fragen Sie sich vielleicht, welche Sie denn nun benutzen sollen. Als Faustregel sollten Sie die PR-Kurve immer dann bevorzugen, wenn die positive Kategorie selten ist oder wenn die falsch Positiven wichtiger als die falsch Negativen sind. Andernfalls verwenden Sie die ROC-Kurve. Beim Betrachten der obigen ROC-Kurve (und des ROC-AUC-Scores) könnten Sie denken, dass der Klassifikator wirklich gut ist. Aber das liegt vor allem daran, dass es nur wenige Positive (5en) im Vergleich zu den Negativen (Nicht-5en) gibt. Die PR-Kurve dagegen macht deutlich, dass unser Klassifikator noch Luft nach oben hat (die Kurve sollte näher an der oberen linken Ecke liegen). |
Trainieren wir nun einen RandomForestClassifier und vergleichen wir dessen ROC-Kurve und ROC-AUC-Score mit dem SGDClassifier. Zunächst benötigen wir die Scores für jeden Datenpunkt im Trainingsdatensatz. Allerdings besitzt der RandomForestClassifier aufgrund seiner Funktionsweise (siehe Kapitel 7) keine Methode decision_function(). Stattdessen besitzt er die Methode predict_proba(). Klassifikatoren in Scikit-Learn haben im Allgemeinen die eine oder die andere – oder beide. Die Methode predict_proba() liefert ein Array mit einer Zeile pro Datenpunkt und einer Spalte pro Kategorie. Es enthält die Wahrscheinlichkeit, dass ein bestimmter Datenpunkt einer bestimmten Kategorie angehört (z.B. eine 70%ige Chance, dass das Bild eine 5 darstellt):
from sklearn.ensemble import RandomForestClassifier
forest_clf = RandomForestClassifier(random_state=42)
y_probas_forest = cross_val_predict(forest_clf, X_train, y_train_5, cv=3,
method="predict_proba")
Die Funktion roc_curve() erwartet Labels und Scores, aber statt Scores können Sie ihr auch Wahrscheinlichkeiten von Kategorien mitgeben. Nutzen wir die Wahrscheinlichkeit der positiven Kategorie als Score:
y_scores_forest = y_probas_forest[:, 1] # score = Wahrscheinlichkeit
# der positiven Kategorie
fpr_forest, tpr_forest, thresholds_forest = roc_curve(y_train_5,y_scores_forest)
Nun sind Sie so weit, die ROC-Kurve zu plotten. Dabei ist es hilfreich, zum Vergleich auch die erste ROC-Kurve zu plotten (siehe Abbildung 3-7):
plt.plot(fpr, tpr, "b:", label="SGD")
plot_roc_curve(fpr_forest, tpr_forest, "Random Forest")
plt.legend(loc="lower right")
plt.show()
Wie in Abbildung 3-7 gezeigt, sieht die Kurve für den RandomForestClassifier viel besser aus als die für den SGDClassifier: Sie kommt deutlich näher an die linke obere Ecke heran. Dementsprechend ist auch der ROC-AUC-Score deutlich besser:
>>> roc_auc_score(y_train_5, y_scores_forest)
0.9983436731328145
Versuchen Sie, Relevanz und Sensitivität zu berechnen: Sie sollten eine Relevanz von 99,0% und eine Sensitivität von 86,6% erhalten. Gar nicht schlecht!
Sie wissen nun hoffentlich, wie Sie binäre Klassifikatoren trainieren, ein für Ihre Aufgabe geeignetes Qualitätsmaß auswählen, Ihre Klassifikatoren mithilfe einer Kreuzvalidierung auswerten, einen Ihren Anforderungen entsprechenden Kompromiss zwischen Relevanz und Sensitivität finden und unterschiedliche Modelle über ROC-Kurven und ROC-AUC-Scores vergleichen können. Versuchen wir als Nächstes, mehr als nur die 5en zu erkennen.
Abbildung 3-7: Vergleich zweier ROC-Kurven: Der Random-Forest-Klassifikator ist besser als der SGD-Klassifikator, weil dessen ROC-Kurve viel näher an der oberen linken Ecke ist und eine größere AUC besitzt.