Machine Learning von Grund auf · Lektion 3.4 · 17 von 33 fertigen Lektionen · 12 Min.
Regularisierung: Ridge und Lasso
Kurz gesagt
Eine Strafe für große Gewichte beruhigt das Modell. Lasso setzt Gewichte nacheinander auf null: Mit 3 von 10 Merkmalen fällt das Test-R² von 0,470 auf 0,386.
Aufwärmen Zwei Fragen aus früheren Lektionen. Eine Minute, und sie blockiert die Lektion nicht.
In Lektion 3.1 hat ein Modell mit vielen Parametern das Rauschen gelernt: Der Trainingsfehler fiel, der Testfehler stieg. Statt dem Modell Merkmale wegzunehmen, kannst du sie ihm berechnen. Regularisierung ist eine Strafe, die zum Trainingsfehler addiert wird: Je größer die Gewichte, desto größer die Strafe. Ihre Stärke legt eine Zahl α fest. Heute probierst du zwei Strafen an 10 Merkmalen von Diabetespatienten aus und siehst, dass eine von ihnen die Merkmale selbst auswählt.
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: Der BMI, der Body-Mass-Index, weil er allein am meisten Information trägt
Als letzter bleibt der BMI: Bei α = 39,8 ist er das einzige Merkmal mit Gewicht. s2 verschwindet als erstes endgültig (ab α = 0,398). Mit 3 Merkmalen (BMI, Blutdruck und s5) fällt das Test-R² von 0,470 auf 0,386.
Probier es aus
- Erhöhe α bei Lasso vom kleinsten Wert an. In welcher Reihenfolge erreichen die Gewichtslinien null? Wie viele Merkmale bleiben bei α = 15,8, und was kostet das im Test?
- Beobachte s3. Wann berührt es zum ersten Mal null, und was passiert danach?
- Wechsle zu Ridge und schiebe α bis zum Ende. Wird irgendein Gewicht genau null?
Wenn du es im Lab geprüft hast, geben wir dem, was du siehst, einen Namen.
Die Idee in einfachen Worten
Die gewöhnliche lineare Regression wählt die Gewichte so, dass der Fehler auf den Trainingsdaten möglichst klein wird. Regularisierung addiert zu diesem Fehler eine Strafe für die Größe der Gewichte. Das Modell muss jetzt abwägen: die Daten besser treffen oder kleinere Gewichte haben. Ein Merkmal behält nur dann ein großes Gewicht, wenn es die Vorhersagen wirklich verbessert.
Ridge bestraft die Summe der quadrierten Gewichte. Es zieht alle Gewichte zur Null, setzt aber keines auf null: Im Lab fällt bei α = 398 das Test-R² auf 0,405, und alle 10 Merkmale haben noch ein Gewicht. Lasso bestraft die Summe der Beträge der Gewichte und setzt sie nacheinander auf null. Bei α = 15,8 bleiben drei Merkmale: BMI, Blutdruck und s5. Ohne Strafe ist das Test-R² 0,470, mit drei Merkmalen 0,386. Das Modell ist einfacher und billiger im Einsatz, sagt aber schlechter voraus.
Die Merkmale sind in Standardabweichungen angegeben. Das ist wichtig: Die Strafe misst die Größe der Gewichte, also bekäme ein Merkmal in großen Einheiten ein kleines Gewicht und entginge der Strafe.
Jak to policzono
- Daten: Diabetes, Efron et al. (2004), Annals of Statistics. 442 Patienten, 10 Merkmale zu Beginn der Studie gemessen, Ziel: Fortschreiten der Krankheit ein Jahr später. Die Autoren haben keine Lizenz angegeben; scikit-learn verbreitet den Datensatz weiter (Lizenz BSD-3-Clause).
- Zufällige Aufteilung: 309 Patienten zum Lernen, 133 für den Test. Mittelwerte und Standardabweichungen der Merkmale nur auf dem Trainingsteil berechnet.
- Lasso: 11 Werte von α von 0,01 bis 100. Ridge: 11 Werte von α von 0,1 bis 100000 (Ridge in scikit-learn rechnet die Strafe auf einer anderen Skala als Lasso, daher die anderen Zahlen).
- Test-R²: welchen Anteil der Streuung im Ergebnis der Testpatienten das Modell erklärt (1 = alles, 0 = so viel wie der Mittelwert).
Warum es funktioniert
Die Lasso-Strafe wächst linear: Ein Gewicht um eine Einheit zu verkleinern, spart immer gleich viel Strafe, ob das Gewicht groß oder klein ist. Verbessert ein Merkmal die Anpassung weniger, als die Strafe kostet, lohnt sich ein Gewicht von genau null. Die Ridge-Strafe wächst mit dem Quadrat des Gewichts, kleine Gewichte kosten also fast nichts. Ridge schrumpft ein Gewicht immer weiter, muss es aber nie auf null setzen.
Die Strafe beruhigt auch die Gewichte von Merkmalen, die fast dasselbe sagen. s1 und s2 sind zwei Blutwerte, die stark zusammenhängen (im Code unten ist ihre Korrelation 0,90). Bei der schwächsten Lasso-Strafe hat s1 ein Gewicht von −39,0 und s2 von +26,2: zwei große Zahlen mit entgegengesetztem Vorzeichen, die sich fast aufheben. Solche Gewichte schwanken stark von Stichprobe zu Stichprobe. Die Strafe holt sie herein, und bald entfernt Lasso s2 ganz, weil s1 fast dieselbe Information trägt.
Das ist kein Zufall einer einzigen Aufteilung. Im Code unten läuft dasselbe Experiment auf 50 zufälligen Aufteilungen: Der BMI bleibt in 37 davon als letzter übrig, s5 in den anderen 13. Das Merkmal, das zuerst verschwindet, wechselt noch stärker von Aufteilung zu Aufteilung: das Alter in 21 Aufteilungen, s2 in 16.
Häufiger Fehler
Richtig oder falsch: „Lasso hat einem Merkmal das Gewicht null gegeben, also spielt es keine Rolle.“ Falsch. s2 verschwindet zuerst, obwohl es stark mit s1 zusammenhängt: Lasso wählt ein Merkmal des Paares, und das andere bekommt null, weil es neben s1 nichts Neues bringt. Ohne s1 könnte s2 wichtig sein. Das Lab zeigt es auch an s3: Bei α = 0,158 ist sein Gewicht null, bei α = 0,398 ist es zurück, weil es mit s4 zusammenhängt (r = −0,73) und Lasso das Gewicht zwischen ihnen verschiebt.
Die Wahl zwischen korrelierten Merkmalen kann Zufall sein. Im Code unten verschwindet zuerst mal s2, mal das Alter, und sogar als letztes bleibt manchmal s5 statt des BMI, je nachdem, welche Patienten im Trainingsteil landen. Eine Null bei Lasso heißt: „Dieses Modell brauchte dieses Merkmal nicht, mit diesen Daten und diesem α.“ Sie heißt nicht: „Dieses Merkmal hat nichts mit der Krankheit zu tun.“
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
- Regularisierung addiert zum Fehler eine Strafe für große Gewichte; α legt ihre Stärke fest.
- Ridge zieht alle Gewichte herein und setzt keines auf null; Lasso setzt sie nacheinander auf null und wählt Merkmale aus.
- Ein einfacheres Modell kostet meist etwas Genauigkeit: α wählst du auf der Validierung, nicht auf dem Test.
- Ein Gewicht null bei Lasso heißt nicht, dass das Merkmal unwichtig ist: Von zwei korrelierten Merkmalen behält Lasso oft eines.
Tiefer: Formel, Code, Praxis
Die Mathematik
Ridge: min_w ‖y − Xw‖² + α · Σⱼ wⱼ². Lasso: min_w (1/(2n)) · ‖y − Xw‖² + α · Σⱼ |wⱼ|. So rechnet scikit-learn, deshalb bedeuten dieselben Zahlen für α in den beiden Strafen Verschiedenes.
Warum Lasso auf null setzt: Bei Merkmalen mit Mittelwert 0 und Varianz 1 ist ein Gewicht nach einer Aktualisierung wⱼ = sign(ρⱼ) · max(|ρⱼ| − α, 0), wobei ρⱼ = (1/n) · xⱼᵀ rⱼ der Zusammenhang des Merkmals mit dem Restfehler ohne es ist. Ist |ρⱼ| ≤ α, ist das Gewicht genau null. Ridge ergibt unter denselben Annahmen wⱼ = ρⱼ / (1 + α/n): Das Gewicht schrumpft, ist aber nur null, wenn ρⱼ = 0.
R²: R² = 1 − Σ(yᵢ − ŷᵢ)² / Σ(yᵢ − ȳ)², berechnet auf den Testpatienten.
Im Code (Python)
Dasselbe Experiment in scikit-learn auf 50 zufälligen Aufteilungen (70 % zum Lernen, 30 % für den Test): welches Merkmal Lasso zuletzt behält, welches es zuerst entfernt und was es kostet, höchstens 3 Merkmale zu behalten.
import numpy as np
from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression, Lasso, lars_path
from sklearn.metrics import r2_score
X, y = load_diabetes(return_X_y=True)
names = np.array(["age", "sex", "bmi", "bp", "s1", "s2", "s3", "s4", "s5", "s6"])
alphas = 10 ** np.linspace(-2, 2, 41) # der Strafbereich des Labs, feiner
last, first, r2 = [], [], []
for s in range(50):
tr, te = train_test_split(np.arange(len(y)), test_size=0.3, random_state=s)
sc = StandardScaler().fit(X[tr])
Xtr, Xte = sc.transform(X[tr]), sc.transform(X[te])
path_alphas, _, coefs = lars_path(Xtr, y[tr] - y[tr].mean(), method="lasso") # der exakte Lasso-Pfad, von der stärksten Strafe abwärts
enters = [np.flatnonzero(coefs[j])[0] if coefs[j].any() else len(path_alphas) for j in range(10)] # wo jedes Merkmal zum ersten Mal ein Gewicht bekommt
last.append(names[np.argmin(enters)]); first.append(names[np.argmax(enters)]) # zuerst mit Gewicht = zuletzt ohne, wenn die Strafe wächst
W = np.array([Lasso(alpha=a, max_iter=100000).fit(Xtr, y[tr]).coef_ for a in alphas])
k3 = min(k for k in range(len(alphas)) if (W[k] != 0).sum() <= 3) # die schwächste Strafe, die höchstens 3 Merkmale übrig lässt
m3 = Lasso(alpha=alphas[k3], max_iter=100000).fit(Xtr, y[tr])
r2.append((r2_score(y[te], LinearRegression().fit(Xtr, y[tr]).predict(Xte)), r2_score(y[te], m3.predict(Xte))))
r2 = np.array(r2)
print(f"last feature lasso keeps, 50 splits: {', '.join(f'{n} {last.count(n)}' for n in sorted(set(last), key=lambda n: (-last.count(n), n)))}")
print(f"first feature it drops for good: {', '.join(f'{n} {first.count(n)}' for n in sorted(set(first), key=lambda n: (-first.count(n), n)))}")
print(f"test R2: no penalty {r2[:, 0].mean():.3f}, at most 3 features {r2[:, 1].mean():.3f}; lower with 3 in {(r2[:, 1] < r2[:, 0]).sum()} of 50")
print(f"correlation of s1 and s2: {np.corrcoef(X[:, 4], X[:, 5])[0, 1]:.2f}")
Ausgabe
last feature lasso keeps, 50 splits: bmi 37, s5 13
first feature it drops for good: age 21, s2 16, s4 9, s1 2, s6 2
test R2: no penalty 0.471, at most 3 features 0.379; lower with 3 in 50 of 50
correlation of s1 and s2: 0.90
Die Aufteilungen sind andere als im Lab, also auch die Zahlen. Das Bild ist dasselbe: Der BMI bleibt in 37 von 50 Aufteilungen als letzter übrig (s5 in den anderen 13), und höchstens 3 Merkmale senken das Test-R² in jeder Aufteilung, im Mittel von 0,471 auf 0,379. Zuerst verschwindet mal s2, mal das Alter: Lasso wählt zwischen zusammenhängenden Merkmalen, und die Wahl hängt davon ab, welche Patienten im Trainingsteil gelandet sind.
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:
Ridge,LassoundElasticNet(eine Mischung beider Strafen, hilfreich bei Gruppen korrelierter Merkmale). Pack die Standardisierung in eine Pipeline (make_pipeline(StandardScaler(), Lasso())), damit Mittelwerte und Standardabweichungen nur auf dem Training berechnet werden. - Wähle die Stärke der Strafe per Kreuzvalidierung:
RidgeCVundLassoCVerledigen das in einem Schritt. Wähle α nicht nach dem Testergebnis: Das ist Abstimmen auf dem Testset (Lektion 3.5). - Die logistische Regression in scikit-learn hat standardmäßig eine Ridge-Strafe (
penalty="l2"); ihre Stärke legtCfest, der Kehrwert von α: Ein kleineresCist eine stärkere Strafe. - Wenn du über die Wichtigkeit von Merkmalen sprechen willst, lies nicht nur die Nullen von Lasso. Prüfe, wie stabil die Auswahl über viele Aufteilungen ist, oder nutze die Methoden aus Modul 6.
War das hilfreich?
Danke! Das hilft uns, besser zu werden.
Mehr im Atlas
Einträge der Enzyklopädie zu den Ideen dieser Lektion: