Grid Search zur Hyperparameter-Optimierung in Python
GridSearchCV und RandomizedSearchCV in Python verwenden, um Hyperparameter von Machine-Learning-Modellen zu optimieren – mit scikit-learn-Beispielen.
Hyperparameter-Optimierung ist der Prozess, die Konfigurationswerte eines Machine-Learning-Modells zu finden, die nicht aus den Daten gelernt werden – zum Beispiel die Tiefe eines Entscheidungsbaums, die Regularisierungsstärke einer logistischen Regression oder die Anzahl der Neuronen in einem neuronalen Netz. Grid Search ist der direkteste Ansatz: Man definiert einen diskreten Satz von Werten für jeden Hyperparameter, probiert jede Kombination aus und behält die beste.
Diese Seite behandelt:
- Was Hyperparameter sind und warum sie wichtig sind
- Wie
GridSearchCVein Parameterraster erschöpfend durchsucht - Wie man
cv_results_liest und versteht, was getestet wurde - Verwendung von
n_jobs=-1zur Parallelisierung der Suche RandomizedSearchCVals schnellere Alternative für große Raster- Kombination von Grid Search mit einer
Pipelinezur Vermeidung von Data Leakage - Wann Grid Search gegenüber schnelleren Alternativen vorzuziehen ist
Alle Beispiele verwenden die eingebauten Datensätze von scikit-learn, sodass sie sofort ausgeführt werden können.
Was sind Hyperparameter?
Jedes Machine-Learning-Modell hat zwei Arten von Parametern:
- Modellparameter werden beim Training automatisch gelernt (z. B. die Gewichte in einem neuronalen Netz, die Schwellenwerte für Splits in einem Entscheidungsbaum).
- Hyperparameter werden von Ihnen vor dem Training festgelegt. Sie steuern den Lernprozess selbst.
Die Wahl falscher Hyperparameter kann dazu führen, dass ein leistungsfähiges Modell erheblich schlechter abschneidet. Ein Entscheidungsbaum ohne Tiefenbegrenzung wird die Trainingsdaten überanpassen; einer mit einer Tiefenbegrenzung von 1 wird zu wenig anpassen. Die korrekte Begrenzung hängt von den Daten ab – Grid Search findet sie systematisch statt durch Raten.
Wie GridSearchCV funktioniert
GridSearchCV aus scikit-learn kombiniert zwei Konzepte:
- Rasterenumeration — es erzeugt jede Kombination der von Ihnen angegebenen Hyperparameter-Werte.
- Kreuzvalidierung — für jede Kombination führt es eine k-fache Kreuzvalidierung durch (siehe Kreuzvalidierung in Python) und speichert den Durchschnittswert.
Nach der Suche speichert GridSearchCV die beste Kombination und passt automatisch ein Modell mit diesen Einstellungen an den vollständigen Trainingsdatensatz an.
Die Anzahl der Anpassungen beträgt (Kombinationen) × (CV-Folds). Ein Raster mit 3 × 3 × 3 = 27 Kombinationen und cv=5 führt 135 Anpassungen durch – handhabbar für schnelle Modelle, aufwendig für langsame.
Einfaches GridSearchCV-Beispiel
Das folgende Beispiel optimiert einen Entscheidungsbaum-Klassifikator auf dem Iris-Datensatz.
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import GridSearchCV
from sklearn.datasets import load_iris
X, y = load_iris(return_X_y=True)
# Model with no hyperparameters set yet
model = DecisionTreeClassifier(random_state=42)
# Define the grid of values to try
param_grid = {
'max_depth': [2, 3, 5, None],
'min_samples_split': [2, 5, 10],
'criterion': ['gini', 'entropy'],
}
# cv=5 means 5-fold cross-validation for each combination
grid_search = GridSearchCV(
estimator=model,
param_grid=param_grid,
cv=5,
scoring='accuracy',
n_jobs=-1, # use all CPU cores
verbose=0,
)
grid_search.fit(X, y)
print("Best parameters:", grid_search.best_params_)
print("Best CV accuracy: {:.3f}".format(grid_search.best_score_))Was jedes Argument bewirkt:
| Argument | Zweck |
|---|---|
estimator | Das zu optimierende Modell. Jeder scikit-learn-Estimator funktioniert. |
param_grid | Dict, das Parameternamen auf Listen von Kandidatenwerten abbildet. |
cv | Anzahl der Folds bei der Kreuzvalidierung (5 ist ein üblicher Standardwert). |
scoring | Zu optimierende Metrik. Standardmäßig die .score()-Methode des Estimators. |
n_jobs | Anzahl der parallelen Jobs. -1 verwendet alle verfügbaren CPU-Kerne. |
Typische Ausgabe:
Best parameters: {'criterion': 'gini', 'max_depth': 3, 'min_samples_split': 2}
Best CV accuracy: 0.967cv_results_ lesen
Nach der Anpassung ist grid_search.cv_results_ ein Dict aus Arrays – ein Eintrag pro getesteter Kombination. Die nützlichsten Schlüssel sind:
import pandas as pd
results = pd.DataFrame(grid_search.cv_results_)
# Show top 5 combinations by mean test score
cols = ['param_max_depth', 'param_min_samples_split', 'param_criterion',
'mean_test_score', 'std_test_score', 'rank_test_score']
print(results[cols].sort_values('rank_test_score').head(5).to_string(index=False))Wichtige Spalten:
mean_test_score— der durchschnittliche CV-Score über alle Folds für diese Kombination.std_test_score— Standardabweichung; ein hoher Wert bedeutet, dass der Score über Folds hinweg instabil ist.rank_test_score— Rang 1 ist der Gewinner.
Scoring-Optionen
Standardmäßig optimiert GridSearchCV die Standardmetrik des Estimators. Sie können einen beliebigen eingebauten Scorer oder einen eigenen angeben:
# Common scoring strings
scoring_options = [
'accuracy', # classification
'f1_weighted', # F1 for multi-class
'roc_auc', # binary classification
'neg_mean_squared_error', # regression (note: negative so higher = better)
'r2', # regression
]
# Evaluate multiple metrics at once (refit on the one you care most about)
grid_search = GridSearchCV(
estimator=DecisionTreeClassifier(random_state=42),
param_grid={'max_depth': [2, 3, 5]},
cv=5,
scoring={'acc': 'accuracy', 'f1': 'f1_weighted'},
refit='acc', # use accuracy to pick the best model
n_jobs=-1,
)Eine Pipeline verwenden, um Data Leakage zu verhindern
Wenn Ihre Vorverarbeitung von den Trainingsdaten abhängt (Skalierung, Imputation, Feature-Selektion), müssen Sie den Preprocessor nur auf Trainings-Folds anpassen – niemals auf dem vollständigen Datensatz vor der Aufteilung. Eine Pipeline übernimmt das automatisch und funktioniert nahtlos mit GridSearchCV.
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import GridSearchCV
X, y = load_breast_cancer(return_X_y=True)
# Build a pipeline: scale then classify
pipe = Pipeline([
('scaler', StandardScaler()),
('svc', SVC()),
])
# Reference pipeline steps with double-underscore: step__param
param_grid = {
'svc__C': [0.1, 1, 10],
'svc__kernel': ['linear', 'rbf'],
'svc__gamma': ['scale', 'auto'],
}
grid_search = GridSearchCV(pipe, param_grid, cv=5, scoring='accuracy', n_jobs=-1)
grid_search.fit(X, y)
print("Best params:", grid_search.best_params_)
print("Best CV accuracy: {:.3f}".format(grid_search.best_score_))Die Doppelunterstrich-Syntax (svc__C) ist entscheidend: Sie teilt scikit-learn mit, C an den svc-Schritt innerhalb der Pipeline weiterzugeben. Ohne eine Pipeline würde die Skalierung des vollständigen Datensatzes vor der Kreuzvalidierung Informationen aus dem Test-Fold in den Scaler einführen und einen zu optimistischen Score liefern.
RandomizedSearchCV: Schneller bei großen Rastern
Erschöpfende Grid Search wird unpraktisch, wenn jeder Hyperparameter viele Kandidatenwerte hat. RandomizedSearchCV zieht eine feste Anzahl zufälliger Kombinationen, anstatt alle zu testen:
from sklearn.model_selection import RandomizedSearchCV
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
from scipy.stats import randint
X, y = load_iris(return_X_y=True)
# Use distributions instead of discrete lists
param_dist = {
'n_estimators': randint(50, 500), # random integer in [50, 500)
'max_depth': [3, 5, 10, None],
'min_samples_split': randint(2, 20),
'max_features': ['sqrt', 'log2'],
}
rand_search = RandomizedSearchCV(
estimator=RandomForestClassifier(random_state=42),
param_distributions=param_dist,
n_iter=30, # try 30 random combinations instead of all
cv=5,
scoring='accuracy',
n_jobs=-1,
random_state=42,
)
rand_search.fit(X, y)
print("Best params:", rand_search.best_params_)
print("Best CV accuracy: {:.3f}".format(rand_search.best_score_))GridSearchCV vs. RandomizedSearchCV:
GridSearchCV | RandomizedSearchCV | |
|---|---|---|
| Suchstrategie | Erschöpfend (alle Kombinationen) | Zufällige Stichprobe |
| Reproduzierbarkeit | Vollständig deterministisch | random_state setzen |
| Am besten geeignet für | Kleine, klar definierte Raster | Große Suchräume |
| Kontinuierliche Verteilungen | Nicht unterstützt | Unterstützt via scipy.stats |
| Findet garantiert das Beste | Ja (innerhalb des Rasters) | Nein, aber oft nah dran |
Bei großen Rastern findet RandomizedSearchCV mit n_iter=50–100 häufig eine nahezu optimale Lösung in einem Bruchteil der Rechenzeit.
Vorhersagen mit dem besten Modell treffen
Nach der Anpassung verhält sich GridSearchCV wie ein normaler Estimator. Das Attribut best_estimator_ enthält das neu angepasste Modell:
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import GridSearchCV
from sklearn.datasets import load_iris
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
param_grid = {'max_depth': [2, 3, 5], 'criterion': ['gini', 'entropy']}
grid_search = GridSearchCV(
DecisionTreeClassifier(random_state=42),
param_grid, cv=5, n_jobs=-1
)
grid_search.fit(X_train, y_train)
# Evaluate on the held-out test set
test_score = grid_search.score(X_test, y_test)
print("Test accuracy: {:.3f}".format(test_score))
# Access the best model directly
best_model = grid_search.best_estimator_
predictions = best_model.predict(X_test[:5])
print("Predictions for first 5 test samples:", predictions)Wichtig: Halten Sie immer einen separaten zurückgehaltenen Testdatensatz bereit, der während der Grid Search nie verwendet wird. Der Kreuzvalidierungs-Score innerhalb von GridSearchCV schätzt die Generalisierungsfähigkeit, aber die eigentliche abschließende Bewertung sollte auf Daten erfolgen, die die Suche nie berührt hat.
Wann Grid Search verwendet werden sollte
Grid Search ist eine gute Standardwahl, wenn:
- Sie ein kleines oder mittelgroßes Modell haben, das schnell trainiert (Sekunden bis wenige Minuten pro Anpassung).
- Sie grob wissen, welche Hyperparameter am wichtigsten sind, und einen sinnvollen Satz von Kandidatenwerten haben.
- Reproduzierbarkeit und Vollständigkeit wichtig sind.
Erwägen Sie Alternativen, wenn:
- Das Raster groß ist (viele Parameter mit vielen Werten) — verwenden Sie zuerst
RandomizedSearchCV, um den Raum einzugrenzen, und verfeinern Sie dann mitGridSearchCV. - Das Training aufwendig ist (Deep Learning, große Ensembles) — Bayesianische Optimierungsbibliotheken wie
scikit-optimizeoderOptunatreffen klügere Entscheidungen als zufälliges Sampling. - Sie automatisches Stoppen wünschen — Halving-Strategien (
HalvingGridSearchCV) scheiden schwach performende Kandidaten früh aus und benötigen insgesamt weniger Anpassungen.
Praktische Tipps
- Beginnen Sie grob. Verwenden Sie ein kleines Raster mit Werten, die sich über Größenordnungen erstrecken (z. B.
C: [0.01, 0.1, 1, 10, 100]). Sobald Sie eine vielversprechende Region gefunden haben, verfeinern Sie mit einem feineren Raster. - Beobachten Sie Standardabweichungen. Wenn
std_test_scoregroß ist, ist das Modell empfindlich gegenüber der jeweiligen Datenteilung. Erwägen Sie,cvzu erhöhen oder mehr Daten zu sammeln. - Setzen Sie
n_jobs=-1, um alle CPU-Kerne zu nutzen – das kostet nichts und bringt auf einem modernen Rechner oft einen 4–8-fachen Geschwindigkeitsvorteil. - Kombinieren Sie mit einer Pipeline. Wickeln Sie Vorverarbeitung und Modell immer in einer
Pipelineein, bevor Sie sie anGridSearchCVübergeben. Dies ist die wichtigste Praxis für zuverlässige Scores. - Verwenden Sie stratifizierte Folds bei der Klassifikation.
GridSearchCVverwendet für Klassifikatoren automatischStratifiedKFold, wodurch die Klassenanteile über Folds hinweg erhalten bleiben.
Verwandte Themen
- Kreuzvalidierung in Python — verstehen Sie die k-fache Auswertung, die
GridSearchCVantreibt - Entscheidungsbaum-Klassifikator — ein häufig mit Grid Search optimiertes Modell
- Logistische Regression — ein weiteres schnelles Modell, das gut für Grid Search geeignet ist
- K-Nearest Neighbors —
n_neighborsundmetricsind klassische Grid-Search-Ziele - Lineare Regression — Hyperparameter-Optimierung für regularisierte Regressionsvarianten