AUC - ROC Kurve
AUC-ROC-Kurven in Python mit sklearn berechnen und darstellen. TPR, FPR, Schwellenwerte und wann AUC besser als Genauigkeit ist.
Die AUC-ROC-Kurve (Area Under the Receiver Operating Characteristic Curve) ist eine der wichtigsten Metriken zur Bewertung binärer Klassifikationsmodelle. Sie erfasst die Fähigkeit eines Modells, positive und negative Beispiele über jeden möglichen Entscheidungsschwellenwert hinweg zu trennen, und liefert damit ein deutlich reichhaltigeres Bild als ein einzelner Genauigkeitswert.
Dieses Kapitel behandelt:
- Was die ROC-Kurve ist und wie sie aufgebaut wird
- Wie man TPR, FPR und die dahinterstehenden Begriffe der Konfusionsmatrix liest
- Wie man AUC-ROC mit Python's
scikit-learnberechnet - Wie man die ROC-Kurve mit
matplotlibdarstellt - Wann AUC-ROC die richtige Metrik ist und wann nicht
Schlüsselbegriffe: TP, FP, TN, FN
Bevor wir uns der Kurve selbst widmen, ist es wichtig, die vier Ergebnisse zu verstehen, die ein binärer Klassifikator erzeugen kann. Bei jeder Vorhersage ist das tatsächliche Label entweder positiv (P) oder negativ (N), und das vorhergesagte Label ist entweder positiv oder negativ:
| Vorhergesagt Positiv | Vorhergesagt Negativ | |
|---|---|---|
| Tatsächlich Positiv | Richtig Positiv (TP) | Falsch Negativ (FN) |
| Tatsächlich Negativ | Falsch Positiv (FP) | Richtig Negativ (TN) |
Diese vier Zellen sind die Bausteine jeder in diesem Kapitel behandelten Bewertungsmetrik. Eine ausführlichere Einführung finden Sie im Kapitel Konfusionsmatrix.
Was ist die ROC-Kurve?
Ein Klassifikator gibt in der Regel einen Wahrscheinlichkeitswert (eine Zahl zwischen 0 und 1) aus, anstatt ein hartes Label. Sie wählen einen Schwellenwert — beispielsweise 0,5 — und alles, was über dem Schwellenwert liegt, wird als positiv vorhergesagt.
Das Verändern des Schwellenwerts verschiebt das Gleichgewicht zwischen dem Erkennen echter positiver Fälle und dem versehentlichen Markieren echter negativer Fälle:
- Ein sehr niedriger Schwellenwert erkennt mehr positive Fälle (hoher Recall), erzeugt aber auch mehr Fehlalarme.
- Ein sehr hoher Schwellenwert ist selektiv (hohe Präzision), übersieht jedoch echte positive Fälle.
Die ROC-Kurve stellt diesen Kompromiss für jeden möglichen Schwellenwert gleichzeitig dar:
- X-Achse — False Positive Rate (FPR): Welcher Anteil der tatsächlich negativen Fälle wird fälschlicherweise als positiv markiert.
- Y-Achse — True Positive Rate (TPR), auch Recall oder Sensitivität genannt: Welcher Anteil der tatsächlich positiven Fälle wird korrekt erkannt.
TPR = TP / (TP + FN) und FPR = FP / (FP + TN)
Jeder Punkt auf der ROC-Kurve entspricht einer Schwellenwerteinstellung. Zusammen zeichnen sie einen Pfad von (0, 0) — dem selektivsten Schwellenwert, der nichts als positiv vorhersagt — bis (1, 1) — dem am wenigsten selektiven Schwellenwert, der alles als positiv vorhersagt.
Was ist AUC?
Der AUC (Area Under the Curve) fasst die gesamte ROC-Kurve in einer einzigen Zahl zwischen 0 und 1 zusammen:
| AUC | Bedeutung |
|---|---|
| 1,0 | Perfekter Klassifikator — trennt jeden positiven von jedem negativen Fall |
| 0,5 | Kein Skill — entspricht zufälligem Raten |
| < 0,5 | Schlechter als zufällig (Ihre vorhergesagten Wahrscheinlichkeiten sind invertiert) |
| 0,7 – 0,8 | Akzeptabel für viele praktische Probleme |
| 0,8 – 0,9 | Gut |
| > 0,9 | Ausgezeichnet |
Intuitiv ist AUC die Wahrscheinlichkeit, dass das Modell ein zufällig gewähltes positives Beispiel höher einstuft als ein zufällig gewähltes negatives Beispiel.
AUC-ROC mit scikit-learn berechnen
Das Modul sklearn.metrics bietet roc_curve() zum Abrufen der schwellenwertweisen TPR/FPR-Werte und roc_auc_score() zum Ermitteln des einzelnen AUC-Werts.
Minimales funktionierendes Beispiel
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score, roc_curve
# 1. Create a toy binary-classification dataset
X, y = make_classification(n_samples=500, n_features=10, random_state=42)
# 2. Split into train / test sets
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42
)
# 3. Train a logistic regression model
model = LogisticRegression(random_state=42)
model.fit(X_train, y_train)
# 4. Get probability scores for the positive class (column 1)
y_proba = model.predict_proba(X_test)[:, 1]
# 5. Compute AUC
auc = roc_auc_score(y_test, y_proba)
print(f"AUC-ROC: {auc:.3f}")
# 6. Get the (fpr, tpr, thresholds) arrays for plotting
fpr, tpr, thresholds = roc_curve(y_test, y_proba)
print(f"Number of threshold points: {len(thresholds)}")Die Ausgabe wird ungefähr wie folgt aussehen:
AUC-ROC: 0.944
Number of threshold points: 30Der genaue Wert variiert leicht je nach Ihrer scikit-learn-Version, sollte aber für diesen Datensatz im Bereich 0,90–0,97 liegen.
Die ROC-Kurve darstellen
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score, roc_curve
X, y = make_classification(n_samples=500, n_features=10, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
model = LogisticRegression(random_state=42)
model.fit(X_train, y_train)
y_proba = model.predict_proba(X_test)[:, 1]
auc = roc_auc_score(y_test, y_proba)
fpr, tpr, _ = roc_curve(y_test, y_proba)
plt.figure(figsize=(7, 5))
plt.plot(fpr, tpr, color="steelblue", lw=2, label=f"ROC curve (AUC = {auc:.2f})")
plt.plot([0, 1], [0, 1], color="gray", linestyle="--", label="Random baseline (AUC = 0.50)")
plt.xlabel("False Positive Rate (FPR)")
plt.ylabel("True Positive Rate (TPR)")
plt.title("ROC Curve")
plt.legend(loc="lower right")
plt.tight_layout()
plt.savefig("roc_curve.png", dpi=120)
plt.show()Die diagonale gestrichelte Linie repräsentiert einen zufälligen Klassifikator. Je weiter die ROC-Kurve in Richtung der oberen linken Ecke ausbeult, desto besser ist das Modell.
Mehrere Modelle vergleichen
Ein gängiges Vorgehen ist es, mehrere Modelle zu trainieren und deren ROC-Kurven in derselben Grafik zu vergleichen:
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score, roc_curve
import matplotlib.pyplot as plt
X, y = make_classification(n_samples=500, n_features=10, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
models = {
"Logistic Regression": LogisticRegression(random_state=42),
"Decision Tree": DecisionTreeClassifier(max_depth=3, random_state=42),
}
plt.figure(figsize=(7, 5))
for name, clf in models.items():
clf.fit(X_train, y_train)
y_proba = clf.predict_proba(X_test)[:, 1]
fpr, tpr, _ = roc_curve(y_test, y_proba)
auc = roc_auc_score(y_test, y_proba)
plt.plot(fpr, tpr, lw=2, label=f"{name} (AUC = {auc:.2f})")
plt.plot([0, 1], [0, 1], "k--", label="Random (AUC = 0.50)")
plt.xlabel("False Positive Rate")
plt.ylabel("True Positive Rate")
plt.title("ROC Curve Comparison")
plt.legend(loc="lower right")
plt.tight_layout()
plt.savefig("roc_comparison.png", dpi=120)
plt.show()Das Modell mit der größeren Fläche unter seiner Kurve ist in der Regel die bessere Wahl für diesen Datensatz. Für einen rigorosen Modellauswahlprozess kombinieren Sie dies mit Kreuzvalidierung.
Einen Betriebspunkt wählen (Schwellenwert)
Der AUC fasst alle Schwellenwerte zusammen, aber letztendlich müssen Sie einen Schwellenwert für die Produktion auswählen. Zwei gängige Strategien:
1. Youdens J-Statistik
Youdens J maximiert TPR − FPR und findet den einzelnen Punkt auf der ROC-Kurve, der am weitesten von der Diagonalen entfernt ist:
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_curve
import numpy as np
X, y = make_classification(n_samples=500, n_features=10, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
model = LogisticRegression(random_state=42)
model.fit(X_train, y_train)
y_proba = model.predict_proba(X_test)[:, 1]
fpr, tpr, thresholds = roc_curve(y_test, y_proba)
j_scores = tpr - fpr
best_idx = int(np.argmax(j_scores))
best_threshold = thresholds[best_idx]
print(f"Best threshold (Youden's J): {best_threshold:.3f}")
print(f"TPR at best threshold: {tpr[best_idx]:.3f}")
print(f"FPR at best threshold: {fpr[best_idx]:.3f}")2. Geschäftlich motivierter Schwellenwert
Bei der Betrugserkennung kann man mehr falsch positive Ergebnisse tolerieren, um mehr Betrug zu erkennen (niedrigerer Schwellenwert). Bei medizinischen Screenings möchte man möglicherweise sehr wenige falsch negative Ergebnisse (ebenfalls niedrigerer Schwellenwert). Die Wahl des Schwellenwerts ist letztlich eine Geschäftsentscheidung, die durch die Kosten jedes Fehlertyps bestimmt wird.
AUC-ROC vs. andere Metriken
| Metrik | Am besten, wenn... | Achtung bei... |
|---|---|---|
| Accuracy | Klassen ausgewogen sind | Irreführend bei unausgewogenen Datensätzen |
| Precision / Recall | Man sich hauptsächlich um eine Klasse kümmert | Erfordert einen Schwellenwert |
| F1-Score | Harmonisches Gleichgewicht zwischen Precision und Recall | Noch schwellenwertabhängig |
| AUC-ROC | Modelle vergleichen oder Schwellenwerte anpassen | Nicht aussagekräftig für mehrere Klassen ohne Erweiterung |
| AUC-PR (Precision-Recall AUC) | Starke Klassenungleichgewichte (seltene positive Fälle) | Weniger intuitiv als ROC |
Bei stark unausgewogenen Daten — etwa 1 % positive Fälle — ist die AUC-PR-Kurve (Precision vs. Recall) oft informativer als die AUC-ROC, da FPR klein erscheinen kann, auch wenn viele negative Fälle falsch markiert werden.
Häufige Fallstricke
Harte Labels anstelle von Wahrscheinlichkeiten übergeben. roc_auc_score benötigt Wahrscheinlichkeitswerte, keine 0/1-Labels. Verwenden Sie model.predict_proba(X_test)[:, 1], nicht model.predict(X_test).
Vergessen, die positive Klasse anzugeben. Standardmäßig behandeln roc_curve und roc_auc_score das größere Integer-Label als positiv. Übergeben Sie explizit pos_label=1, wenn Ihre Labels keine 0/1-Integer sind.
Überanpassung an AUC auf dem Trainingsset. Bewerten Sie immer auf einem zurückgehaltenen Testset oder verwenden Sie Kreuzvalidierung, um eine zuverlässige AUC-Schätzung zu erhalten. Das Kapitel Grid Search zeigt, wie man scoring='roc_auc' direkt an GridSearchCV übergibt.
AUC ≈ 0,5 bedeutet nicht immer, dass das Modell schlecht ist. Es kann bedeuten, dass sich positive und negative Beispiele im Merkmalsraum wirklich überlappen, oder dass Ihre Merkmale für die Aufgabe nicht informativ sind.
Praktisches Beispiel: Krankheitsvorhersage
Das folgende End-to-End-Beispiel verwendet den Brustkrebs-Datensatz, der mit scikit-learn ausgeliefert wird:
from sklearn.datasets import load_breast_cancer
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import roc_auc_score, roc_curve
import matplotlib.pyplot as plt
# Load dataset (569 samples, 30 features, binary labels: malignant=0 / benign=1)
data = load_breast_cancer()
X, y = data.data, data.target
# Scale features — important for logistic regression
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
X_train, X_test, y_train, y_test = train_test_split(
X_scaled, y, test_size=0.2, random_state=42, stratify=y
)
classifiers = {
"Logistic Regression": LogisticRegression(max_iter=1000, random_state=42),
"Random Forest": RandomForestClassifier(n_estimators=100, random_state=42),
}
plt.figure(figsize=(7, 5))
for name, clf in classifiers.items():
clf.fit(X_train, y_train)
y_proba = clf.predict_proba(X_test)[:, 1]
auc = roc_auc_score(y_test, y_proba)
fpr, tpr, _ = roc_curve(y_test, y_proba)
plt.plot(fpr, tpr, lw=2, label=f"{name} (AUC = {auc:.3f})")
plt.plot([0, 1], [0, 1], "k--", label="Random (AUC = 0.50)")
plt.xlabel("False Positive Rate")
plt.ylabel("True Positive Rate")
plt.title("ROC Curve — Breast Cancer Dataset")
plt.legend(loc="lower right")
plt.tight_layout()
plt.savefig("breast_cancer_roc.png", dpi=120)
plt.show()Beide Klassifikatoren sollten bei diesem Datensatz AUC-Werte über 0,98 erzielen, was bestätigt, dass die Brustkrebs-Merkmale hoch prädiktiv sind.
Verwandte Themen
- Konfusionsmatrix — die TP/FP/TN/FN-Bausteine, die in diesem Kapitel verwendet werden
- Logistische Regression — das häufigste Modell, das mit der AUC-ROC-Bewertung kombiniert wird
- Kreuzvalidierung — wie man zuverlässige AUC-Schätzungen erhält, die über eine einzelne Trainings-/Testaufteilung hinaus verallgemeinern
- Grid Search — wie man Hyperparameter mit
scoring='roc_auc'abstimmt - Entscheidungsbaum — ein weiterer binärer Klassifikator, dessen Wahrscheinlichkeitsausgaben mit AUC-ROC bewertet werden können
Zusammenfassung
| Konzept | Kernaussage |
|---|---|
| ROC-Kurve | Stellt TPR vs. FPR bei jedem Entscheidungsschwellenwert dar |
| AUC | Fläche unter der ROC-Kurve; 1,0 = perfekt, 0,5 = zufällig |
roc_auc_score | Wahrscheinlichkeitswerte übergeben, keine harten Labels |
roc_curve | Gibt (fpr, tpr, thresholds)-Arrays zum Darstellen zurück |
| Schwellenwertauswahl | Youdens J oder Domänenwissen verwenden, um einen Produktionsschwellenwert zu wählen |
| Wann AUC-PR bevorzugt wird | Stark unausgewogene Datensätze mit seltenen positiven Fällen |
AUC-ROC gibt Ihnen eine einzige, schwellenwertunabhängige Zahl, die die diskriminative Fähigkeit Ihres Modells über alle Betriebspunkte zusammenfasst. Verwenden Sie sie, um Modelle zu vergleichen, Hyperparameter abzustimmen und die Qualität von Klassifikatoren zu kommunizieren — wählen Sie dann den spezifischen Schwellenwert, der zur Toleranz Ihrer Anwendung gegenüber falsch positiven und falsch negativen Ergebnissen passt.