Machine Learning von Grund auf · Lektion 2.3 · 10 von 33 fertigen Lektionen · 12 Min.
Schwelle, ROC und PR: alle Schwellen auf einmal
Kurz gesagt
ROC- und Precision-Recall-Kurven zeigen alle Schwellen zugleich. Ist eine Klasse selten, bleibt ROC AUC fast gleich, AP fällt: Fehlalarme fressen Präzision.
Aufwärmen Zwei Fragen aus früheren Lektionen. Eine Minute, und sie blockiert die Lektion nicht.
In Lektion 2.2 hast du eine Schwelle verschoben und zugesehen, wie sich die Konfusionsmatrix ändert. Jede Schwelle ist eine andere Entscheidung, obwohl die Werte des Modells gleich bleiben. Heute siehst du alle Schwellen auf einmal, auf zwei Kurven: ROC und Precision-Recall (PR). Du prüfst auch, welche von beiden die Wahrheit sagt, wenn es nur wenige Kranke gibt. Das Modell ist absichtlich schwach: eine logistische Regression, die nur einen Messwert sieht, die mittlere Textur des Tumors, damit die Kurven nicht an den Ecken kleben.
Wähle eine Antwort und wie sicher du bist.
Antworte, um das Labor freizuschalten.
Interaktives Labor
Dieses interaktive Labor läuft im Browser mit aktiviertem JavaScript. Der Text drumherum beschreibt, was es zeigt.
Antwort anzeigen
Richtige Antwort: ROC AUC ändert sich kaum (etwa 0,77), während AP auf etwa 0,14 fällt
ROC AUC beträgt 0,773 mit allen bösartigen und im Mittel 0,772 mit 19 (über 200 Ziehungen, welche bösartigen bleiben). AP fällt von 0,591 auf im Mittel 0,137. Das Modell hat nichts vergessen; nur die Anteile der Klassen haben sich geändert. ROC sieht das nicht, die PR-Kurve schon.
Probier es aus
- Beginne mit 212 bösartigen und der Schwelle 0,5. Lies Sensitivität und FPR ab und verschiebe die Schwelle dann auf 0,3. In welche Richtung wandert der Punkt auf beiden Kurven?
- Wechsle bei der Schwelle 0,3 zu 19 bösartigen. Es gibt genauso viele Fehlalarme wie eben. Was ist mit der Präzision passiert?
- Vergleiche ROC AUC und AP bei 212, 40 und 19 bösartigen.
Wenn du es im Labor geprüft hast, benennen wir, was du siehst.
Die Idee in einfachen Worten
Das Modell sagt nicht „bösartig“ oder „gutartig“. Es gibt einen Wert von 0 bis 1, und eine Schwelle trifft die Entscheidung. Jede Schwelle ergibt ein anderes Zahlenpaar: wie viele bösartige gefunden wurden (Sensitivität) und wie viele gutartige einen Fehlalarm bekamen. Die ROC-Kurve zeichnet diese Paare für alle Schwellen auf einmal: waagerecht der Anteil der Fehlalarme unter den gutartigen (FPR), senkrecht die Sensitivität. Eine hohe Schwelle ist die linke untere Ecke (wenige Alarme), eine niedrige die rechte obere (Alarm bei jeder Biopsie).
Die Precision-Recall-Kurve (PR) zeigt dieselben Schwellen anders: waagerecht die Sensitivität, senkrecht die Präzision, also welcher Teil der Alarme richtig ist. Die Fläche unter der ROC-Kurve ist ROC AUC, die Fläche unter der PR-Kurve ist AP (average precision). Jede dieser Zahlen fasst alle Schwellen auf einmal zusammen und hängt daher nicht davon ab, welche Schwelle du wählst.
Auf allen 569 Biopsien hat das Modell ROC AUC 0,773 und AP 0,591. Zufälliges Raten ergäbe ROC AUC 0,5 und ein AP gleich dem Anteil bösartiger Biopsien, also 0,373. Das Modell ist klar besser als Raten, aber weit vom Ideal entfernt, das 1 ist.
Jak to policzono
- Biopsien: Breast Cancer Wisconsin (Diagnostic), UCI, Lizenz CC BY 4.0. 569 Biopsien (357 gutartig, 212 bösartig). Das Modell sieht einen Messwert: die mittlere Textur des Tumors.
- Werte aus einer Kreuzvalidierung mit 5 Teilen (
StratifiedKFold(5)in scikit-learn): Jede Biopsie bewertet ein Modell, das sie nie gesehen hat. - Seltenere Klasse: Alle 357 gutartigen bleiben, dazu 40 oder 19 zufällig gezogene bösartige. Das Diagramm zeigt eine Ziehung; die Mittelwerte stammen aus 200 Ziehungen.
- Modell: Standardisierung und logistische Regression (C = 1).
Warum es funktioniert
ROC zählt Fehlalarme gegen die gutartigen: FPR ist die Zahl der Fehlalarme geteilt durch 357. Die Sensitivität zählt Treffer gegen die bösartigen. Nimmst du bösartige Biopsien zufällig weg, bleiben beide Brüche ungefähr gleich, also bewegen sich die ROC-Kurve und ihre Fläche kaum. Bei der Schwelle 0,3 schlägt das Modell bei 144 von 357 gutartigen Alarm (FPR 40,3 %), ob es 212 bösartige gibt oder 19.
Die Präzision zählt Fehlalarme gegen alle Alarme. Bei 212 bösartigen und der Schwelle 0,3 findet das Modell 177, die Präzision beträgt also 55,1 %. Bei 19 bösartigen findet es 17, und die 144 Fehlalarme bleiben: Die Präzision fällt auf 10,6 %, also 8,5 Fehlalarme pro richtigem Alarm. Die PR-Kurve fällt mit der Präzision, und AP von 0,591 auf im Mittel 0,137. Die Linie des zufälligen Ratens bei PR fällt ebenfalls, auf den Anteil bösartiger: 0,051.
Das ist kein Zufall einer Ziehung oder einer Aufteilung in Teile. Bei 40 bösartigen (10 %) beträgt ROC AUC im Mittel 0,773 und AP 0,232. Im Code unten hat dasselbe Modell auf 20 anderen Aufteilungen bei 19 bösartigen jedes Mal ein AP unter der Hälfte des AP mit allen Daten.
Häufiger Fehler
Richtig oder falsch: „Ein hohes ROC AUC bedeutet wenige Fehlalarme.“ Falsch. ROC AUC misst, wie gut das Modell sortiert: die Wahrscheinlichkeit, dass eine zufällige bösartige Biopsie einen höheren Wert bekommt als eine zufällige gutartige. Es sagt nicht, wie viele Alarme falsch sein werden, denn das hängt davon ab, wie selten die Klasse ist. Im Labor beträgt ROC AUC bei 19 bösartigen im Mittel 0,772, fast so viel wie bei 212, und bei der Schwelle 0,3 kommen 8,5 Fehlalarme auf einen richtigen. Ist die Klasse selten, schau auf die PR-Kurve und auf die Präzision bei der Schwelle, die du wirklich verwenden wirst.
Eine Warnung in die andere Richtung: Auch AP ist keine Zahl „nur über das Modell“. Es hängt vom Anteil der Klasse in den Daten ab, deshalb lassen sich die AP zweier Datensätze mit verschiedenen Anteilen nicht direkt vergleichen. Vergleiche AP mit der Linie des zufälligen Ratens auf denselben Daten.
Quiz
Drei Fragen zur Selbstkontrolle. Wähle eine Antwort oder klappe die Lösung unter der Frage auf. Mit der Tastatur: Pfeiltasten wählen, Enter oder Leertaste bestätigt.
Das Wichtigste
- Die ROC-Kurve und die PR-Kurve zeigen alle Schwellen auf einmal; die Schwelle wählst du danach, nach den Kosten der Fehler.
- ROC AUC misst, wie gut das Modell sortiert, und hängt kaum von den Anteilen der Klassen ab.
- Ist die positive Klasse selten, fressen dieselben Fehlalarme die Präzision: Schau auf die PR-Kurve und AP.
- Vergleiche AP mit der Linie des zufälligen Ratens, also dem Anteil der positiven Klasse in denselben Daten.
Tiefer: Formel, Code, Praxis
Die Mathematik
Bei der Schwelle t sagt das Modell „bösartig“, wenn sein Wert s ≥ t. Dann gilt Sensitivität = TP / (TP + FN), FPR = FP / (FP + TN), Präzision = TP / (TP + FP).
Die FPR hat im Nenner nur gutartige, die Sensitivität nur bösartige. Nimmst du bösartige zufällig weg, ändert sich keiner der beiden Brüche systematisch, also bleibt die ROC-Kurve. Die Präzision hat beide Arten von Alarmen im Nenner. Bei der Schwelle 0,3: 177 / (177 + 144) ≈ 0,551 bei 212 bösartigen und 17 / (17 + 144) ≈ 0,106 bei 19.
ROC AUC ist die Wahrscheinlichkeit, dass eine zufällige bösartige Biopsie einen höheren Wert bekommt als eine zufällige gutartige: AUC = P(s₊ > s₋), Gleichstände zählen halb. AP ist die mittlere Präzision, gewichtet mit den Schritten der Sensitivität: AP = Σₖ (Rₖ − Rₖ₋₁) · Pₖ. Zufällige Werte ergeben AUC 0,5 und ein AP gleich dem Anteil der positiven Klasse: 212 / 569 ≈ 0,373 oder 19 / 376 ≈ 0,051.
Im Code (Python)
Dasselbe Experiment in scikit-learn: Werte aus der Kreuzvalidierung, ROC AUC und AP bei 212, 40 und 19 bösartigen (Mittel aus 1000 Ziehungen), dann dasselbe auf 20 anderen Aufteilungen.
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import StratifiedKFold, cross_val_predict
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_auc_score, average_precision_score
X, y = load_breast_cancer(return_X_y=True)
X, y = X[:, [1]], 1 - y # nur die mittlere Textur, wie im Labor; 1 = bösartig
model = make_pipeline(StandardScaler(), LogisticRegression())
def scores(cv): # Validierungswerte: Jede Biopsie bewertet ein Modell, das sie nie gesehen hat
return cross_val_predict(model, X, y, cv=cv, method="predict_proba")[:, 1]
ben, mal = np.flatnonzero(y == 0), np.flatnonzero(y == 1)
def rare(p, keep, draws, seed): # alle 357 gutartigen + `keep` zufällige bösartige, Mittel über die Ziehungen
rng = np.random.default_rng(seed)
rows = [np.r_[ben, rng.choice(mal, keep, replace=False)] for _ in range(draws)]
return np.mean([(roc_auc_score(y[i], p[i]), average_precision_score(y[i], p[i])) for i in rows], axis=0)
p = scores(StratifiedKFold(5))
print(f"212 malignant ({212 / 569:.0%}): ROC AUC {roc_auc_score(y, p):.3f}, AP {average_precision_score(y, p):.3f}")
for keep in (40, 19):
auc, ap = rare(p, keep, 1000, 0)
print(f"{keep} malignant ({keep / (357 + keep):.0%}), mean of 1000 draws: ROC AUC {auc:.3f}, AP {ap:.3f}")
r = []
for s in range(20): # 20 andere Arten, die Daten in 5 Teile zu schneiden
q = scores(StratifiedKFold(5, shuffle=True, random_state=s))
r.append([roc_auc_score(y, q), average_precision_score(y, q), *rare(q, 19, 200, s)])
r = np.array(r)
print(f"20 other fold splits, 212 -> 19 malignant: ROC AUC {r[:, 0].mean():.3f} -> {r[:, 2].mean():.3f}, AP {r[:, 1].mean():.3f} -> {r[:, 3].mean():.3f}; AP below half in {(r[:, 3] < r[:, 1] / 2).sum()} of 20")
Ausgabe
212 malignant (37%): ROC AUC 0.773, AP 0.591
40 malignant (10%), mean of 1000 draws: ROC AUC 0.773, AP 0.231
19 malignant (5%), mean of 1000 draws: ROC AUC 0.774, AP 0.140
20 other fold splits, 212 -> 19 malignant: ROC AUC 0.774 -> 0.775, AP 0.595 -> 0.140; AP below half in 20 of 20
Mit allen bösartigen sind die Zahlen dieselben wie im Labor. Bei 40 und 19 zieht der Code die bösartigen anders als das Labor und macht 1000 Ziehungen statt 200, deshalb unterscheiden sich die Mittelwerte in der dritten Nachkommastelle: AP 0,140 statt 0,137. Auf 20 anderen Aufteilungen ist das Bild dasselbe: ROC AUC bleibt, und AP fällt jedes Mal unter die Hälfte.
Notebook herunterladen (.ipynb). Öffne es in Jupyter oder lade es in Google Colab hoch; fehlende Daten lädt es selbst.
Für die Praxis
- In scikit-learn liefern
roc_auc_scoreundaverage_precision_scoredie Zahlen, undRocCurveDisplayundPrecisionRecallDisplayzeichnen die Kurven. Berechne sie auf Validierungswerten (cross_val_predict(..., method="predict_proba")), nicht auf den Lerndaten. - Bei einer seltenen Klasse (Betrug, seltene Krankheiten, Ausfälle) berichte AP neben ROC AUC und neben AP die Linie des zufälligen Ratens, also den Anteil der positiven Klasse.
- Eine Kurve ist eine Speisekarte von Schwellen. Wähle die Schwelle in der Validierung nach den Kosten der Fehler, zum Beispiel „Sensitivität mindestens 90 % bei höchstmöglicher Präzision“, und prüfe sie erst danach auf dem Testdatensatz.
- Das ROC AUC zweier Datensätze mit verschiedenen Anteilen lässt sich vergleichen, sagt aber nicht, wie viele Alarme falsch sein werden; AP sagt darüber mehr, aber vergleiche es nur bei gleichen Anteilen.
War das hilfreich?
Danke! Das hilft uns, besser zu werden.
Mehr im Atlas
Einträge der Enzyklopädie zu den Ideen dieser Lektion: