W3docs

Recherche par Grille pour le Réglage des Hyperparamètres en Python

Apprenez à utiliser GridSearchCV et RandomizedSearchCV en Python pour régler les hyperparamètres de modèles ML avec des exemples scikit-learn.

Le réglage des hyperparamètres est le processus qui consiste à trouver les valeurs de configuration d'un modèle d'apprentissage automatique qui ne sont pas apprises à partir des données — des éléments tels que la profondeur d'un arbre de décision, la force de régularisation d'une régression logistique, ou le nombre de neurones dans un réseau de neurones. La recherche par grille est l'approche la plus directe : définir un ensemble discret de valeurs pour chaque hyperparamètre, tester toutes les combinaisons et conserver la meilleure.

Cette page couvre :

  • Ce que sont les hyperparamètres et pourquoi ils sont importants
  • Comment GridSearchCV explore exhaustivement une grille de paramètres
  • Comment lire cv_results_ et comprendre ce qui a été testé
  • L'utilisation de n_jobs=-1 pour paralléliser la recherche
  • RandomizedSearchCV comme alternative plus rapide pour les grandes grilles
  • La combinaison de la recherche par grille avec un Pipeline pour éviter les fuites de données
  • Quand utiliser la recherche par grille plutôt que des alternatives plus rapides

Tous les exemples utilisent les jeux de données intégrés de scikit-learn, vous pouvez donc les exécuter immédiatement.

Que sont les Hyperparamètres ?

Chaque modèle d'apprentissage automatique possède deux types de paramètres :

  • Les paramètres du modèle sont appris automatiquement pendant l'entraînement (par exemple, les poids dans un réseau de neurones, les seuils de division dans un arbre de décision).
  • Les hyperparamètres sont définis par vous avant le début de l'entraînement. Ils contrôlent le processus d'apprentissage lui-même.

Choisir de mauvais hyperparamètres peut laisser un modèle capable bien en dessous de ses performances potentielles. Par exemple, un arbre de décision sans limite de profondeur va sur-apprendre les données d'entraînement ; un arbre avec une limite de profondeur de 1 va sous-apprendre. La limite correcte dépend de vos données, et la recherche par grille la trouve de manière systématique plutôt que par essais-erreurs.

Comment fonctionne GridSearchCV

GridSearchCV de scikit-learn combine deux idées :

  1. Énumération de la grille — il génère toutes les combinaisons de valeurs d'hyperparamètres que vous spécifiez.
  2. Validation croisée — pour chaque combinaison, il effectue une validation croisée k-fold (voir Validation Croisée en Python) et enregistre le score moyen.

Après la recherche, GridSearchCV stocke la meilleure combinaison et ré-entraîne automatiquement un modèle avec ces paramètres sur l'ensemble d'entraînement complet.

Le nombre d'ajustements est (combinaisons) × (plis de validation croisée). Une grille avec 3 × 3 × 3 = 27 combinaisons et cv=5 effectue 135 ajustements — gérable pour les modèles rapides, coûteux pour les modèles lents.

Exemple de Base avec GridSearchCV

L'exemple ci-dessous règle un Classifieur par Arbre de Décision sur le jeu de données Iris.

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_))

Ce que fait chaque argument :

ArgumentRôle
estimatorLe modèle à régler. Tout estimateur scikit-learn fonctionne.
param_gridDict associant les noms de paramètres à des listes de valeurs candidates.
cvNombre de plis dans la validation croisée (5 est une valeur par défaut courante).
scoringMétrique à optimiser. Par défaut, la méthode .score() de l'estimateur.
n_jobsNombre de tâches parallèles. -1 utilise tous les cœurs CPU disponibles.

Sortie typique :

Best parameters: {'criterion': 'gini', 'max_depth': 3, 'min_samples_split': 2}
Best CV accuracy: 0.967

Lecture de cv_results_

Après l'ajustement, grid_search.cv_results_ est un dictionnaire de tableaux — une entrée par combinaison testée. Les clés les plus utiles sont :

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))

Colonnes clés :

  • mean_test_score — le score CV moyen sur tous les plis pour cette combinaison.
  • std_test_score — l'écart-type ; une valeur élevée signifie que le score est instable selon les plis.
  • rank_test_score — le rang 1 est le gagnant.

Options de Scoring

Par défaut, GridSearchCV optimise la métrique par défaut de l'estimateur. Vous pouvez spécifier n'importe quel scorer intégré ou personnalisé :

# 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,
)

Utiliser un Pipeline pour Éviter les Fuites de Données

Lorsque votre prétraitement dépend des données d'entraînement (mise à l'échelle, imputation, sélection de caractéristiques), vous devez ajuster le préprocesseur uniquement sur les plis d'entraînement — jamais sur l'ensemble de données complet avant la division. Un Pipeline gère cela automatiquement et fonctionne parfaitement avec 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_))

La syntaxe avec double tiret bas (svc__C) est la clé : elle indique à scikit-learn de passer C à l'étape svc à l'intérieur du pipeline. Sans pipeline, mettre à l'échelle l'ensemble de données complet avant la validation croisée ferait fuir des informations du pli de test dans le scaler, donnant un score trop optimiste.

RandomizedSearchCV : Plus Rapide pour les Grandes Grilles

La recherche par grille exhaustive devient impraticable lorsque chaque hyperparamètre a de nombreuses valeurs candidates. RandomizedSearchCV échantillonne un nombre fixe de combinaisons aléatoires au lieu de toutes les tester :

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 :

GridSearchCVRandomizedSearchCV
Stratégie de rechercheExhaustive (toutes les combinaisons)Échantillonnage aléatoire
ReproductibilitéEntièrement déterministeDéfinir random_state
Idéal pourGrilles petites et bien définiesGrands espaces de recherche
Distributions continuesNon pris en chargePris en charge via scipy.stats
Garantit de trouver le meilleurOui (dans la grille)Non, mais souvent proche

Pour les grandes grilles, RandomizedSearchCV avec n_iter=50–100 trouve fréquemment une solution quasi-optimale en une fraction du temps de calcul.

Faire des Prédictions avec le Meilleur Modèle

Après l'ajustement, GridSearchCV se comporte comme un estimateur classique. Son attribut best_estimator_ contient le modèle ré-entraîné :

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)

Important : conservez toujours un ensemble de test distinct mis de côté qui n'est jamais consulté pendant la recherche par grille. Le score de validation croisée à l'intérieur de GridSearchCV estime la généralisation, mais l'évaluation finale réelle doit porter sur des données que la recherche n'a jamais touchées.

Quand Utiliser la Recherche par Grille

La recherche par grille est un choix solide par défaut lorsque :

  • Vous avez un modèle de taille petite à moyenne qui s'entraîne rapidement (quelques secondes à quelques minutes par ajustement).
  • Vous savez approximativement quels hyperparamètres comptent le plus et vous disposez d'un ensemble raisonnable de valeurs candidates.
  • La reproductibilité et l'exhaustivité sont importantes.

Envisagez des alternatives lorsque :

  • La grille est grande (de nombreux paramètres avec de nombreuses valeurs) — utilisez d'abord RandomizedSearchCV pour réduire l'espace, puis affinez avec GridSearchCV.
  • L'entraînement est coûteux (apprentissage profond, grands ensembles) — les bibliothèques d'optimisation bayésienne comme scikit-optimize ou Optuna font des choix plus intelligents que l'échantillonnage aléatoire.
  • Vous souhaitez un arrêt automatique — les stratégies de réduction (HalvingGridSearchCV) éliminent rapidement les candidats peu performants et nécessitent moins d'ajustements au total.

Conseils Pratiques

  • Commencez grossièrement. Utilisez une petite grille avec des valeurs réparties sur des ordres de grandeur (par exemple, C: [0.01, 0.1, 1, 10, 100]). Une fois que vous avez trouvé une région prometteuse, affinez avec une grille plus fine.
  • Surveillez les écarts-types. Si std_test_score est grand, le modèle est sensible à la division particulière des données. Envisagez d'augmenter cv ou de collecter davantage de données.
  • Définissez n_jobs=-1 pour utiliser tous les cœurs CPU — cela ne coûte rien et offre souvent une accélération de 4 à 8× sur une machine moderne.
  • Associez à un Pipeline. Enveloppez toujours le prétraitement et le modèle ensemble dans un Pipeline avant de les passer à GridSearchCV. C'est la pratique la plus importante pour obtenir des scores fiables.
  • Utilisez des plis stratifiés pour la classification. GridSearchCV utilise automatiquement StratifiedKFold pour les classifieurs, ce qui préserve les proportions de classes entre les plis.

Sujets Connexes

Was this page helpful?