Machine Learning von Grund auf · Lektion 1.4 · 5 von 33 fertigen Lektionen · 12 Min.
Nächste Nachbarn: das einfachste Modell
Kurz gesagt
kNN lernt keine Regel: Ein neuer Fall bekommt das Label der Mehrheit seiner k nächsten Beispiele. k formt die Grenzen, die Einheiten bestimmen, wer nah ist.
Aufwärmen Zwei Fragen aus früheren Lektionen. Eine Minute, und sie blockiert die Lektion nicht.
Die einfachste Idee für ein Modell lautet: Ähnliche Fälle haben ähnliche Antworten. Um einen neuen Pinguin zu erkennen, such die k Lernpinguine, die ihm am ähnlichsten sind, und frag, welche Art sie sind. Das ist die Methode der k nächsten Nachbarn (englisch k-nearest neighbours, kNN). Wir kehren zu den Pinguinen aus Lektion 0.1 zurück, diesmal nur mit zwei Messwerten: Schnabellänge und Körpermasse.
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: Es erkennt weniger, im Mittel weniger als kNN mit 9 Nachbarn
Auf den Lernpinguinen erreicht k = 1 100 %, auf den Testpinguinen 94,2 % in Aufteilung 1. Im Mittel über 100 Aufteilungen trifft k = 1 92,2 % und k = 9 94,2 %; k = 9 gewinnt in 78 Aufteilungen und verliert in 9. Ein einzelner Nachbar kopiert jede Ausnahme, die Abstimmung von 9 Nachbarn mittelt sie weg.
Probier es aus
- Das Labor startet in rohen Einheiten, Millimetern und Gramm, bei k = 1. Wechsle zu standardisierten Einheiten: Was passiert mit den Grenzen und dem Ergebnis?
- Noch bei k = 1: Schau dir die Grenzen zwischen den Arten an. Wo sind sie ausgefranst?
- Erhöhe k. Bei welchem k glätten sich die Grenzen, bei welchem fällt das Testergebnis deutlich?
- Vergleiche die letzte Zeile, das Mittel über 20 Aufteilungen, für k = 1 und k = 9.
Wenn du es im Labor geprüft hast, benennen wir, was du siehst.
Die Idee in einfachen Worten
kNN baut überhaupt keine Regel. „Lernen“ heißt, die 239 Lernpinguine zu speichern. Die ganze Arbeit passiert erst bei einer Frage: Für einen neuen Pinguin berechnet das Modell den Abstand zu jedem gespeicherten, nimmt die k nächsten und lässt die Mehrheit entscheiden. Der Hintergrund im Labor ist genau diese Antwort an jedem Punkt des Diagramms.
Die Zahl k legt fest, wie sehr das Modell einzelnen Beispielen traut. Bei k = 1 läuft die Grenze um jeden Pinguin herum, auch um Ausnahmen mitten in einer anderen Art. Bei großem k, etwa 101 von 239, stimmt fast der halbe Datensatz ab, die Grenzen werden glatt, und die seltenste Art, Chinstrap, verliert Abstimmungen: In Aufteilung 1 fällt die Genauigkeit auf 83,5 %. Ein gutes k liegt dazwischen, und du wählst es an Daten, nicht nach Augenmaß.
Der zweite Regler ist weniger sichtbar: die Einheiten. Der Abstand addiert den Unterschied in der Schnabellänge und den Unterschied in der Masse. Schnäbel reichen von 32,1 bis 59,6 mm, die Masse von 2700 bis 6300 g. Ohne Umskalieren wiegt ein Unterschied von 100 g so viel wie 100 mm Schnabel, also entscheidet fast nur die Masse, wer nah ist. Standardisieren macht aus jedem Messwert eine Zahl von Standardabweichungen vom Mittelwert, und beide Messwerte wiegen gleich viel.
Jak to policzono
- Daten: Palmer Penguins (Gorman, Williams und Fraser, 2014; Paket palmerpenguins: Horst, Hill und Gorman, 2020), Lizenz CC0. 342 Pinguine mit allen Messwerten, 3 Arten.
- Aufteilung: 70/30, geschichtet; Aufteilung 1 ist
train_test_split(test_size=0.3, stratify=y, random_state=1)in scikit-learn, dieselbe wie in Lektion 0.1. 239 Pinguine zum Lernen, 103 im Test. - Modell: kNN mit euklidischem Abstand, eine Stimme pro Nachbar; ein Gleichstand geht an die alphabetisch erste Art (wie in scikit-learn).
- Standardisierung: Mittelwert und Standardabweichung nur aus den Lernpinguinen.
Warum es funktioniert
kNN funktioniert, wenn Nähe in den Messwerten Ähnlichkeit in der Antwort bedeutet. Bei Pinguinen stimmt das: Die Arten unterscheiden sich im Körperbau, also gehören Pinguine mit ähnlichem Schnabel und ähnlicher Masse meist zur selben Art. Deshalb bringen schon zwei Messwerte 94,2 % gegenüber 43,7 % beim Raten „immer Adelie“.
Ein kleines und ein großes k verderben das Ergebnis von entgegengesetzten Seiten. Bei k = 1 ist das Modell sehr anfällig für Zufall: Ein ungewöhnlicher Lernpinguin ändert die Antwort in seiner ganzen Umgebung. Die 100 % beim Lernen sagen hier nichts, weil jeder Pinguin sich selbst findet. Bei sehr großem k sieht das Modell die Form der Daten nicht mehr und nähert sich „der häufigsten Art in der Gegend“. Es ist derselbe Kompromiss zwischen Anpassen und Verallgemeinern, der in Modul 3 wiederkommt.
Die Einheiten zählen so viel, weil kNN nicht weiß, welcher Messwert wichtig ist: Es berechnet nur Abstände. In rohen Einheiten erkennt es bei k = 5 77,7 % der Testpinguine, nach dem Standardisieren 94,2 %. Mit allen vier Messwerten, die Masse in Gramm, ist der Unterschied noch größer: 76,7 % ohne Skalierung und 96,1 % nach dem Standardisieren, im Mittel über 100 Aufteilungen 76,7 % und 98,9 %.
Häufiger Fehler
Richtig oder falsch: „Das kleinste k ist das beste, weil das Modell perfekt zu den Daten passt“. Falsch. Bei k = 1 erreicht das Modell 100 % auf den Lernpinguinen, weil jeder sein eigener Nachbar ist, aber bei neuen Pinguinen verliert es im Mittel gegen k = 9: 92,2 % gegenüber 94,2 % über 100 Aufteilungen. Perfekt zu den Lerndaten zu passen heißt, auch die Ausnahmen auswendig zu lernen. Wähl k nach dem Ergebnis auf Daten, die das Modell nicht gesehen hat.
Wo der Vergleich hinkt: „Nachbarn“ in kNN sind nicht die Pinguine, die am Strand neben dir stehen, sondern die mit ähnlichen Messwerten. Und wer ähnlich ist, hängt von den Einheiten ab, die du wählst.
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
- kNN baut keine Regel: Ein neuer Fall bekommt die Mehrheit der Stimmen seiner k nächsten Lernbeispiele.
- Ein kleines k folgt jeder Ausnahme, ein großes glättet die Grenzen bis hin zum Raten; k wählst du auf Daten, die das Modell nicht gesehen hat.
- 100 % auf den Lerndaten bei k = 1 bedeuten nichts, denn jedes Beispiel ist sein eigener Nachbar.
- kNN rechnet mit Abständen, also entscheiden die Einheiten das Ergebnis: Standardisiere die Messwerte auf den Lerndaten.
Tiefer: Formel, Code, Praxis
Die Mathematik
Der euklidische Abstand zwischen den Pinguinen a und b mit zwei Messwerten ist d(a, b) = √((a₁ − b₁)² + (a₂ − b₂)²). Das Modell sortiert die Lernpinguine nach d und nimmt die ersten k; die Antwort ist die Art mit den meisten Stimmen unter ihnen.
Standardisieren macht aus einem Messwert x den Wert z = (x − μ) / σ, wobei μ und σ Mittelwert und Standardabweichung dieses Messwerts auf den Lerndaten sind. Ohne das fügt ein Unterschied von 100 g in der Masse 100² = 10000 zu d² hinzu, ein Unterschied von 10 mm beim Schnabel nur 10² = 100. Nach dem Standardisieren zählt jeder Messwert in Standardabweichungen, und beide wiegen gleich.
Bei k = 1 hat jedes Lernbeispiel den Abstand 0 zu sich selbst, also ist die Lerngenauigkeit 100 %, solange keine zwei Beispiele mit verschiedenen Labels identische Messwerte haben.
Im Code (Python)
Derselbe Versuch in scikit-learn: die beiden Messwerte aus dem Labor roh und standardisiert für jedes k, k = 1 auf den Lernpinguinen, k = 1, 9 und 101 an 100 Aufteilungen und alle vier Messwerte bei k = 5. Das Notebook, das unter der Ausgabe verlinkt ist, lädt die Daten selbst.
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
df = pd.read_csv("data/raw/penguins.csv")
cols4 = ["bill_length_mm", "bill_depth_mm", "flipper_length_mm", "body_mass_g"]
d = df.dropna(subset=cols4) # die 342 Pinguine mit allen vier Messwerten
y = d["species"]
K = [1, 3, 5, 9, 15, 25, 51, 101]
def knn(k, scale):
model = KNeighborsClassifier(n_neighbors=k)
return make_pipeline(StandardScaler(), model) if scale else model # der Skalierer lernt Mittelwert und Standardabweichung nur auf dem Lernteil
def score(cols, k, scale, seed):
Xtr, Xte, ytr, yte = train_test_split(d[cols], y, test_size=0.3, stratify=y, random_state=seed)
m = knn(k, scale).fit(Xtr, ytr)
return m.score(Xte, yte), m.score(Xtr, ytr)
lab = ["bill_length_mm", "body_mass_g"] # die zwei Messwerte aus dem Labor: Millimeter und Gramm
for scale in (False, True):
print(("standardized:" if scale else "raw mm and g:"), " ".join(f"k={k} {score(lab, k, scale, 1)[0]:.3f}" for k in K))
print(f"k=1 on the learning penguins: {score(lab, 1, True, 1)[1]:.3f}")
runs = {k: np.array([score(lab, k, True, s)[0] for s in range(100)]) for k in (1, 9, 101)}
print(f"100 splits, standardized: k=1 {runs[1].mean():.3f}, k=9 {runs[9].mean():.3f}, k=101 {runs[101].mean():.3f}; k=9 beats k=1 in {(runs[9] > runs[1]).sum()}, loses in {(runs[9] < runs[1]).sum()}")
four = [[score(cols4, 5, scale, s)[0] for s in range(100)] for scale in (False, True)]
print(f"all 4 measurements, k=5: raw {four[0][1]:.3f}, standardized {four[1][1]:.3f} on split 1; mean of 100 splits {np.mean(four[0]):.3f} and {np.mean(four[1]):.3f}")
Ausgabe
raw mm and g: k=1 0.835 k=3 0.748 k=5 0.777 k=9 0.757 k=15 0.777 k=25 0.748 k=51 0.738 k=101 0.738
standardized: k=1 0.942 k=3 0.922 k=5 0.942 k=9 0.942 k=15 0.942 k=25 0.942 k=51 0.942 k=101 0.835
k=1 on the learning penguins: 1.000
100 splits, standardized: k=1 0.922, k=9 0.942, k=101 0.856; k=9 beats k=1 in 78, loses in 9
all 4 measurements, k=5: raw 0.767, standardized 0.961 on split 1; mean of 100 splits 0.767 and 0.989
Bei Aufteilung 1 sind die Ergebnisse dieselben wie im Labor. Das Labor mittelt über seine eigenen 20 Aufteilungen und dieser Code über 100 Aufteilungen von scikit-learn, daher unterscheiden sich die Mittelwerte etwas, aber die Richtung ist dieselbe: Im Mittel schlägt k = 9 k = 1.
Notebook herunterladen (.ipynb). Öffne es in Jupyter oder lade es in Google Colab hoch; fehlende Daten lädt es selbst.
Für die Praxis
- Skaliere in einer Pipeline:
make_pipeline(StandardScaler(), KNeighborsClassifier()). Ein Skalierer, der vor der Aufteilung auf dem ganzen Datensatz angepasst wird, schmuggelt Information aus dem Test ins Lernen. - Wähl k mit Kreuzvalidierung, etwa
GridSearchCVübern_neighbors; bei zwei Klassen vermeidet ein ungerades k Gleichstände. weights="distance"gibt näheren Nachbarn mehr Gewicht; das hilft oft bei großem k.- kNN antwortet bei großen Daten langsam, weil es den Abstand zu jedem Beispiel berechnet, und wird bei vielen Messwerten schwächer, wenn alle Abstände ähnlich werden.
- Für die Aufgabe irrelevante Messwerte gehen auch in den Abstand ein und verderben die Nachbarschaft; wähl die Merkmale, bevor du kNN nutzt.
War das hilfreich?
Danke! Das hilft uns, besser zu werden.
Mehr im Atlas
Einträge der Enzyklopädie zu den Ideen dieser Lektion: