ML Atlas

Machine Learning von Grund auf · Lektion 2.5 · 12 von 33 fertigen Lektionen · 12 Min.

Unausgewogene Klassen

Kurz gesagt

Ist eine Klasse selten, verdeckt die Genauigkeit Verluste, und das Modell lernt „die häufige Klasse“ zu sagen. Sensitivität und Gewichte zeigen und flicken das.

Aufwärmen Zwei Fragen aus früheren Lektionen. Eine Minute, und sie blockiert die Lektion nicht.
Aus Lektion 2.4: Kalibrierung: Heißt 0,8 auch 80 %? Naive Bayes hat ROC AUC 0,966, erklärt aber 98,3 % bei einer Genauigkeit von 88,3 %. Was folgt daraus?

Antwort anzeigen

Richtige Antwort: Es sortiert die Biopsien gut, aber seine Prozente sind aufgebläht

ROC AUC misst die Reihenfolge, Kalibrierung die Prozente. Das sind zwei verschiedene Dinge: Die Temperatur repariert die Prozente von Naive Bayes, und ROC AUC bleibt 0,966.

Aus Lektion 2.3: Schwelle, ROC und PR: alle Schwellen auf einmal Wann sagt die PR-Kurve mehr als die ROC-Kurve?

Antwort anzeigen

Richtige Antwort: Wenn die positive Klasse selten ist und zählt, wie viele Alarme richtig sind

Bei einer seltenen Klasse sieht die ROC-Kurve gleich aus, während die Präzision fällt. Im Labor mit 19 bösartigen fällt AP auf im Mittel 0,137, obwohl ROC AUC fast stillsteht.

In Lektion 1.3 hatte „immer gutartig“ eine hohe Genauigkeit und fand niemanden. Dort war die seltene Klasse nur im Test selten. Heute ist sie in den Lerndaten selten, wie beim echten Screening, bei Betrug oder bei Ausfällen. Du siehst, was das mit dem Modell macht, wie man es misst und was sich ohne neue Daten reparieren lässt.

Erst vorhersagen, dann prüfen Eine logistische Regression lernt aus Biopsien. In den Lerndaten bleiben alle gutartigen, aber nur 8 statt 159 bösartige. Was fällt auf demselben Validierungsteil (zum Prüfen des Modells beiseitegelegt, nicht zum Lernen) stärker: die Genauigkeit oder die Sensitivität?
Wie sicher bist du?

Interaktives Labor

Dieses interaktive Labor läuft im Browser mit aktiviertem JavaScript. Der Text drumherum beschreibt, was es zeigt.

Antwort anzeigen

Richtige Antwort: Die Sensitivität, um mehr als 20 Punkte, die Genauigkeit nur um etwa 6

Die Sensitivität fällt von 83,0 % auf 61,5 % (Mittel aus 5 Ziehungen, welche bösartigen bleiben), die Genauigkeit nur von 91,5 % auf 85,6 %. In der Validierung sind 89 der 142 Biopsien gutartig, und die erkennt das Modell immer sicherer, also sieht die Genauigkeit den Verlust kaum.

Probier es aus

  • Bewege ohne Gewichte den Regler von 159 auf 8 bösartige. Welche Linie fällt schneller: Sensitivität oder Genauigkeit?
  • Schalte bei 8 bösartigen die Klassengewichte ein. Wie viel Sensitivität kommt zurück, und wie viel fehlt noch im Vergleich zu allen Daten?
  • Schau auf die mittlere vorhergesagte P(bösartig). Wie ändert sie sich, wenn bösartige verschwinden?

Wenn du es im Labor geprüft hast, benennen wir, was du siehst.

Die Idee in einfachen Worten

Klassen sind unausgewogen, wenn eine viel seltener ist als die andere. Das Modell lernt dann zwei Dinge auf einmal: wie bösartige Biopsien aussehen und wie selten sie vorkommen. Die zweite Lektion wirkt wie ein Vorurteil: Sind die Messwerte unklar, wählt das Modell immer öfter „gutartig“. Die mittlere vorhergesagte P(bösartig) fällt von 0,36 auf 0,24, wenn 8 statt 159 bösartige zum Lernen bleiben.

Die Genauigkeit sieht das kaum. Die Sensitivität fällt von 83,0 % auf 61,5 %, die Genauigkeit nur von 91,5 % auf 85,6 %. Deshalb berichtet man bei einer seltenen Klasse die Sensitivität der seltenen Klasse oder die balancierte Genauigkeit, den Mittelwert der Sensitivitäten beider Klassen. „Immer gutartig“ hat eine balancierte Genauigkeit von 0,5, egal bei welchen Anteilen.

Die erste Korrektur ist einfach: Klassengewichte. Ein Fehler bei der seltenen Klasse kostet beim Lernen so viel mehr, wie die Klasse seltener ist (class_weight='balanced'). Bei 8 bösartigen heben die Gewichte die Sensitivität von 61,5 % auf 80,0 %, und die Genauigkeit steigt sogar, auf 91,4 %. Zu allen Daten mit Gewichten (86,8 %) fehlt trotzdem etwas: Gewichte ändern die Anteile, sie fügen keine Beispiele hinzu.

Jak to policzono
  • Biopsien: Breast Cancer Wisconsin (Diagnostic), UCI, Lizenz CC BY 4.0. 569 Biopsien, 10 „mean“-Messwerte.
  • Validierungsteil: 25 % der Biopsien, stratifiziert (142: 53 bösartig, 89 gutartig), in jeder Einstellung derselbe. Zum Lernen 268 gutartige und 159 bis 8 bösartige; unter 159 ist es das Mittel aus 5 Ziehungen, welche bösartigen bleiben.
  • Modell: Standardisierung auf den Lerndaten und logistische Regression (C = 1), mit oder ohne Klassengewichte; Schwelle 0,5.

Warum es funktioniert

Die logistische Regression sucht das Modell, das sich auf den Lerndaten im Mittel am wenigsten irrt. Bei 268 gutartigen und 8 bösartigen sind die bösartigen nur 2,9 % der gesamten Strafe. Das Modell schiebt die Grenze zur bösartigen Seite: Es gibt ein paar bösartige auf, um gutartige seltener falsch einzuordnen. Klassengewichte gleichen die Strafe aus: Die 8 bösartigen wiegen zusammen so viel wie die 268 gutartigen.

Eine Aufteilung könnte zufällig so ausfallen. Im Code unten läuft dasselbe Experiment auf 50 verschiedenen Aufteilungen: Die Sensitivität fällt im Mittel von 89,3 % auf 67,3 %, die Genauigkeit von 93,5 % auf 87,7 %, und die Gewichte geben bei 8 bösartigen 84,0 %. Die Sensitivität fällt in 50 von 50 Aufteilungen stärker als die Genauigkeit, und die Gewichte heben sie in jeder davon.

Die Genauigkeit kann sogar steigen, während sich das Modell gar nicht ändert. Im Atlas-Widget zur balancierten Genauigkeit bewertet ein schwaches Modell mit zwei Messwerten dieselben Biopsien, während die bösartigen von 212 auf 20 sinken. Seine Genauigkeit steigt von 75,9 % auf 83,8 %, die balancierte Genauigkeit bleibt stehen: 0,728 und 0,726. „Immer gutartig“ kommt bei 20 bösartigen auf ganze 94,7 % Genauigkeit.

Häufiger Fehler

Richtig oder falsch: „SMOTE hilft immer.“ Falsch. SMOTE erzeugt synthetische Beispiele der seltenen Klasse auf den Strecken zwischen echten Beispielen und ihren nächsten Nachbarn, bis beide Klassen gleich groß sind. Das verschiebt die Entscheidungsgrenze genauso wie Klassengewichte: Das Modell sagt öfter „bösartig“. Im Atlas-Widget zu SMOTE (357 gutartige, 30 bösartige, zwei Messwerte, Kreuzvalidierung 5 × 5) findet das Modell ohne Korrektur 60,0 % der bösartigen bei einer Präzision von 90,0 %. SMOTE hebt die Erkennung auf 86,7 %, aber die Präzision fällt auf 42,9 %. Klassengewichte geben dieselbe Sensitivität bei einer Präzision von 40,2 %, einfaches Duplizieren bei 39,6 %. Das ist eine Ziehung von 30 bösartigen, die mit dem größten Abfall: Im Mittel über 20 Ziehungen steigt die Erkennung von 68,7 % auf 91,9 %, und die Präzision fällt von 91,0 % auf 54,7 %. Sie fällt in jeder davon. SMOTE fügt kein Wissen hinzu, es ändert nur die Anteile. Ob das hilft, hängt von den Kosten der Fehler ab: mehr Gefundene zum Preis vieler Fehlalarme.

Eine Warnung: Die Korrektur gehört nur auf die Lerndaten. Synthetische oder duplizierte Beispiele in Validierung oder Test ergäben ein Ergebnis, das nichts bedeutet.

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.

1. Statt 159 bleiben 8 bösartige Biopsien zum Lernen. Warum zeigt die Genauigkeit das kaum?
Antwort anzeigen

Richtige Antwort: Weil in der Validierung gutartige überwiegen und das Modell sie immer sicherer erkennt

In der Validierung sind 89 der 142 Biopsien gutartig. Die Sensitivität fällt von 83,0 % auf 61,5 %, die Genauigkeit nur von 91,5 % auf 85,6 %.

2. Was misst die balancierte Genauigkeit?
Antwort anzeigen

Richtige Antwort: Den Mittelwert der Sensitivitäten beider Klassen, also bekommt „immer häufig“ genau 0,5

Jede Klasse zählt gleich, egal wie groß sie ist. Das schwache Modell des Widgets hat eine balancierte Genauigkeit von 0,728 bei 212 bösartigen und 0,726 bei 20, obwohl seine Genauigkeit von 75,9 % auf 83,8 % steigt.

3. Bei 8 bösartigen zum Lernen heben Klassengewichte die Sensitivität von 61,5 % auf 80,0 %. Was tun sie nicht?
Antwort anzeigen

Richtige Antwort: Sie fügen keine neuen Beispiele hinzu, also fehlt zu allen Daten noch etwas

Gewichte ändern nur, wie viel ein Fehler bei jeder Klasse kostet. Alle Daten mit Gewichten ergeben eine Sensitivität von 86,8 %, bei 8 bösartigen fehlen also 6,8 Prozentpunkte.

Das Wichtigste

  • Ist eine Klasse selten, verdeckt die Genauigkeit die Verluste: Berichte die Sensitivität der seltenen Klasse oder die balancierte Genauigkeit.
  • Ein Modell lernt auch die Anteile der Klassen; mit einer seltenen Klasse in den Lerndaten wählt es immer öfter die häufige.
  • Klassengewichte und SMOTE verschieben die Grenze: mehr Gefundene zum Preis von Fehlalarmen, ohne neues Wissen.
  • Wende Korrekturen nur auf die Lerndaten an und prüfe das Ergebnis auf unberührter Validierung, am besten über viele Aufteilungen.

Tiefer: Formel, Code, Praxis

Die Mathematik

Genauigkeit = (TP + TN) / n, Sensitivität = TP / (TP + FN), Spezifität = TN / (TN + FP), balancierte Genauigkeit = (Sensitivität + Spezifität) / 2. „Immer gutartig“ hat Sensitivität 0 und Spezifität 1, also eine balancierte Genauigkeit von (0 + 1) / 2 = 0,5.

Die logistische Regression minimiert den mittleren logistischen Verlust L = Σᵢ wᵢ · ℓ(yᵢ, pᵢ) / Σᵢ wᵢ. Ohne Gewichte ist wᵢ = 1, also sind die 8 bösartigen 8 / 276 ≈ 2,9 % des gesamten Verlusts. Die „balanced“-Gewichte sind w = n / (2 · n_Klasse): 276 / 16 = 17,25 für eine bösartige und 276 / 536 ≈ 0,51 für eine gutartige, also wiegt jede Klasse insgesamt n / 2 = 138.

Im Code (Python)

Dasselbe Experiment in scikit-learn auf 50 verschiedenen Aufteilungen: alle gutartigen und 159 oder 8 bösartige zum Lernen, mit und ohne Klassengewichte, bewertet auf dem unberührten Validierungsteil.

import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import recall_score, accuracy_score

X, y = load_breast_cancer(return_X_y=True)
X, y = X[:, :10], 1 - y  # die 10 „mean“-Messwerte, wie im Labor; 1 = bösartig
def run(seed, m, weights):
    tr, va = train_test_split(np.arange(len(y)), test_size=0.25, stratify=y, random_state=seed)
    mal = np.random.default_rng(seed).choice(tr[y[tr] == 1], m, replace=False)
    keep = np.r_[tr[y[tr] == 0], mal]  # alle gutartigen + m bösartige zum Lernen
    clf = make_pipeline(StandardScaler(), LogisticRegression(class_weight="balanced" if weights else None))
    pred = clf.fit(X[keep], y[keep]).predict(X[va])  # der Validierungsteil ändert sich nie
    return recall_score(y[va], pred), accuracy_score(y[va], pred)
for m, w in ((159, False), (8, False), (8, True)):
    rec, acc = np.mean([run(s, m, w) for s in range(50)], axis=0)
    print(f"{m} malignant{' + class weights' if w else ''}: recall {rec:.1%}, accuracy {acc:.1%} (mean of 50 splits)")
drop = np.array([np.subtract(run(s, 159, False), run(s, 8, False)) for s in range(50)])
gain = np.array([run(s, 8, True)[0] - run(s, 8, False)[0] for s in range(50)])
print(f"recall fell more than accuracy in {(drop[:, 0] > drop[:, 1]).sum()} of 50 splits; weights raised recall in {(gain > 0).sum()}")

Ausgabe

159 malignant: recall 89.3%, accuracy 93.5% (mean of 50 splits)
8 malignant: recall 67.3%, accuracy 87.7% (mean of 50 splits)
8 malignant + class weights: recall 84.0%, accuracy 91.0% (mean of 50 splits)
recall fell more than accuracy in 50 of 50 splits; weights raised recall in 50

Das Labor zeigt eine Aufteilung und 5 Ziehungen, der Code 50 Aufteilungen, also sind die Zahlen andere: Auf der Aufteilung des Labors beträgt die Sensitivität mit allen Daten 83,0 %, im Mittel 89,3 %. Die Schlussfolgerung ist in jeder Aufteilung dieselbe.

Für die Praxis
  • In scikit-learn kommen Gewichte von class_weight="balanced" (logistische Regression, SVM, Bäume, Wälder) und die balancierte Genauigkeit von balanced_accuracy_score. Berichte auch Sensitivität und Präzision der seltenen Klasse.
  • Teile stratifiziert (stratify=y, StratifiedKFold), damit die seltene Klasse in jedem Teil landet.
  • SMOTE und Duplizieren gibt es in der Bibliothek imbalanced-learn. Nutze sie in deren Pipeline, damit sie in der Kreuzvalidierung nur auf die Lernteile wirken.
  • Klassengewichte und eine niedrigere Schwelle tun etwas Ähnliches: Sie verschieben die Entscheidung zur seltenen Klasse. Die Schwelle kannst du in der Validierung anhand der PR-Kurve wählen (Lektion 2.3), ohne das Modell neu zu trainieren.

Mehr im Atlas

Einträge der Enzyklopädie zu den Ideen dieser Lektion: