Praxiseinstieg Machine Learning mit Scikit-Learn, Keras und TensorFlow. Aurélien Géron
von 0 auch korrekt erkennt. Er scheitert aber, wenn wir den Schwellenwert auf 8000 erhöhen.
Wie sollen wir uns also für einen Schwellenwert entscheiden? Dazu müssen Sie zunächst wieder die Scores sämtlicher Datenpunkte im Trainingsdatensatz mit der Funktion cross_val_predict() ermitteln, diesmal aber mit der Angabe, dass Sie die Entscheidungswerte anstelle der Vorhersagen erhalten möchten:
y_scores = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3,
method="decision_function")
Mit diesen Scores können Sie Relevanz und Sensitivität für alle möglichen Schwellenwerte mithilfe der Funktion precision_recall_curve() berechnen:
from sklearn.metrics import precision_recall_curve
precisions, recalls, thresholds = precision_recall_curve(y_train_5, y_scores)
Als letzten Schritt verwenden Sie Matplotlib, um Relevanz und Sensitivität als Funktion des Schwellenwerts darzustellen (siehe Abbildung 3-4):
def plot_precision_recall_vs_threshold(precisions, recalls, thresholds):
plt.plot(thresholds, precisions[:-1], "b--", label="Relevanz")
plt.plot(thresholds, recalls[:-1], "g-", label="Sensitivität")
[...] # Schwellenwert hervorheben und Legende, Achsbeschriftung
# und Raster ergänzen
plot_precision_recall_vs_threshold(precisions, recalls, thresholds)
plt.show()
Abbildung 3-4: Relevanz und Sensitivität über dem Schwellenwert zur Entscheidung
|
Sie fragen sich vielleicht, warum die Verlaufskurve der Relevanz in Abbildung 3-4 unregelmäßiger ist als die der Sensitivität. Das liegt daran, dass die Relevanz manchmal beim Erhöhen des Schwellenwerts sinkt (auch wenn sie im Allgemeinen steigt). Um dies nachzuvollziehen, betrachten Sie noch einmal Abbildung 3-3. Wenn Sie beim Schwellenwert in der Mitte beginnen und sich nur eine Ziffer nach rechts bewegen, sinkt die Relevanz von |
Zur Auswahl eines Kompromisses zwischen Relevanz und Sensitivität können Sie auch die Relevanz gegen die Sensitivität plotten, wie in Abbildung 3-5 gezeigt (hier ist der gleiche Schwellenwert wie zuvor hervorgehoben).
Wie Sie sehen, fällt die Relevanz etwa bei einer Sensitivität von 80% scharf ab. Vermutlich sollten Sie einen Kompromiss zwischen Relevanz und Sensitivität kurz vor diesem Abfall auswählen – beispielsweise bei einer Sensitivität von etwa 60%. Aber natürlich hängt das auch von Ihrem Projekt ab.
Abbildung 3-5: Relevanz gegen Sensitivität
Nehmen wir an, Sie möchten eine Relevanz von 90% erhalten. Sie schauen im ersten Diagramm nach und finden heraus, dass Sie einen Schwellenwert von etwa 8000 benötigen. Um genauer zu sein, können Sie nach dem niedrigsten Schwellenwert suchen, der Ihnen mindestens 90% Relevanz liefert (np.argmax() wird Ihnen den ersten Index des maximalen Werts liefern, was in diesem Fall dem ersten True-Wert entspricht):
threshold_90_precision = thresholds[np.argmax(precisions >= 0.90)] # ~7816
Um Vorhersagen zu treffen (vorerst noch auf den Trainingsdaten), führen Sie anstelle der Methode predict() des Klassifikators den folgenden Code aus:
y_train_pred_90 = (y_scores >= threshold_90_precision)
Überprüfen wir Relevanz und Sensitivität dieser Vorhersagen:
>>> precision_score(y_train_5, y_train_pred_90)
0.9000380083618396
>>> recall_score(y_train_5, y_train_pred_90)
0.4368197749492714
Großartig, Sie haben nun einen Klassifikator mit einer Relevanz von 90% (Sie sind zumindest nah genug dran)! Wie Sie sehen, ist es recht einfach, einen Klassifikator mit einer praktisch beliebigen Relevanz zu erstellen: Sie setzen einfach den Schwellenwert hoch genug und sind fertig. Moment einmal. Ein Klassifikator mit einer hohen Relevanz ist nicht sehr nützlich, wenn dessen Sensitivität zu niedrig ist!
|
Wenn jemand sagt: »Lass uns eine Relevanz von 99% erreichen«, sollten Sie fragen: »Bei welcher Sensitivität?« |
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,