Validation croisée imbriquée : sélectionner et évaluer simultanément
Vous structurerez une boucle externe de validation croisée pour l’évaluation et une boucle interne pour la sélection des hyperparamètres afin d’obtenir une estimation non biaisée des performances réelles du modèle optimisé.
Validation croisée imbriquée : sélectionner et évaluer simultanément est une leçon Machine Learning Academy gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Machine Learning Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Machine Learning Academy comprend 4 leçons au total.
Certaines parties de cette leçon n'ont pas encore été traduites et s'affichent en anglais.
The Problem of Evaluation Bias
When you use the same data for both hyperparameter selection and performance evaluation, you introduce an optimistic bias. Even if you use cross-validation for selection and a separate test set for evaluation, if you repeat the selection process multiple times (trying different grids, different models), you are implicitly using the test set information. With a single held-out test set, random chance may cause a lucky hyperparameter combination to look better than it truly is. Nested cross-validation provides an unbiased performance estimate while still selecting hyperparameters.
The Two-Loop Structure of Nested CV
Nested CV uses two nested loops: (1) an outer loop for performance evaluation — it creates multiple train/test splits, and the test split is used only to evaluate the final selected model; (2) an inner loop for hyperparameter selection — within each outer training fold, a second CV (or grid search) is run to select the best hyperparameters using only the outer training data. The outer test fold never participates in training or selection. Averaging the outer scores gives the true, unbiased generalisation estimate.
Implementing Nested CV with GridSearchCV
The inner loop is a GridSearchCV object. The outer loop is cross_val_score with the GridSearchCV object as the estimator. cross_val_score calls fit on each outer training fold, which triggers the inner grid search CV, selecting the best hyperparameters within that fold. Then predict is called on the outer test fold using those hyperparameters. The result is an array of scores — one per outer fold — representing honest performance estimates.
from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV, cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.datasets import load_breast_cancer
import numpy as np
X, y = load_breast_cancer(return_X_y=True)
pipe = Pipeline([('sc', StandardScaler()), ('svc', SVC())])
param_grid = {'svc__C': [0.1, 1, 10], 'svc__gamma': [0.01, 0.1, 1]}
# Inner CV: selects best hyperparameters on outer training fold
inner_cv = GridSearchCV(pipe, param_grid, cv=3, n_jobs=-1)
# Outer CV: gives honest evaluation
outer_scores = cross_val_score(inner_cv, X, y, cv=5, n_jobs=-1)
print('Nested CV scores:', np.round(outer_scores, 4))
print('Unbiased estimate:', round(outer_scores.mean(), 4), '+/-', round(outer_scores.std(), 4))Nested CV vs Non-Nested CV: The Bias Gap
Comparing nested CV scores to non-nested CV scores on the same dataset reveals the optimistic bias of the non-nested approach. The non-nested CV selects hyperparameters based on the same data used for the score estimate, so it will always appear better. The gap between nested and non-nested scores represents how much the hyperparameter selection process overfit to the available data. On small datasets this gap can be substantial (2-5%).
from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV, cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.datasets import load_breast_cancer
import numpy as np
X, y = load_breast_cancer(return_X_y=True)
pipe = Pipeline([('sc', StandardScaler()), ('svc', SVC())])
param_grid = {'svc__C': [0.1, 1, 10], 'svc__gamma': [0.01, 0.1, 1]}
inner = GridSearchCV(pipe, param_grid, cv=3, n_jobs=-1)
nested_score = cross_val_score(inner, X, y, cv=5).mean()
non_nested = GridSearchCV(pipe, param_grid, cv=5, n_jobs=-1)
non_nested.fit(X, y)
non_nested_score = non_nested.best_score_
print('Non-nested CV score (optimistic):', round(non_nested_score, 4))
print('Nested CV score (unbiased): ', round(nested_score, 4))
print('Optimism gap:', round(non_nested_score - nested_score, 4))When Nested CV Is Essential
Nested CV is most important when: (1) the dataset is small (< 1,000 examples) — test sets are too small for reliable estimates and leakage has more impact; (2) you are comparing multiple algorithm families and selecting the best (model selection adds another layer of overfitting); (3) writing an academic paper that reports unbiased performance. For large datasets or quick prototyping, simple train-validation-test splits or single-level CV with a held-out final test set provide sufficient reliability.
Nested CV for Model Selection
Nested CV extends naturally to selecting among different model families. In each outer fold, the inner search can try multiple algorithms (SVM, random forest, gradient boosting), each with their own hyperparameter grid, and pick the best combination. This gives an honest estimate of the complete model-selection process, not just hyperparameter tuning. This is the rigorous way to answer: 'If I had no prior knowledge, what would I expect my best model to achieve on new data?'
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV, cross_val_score
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_breast_cancer
X, y = load_breast_cancer(return_X_y=True)
# Compare SVM vs RF via nested CV
for name, model, grid in [
('SVM', Pipeline([('sc', StandardScaler()), ('svc', SVC())]), {'svc__C': [0.1, 1, 10]}),
('RF', RandomForestClassifier(random_state=42), {'n_estimators': [50, 100, 200]})
]:
inner = GridSearchCV(model, grid, cv=3)
score = cross_val_score(inner, X, y, cv=5).mean()
print(f'{name} nested CV estimate: {round(score, 4)}')Computational Cost of Nested CV
Nested CV is expensive. With an outer 5-fold and inner 3-fold grid search over 9 combinations, you train 5 × 3 × 9 = 135 models. Adding another outer fold or parameter makes cost grow quickly. Cost-reduction strategies: (1) use RandomizedSearchCV in the inner loop; (2) use fewer outer folds (3-fold outer is common); (3) use fewer inner folds; (4) use faster algorithms (LightGBM instead of SVM for large datasets); (5) use n_jobs=-1 at both levels. In production, nested CV is usually a one-time investment during final model validation.
Interpreting Nested CV Results
The outer scores in nested CV represent: 'If I repeated my entire model-development pipeline (CV-based hyperparameter selection) on fresh data, what accuracy would I expect?'. A high mean with low standard deviation is the ideal — it means the selection process is stable and the model generalises consistently. High variance in outer scores suggests that the optimal hyperparameters change significantly across different data samples — a sign of limited data or high model sensitivity.
Extracting Best Parameters from Each Outer Fold
When you pass a GridSearchCV to cross_val_score, it does not expose the best parameters from each outer fold directly. To inspect them, you must implement the outer loop manually using KFold and iterate, fitting the GridSearchCV on each training fold and recording best_params_. This reveals whether the same hyperparameters win in every fold (stable) or different parameters win in different folds (unstable, data-dependent).
from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV, KFold
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.datasets import load_breast_cancer
import numpy as np
X, y = load_breast_cancer(return_X_y=True)
pipe = Pipeline([('sc', StandardScaler()), ('svc', SVC())])
param_grid = {'svc__C': [0.1, 1, 10], 'svc__gamma': [0.01, 0.1, 1]}
outer_cv = KFold(n_splits=3, shuffle=True, random_state=42)
for fold, (tr, te) in enumerate(outer_cv.split(X, y), 1):
inner = GridSearchCV(pipe, param_grid, cv=3)
inner.fit(X[tr], y[tr])
score = inner.score(X[te], y[te])
print(f'Fold {fold}: best={inner.best_params_}, test_acc={score:.4f}')Nested CV in Practice: Final Model
After nested CV confirms your algorithm and hyperparameter selection process will generalise, you retrain the final model. The standard procedure: (1) run nested CV to get an honest performance estimate; (2) run non-nested CV (or a single inner GridSearchCV on all available data) to select the final best hyperparameters; (3) fit the final model with those hyperparameters on all your labelled data; (4) deploy that final model. The nested CV score is your reported metric — it is honest and reproducible.
When Is Nested CV Overkill?
Nested CV is not always necessary. If you have a very large dataset (>100,000 examples), a simple 80/10/10 train/validation/test split works well because the large sample size reduces the variance of each estimate. Similarly, if you are doing rapid prototyping or exploration, non-nested CV is acceptable — just remember to report test set results from a dedicated hold-out that you only look at once. Nested CV matters most in research settings, small-data problems, and competitive benchmarks where every fraction of a percent counts.
Quick Check
Test your understanding of Nested Cross-Validation from this lesson.
Lesson Recap
In this lesson you learned: nested CV separates hyperparameter selection (inner loop) from evaluation (outer loop) to avoid optimistic bias, the outer test fold never participates in training or selection, and nested CV is most critical for small datasets and rigorous academic comparisons. Next up we explore Feature Engineering through log transforms, binning, and interaction features.
Apprends Python avec un tuteur IA — gratuit
Écris et exécute du vrai code dans ton navigateur, obtiens de l'aide instantanée d'un tuteur IA disponible 24h/24, et reprends là où tu t'es arrêté sur le web ou dans l'app.
- Cours
- 30
- Leçons
- 120
Questions Fréquemment Posées
La leçon « Validation croisée imbriquée : sélectionner et évaluer simultanément » est-elle gratuite ?
Oui — le texte complet de « Validation croisée imbriquée : sélectionner et évaluer simultanément » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Machine Learning Academy, passe à CoddyKit PRO. Le cours Machine Learning Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Validation croisée imbriquée : sélectionner et évaluer simultanément » ?
Vous structurerez une boucle externe de validation croisée pour l’évaluation et une boucle interne pour la sélection des hyperparamètres afin d’obtenir une estimation non biaisée des performances rée… Tu pratiques Machine Learning Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Machine Learning Academy ?
Aucune expérience préalable n'est requise. Machine Learning Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.
Combien de temps prend la leçon « Validation croisée imbriquée : sélectionner et évaluer simultanément » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Machine Learning Academy ?
Oui. Chaque leçon Machine Learning Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Validation croisée K-Fold : découper sans fuite de données
- Validation croisée stratifiée et pour séries temporelles
- Recherche sur grille ou recherche aléatoire
- Validation croisée imbriquée : sélectionner et évaluer simultanément