FichesCarte › Partie 06 · Évaluer › chaîne 02

Estimer l'erreur — validation croisée, LOOCV, fuite

Un seul jeu de données, deux usages qui se disputent chaque ligne : apprendre, et mesurer. La validation croisée les réconcilie — chaque ligne est prédite une fois, hors du pli où elle a servi à apprendre — au prix de k ajustements au lieu d'un. Reste à savoir jusqu'où monter k, et à se rappeler que ce qu'on évalue n'est pas le modèle mais toute la procédure : une sélection de features faite hors des plis fabrique une erreur de 5 % sur du bruit pur. Fil rouge : n = 1 000 lignes pour les plis, et l'exemple d'ESL — 50 lignes, 2 000 features de bruit — pour la fuite.

Ce que cette chaîne suppose acquis
  • L'erreur test est ce qu'on veut, l'erreur train ne la mesure pas. Un modèle est jugé sur des données tirées de la même population mais qu'il n'a pas vues ; l'erreur d'entraînement est mesurée là où les paramètres ont été ajustés, donc optimiste par construction (p06-01 pas 1, b02 lieu 2).
  • Le tirage, c'est le dataset entier. L'erreur d'un modèle appris sur un jeu est elle-même une variable aléatoire : elle a un centre et une largeur (p06-01 pas 2). Toute cette chaîne estime ce centre, et se demande à quel point l'estimation est large.
  • Le maximum d'un lot de scores bruités est biaisé vers le haut. Choisir le meilleur de plusieurs candidats, puis rapporter son score, c'est rapporter un maximum et pas une performance (p01-04 pas 6). C'est le pas 9 d'ici, vu de l'autre côté.
  • Var d'une moyenne de B termes corrélés = ρσ² + (1 − ρ)σ²/B, et le nombre efficace de termes plafonne à 1/ρ (b04 pas 2). C'est le mécanisme du pas 4 : on y renvoie, on ne le redérive pas.
Hypothèses posées
H1Les lignes sont iid — c'est exactement ce qui autorise un découpage au hasard. Une série temporelle et des lignes groupées (un utilisateur, un patient) violent H1 : le pas 8 dit ce qu'on découpe alors à la place. H2Ce qu'on évalue est toute la procédure — preprocessing, imputation, sélection de features, choix d'hyperparamètres, modèle — et pas seulement la dernière étape. Tout ce qui a lu les données en fait partie. C'est le pas 5, et c'est l'hypothèse que les fuites violent. H3La perte est une moyenne sur les lignes (taux d'erreur, MSE), donc la moyenne des erreurs de plis de tailles égales est bien l'erreur sur les n lignes. Pour une métrique non moyennable — AUC, F1 — la CV se lit pli par pli, jamais en recollant les prédictions.

La chaîne

Le décor : une ligne ne peut pas servir deux fois

On veut l'erreur du modèle sur des données non vues. On n'a qu'un jeu, et on veut aussi s'en servir pour apprendre — plus il y a de lignes d'entraînement, meilleur est le modèle ; plus il y a de lignes de mesure, plus serrée est la mesure. Les deux tirent sur la même corde.

Une ligne qui a servi à ajuster un paramètre ne mesure plus rien : elle est dans le modèle. La seule question est donc comment rendre chaque ligne utile aux deux, sans jamais qu'elle le soit en même temps.

« L'erreur d'entraînement est mesurée là où les paramètres ont été ajustés, donc elle est optimiste par construction, donc il faut des lignes que l'apprentissage n'a pas vues, donc il faut découper — et la seule liberté qui reste est la manière de découper. »

Application — le fil rouge

n = 1 000 lignes, classification binaire. Trois manières de dépenser ces lignes :

découpagelignes pour apprendrelignes pour mesurerajustements
tout pour apprendre1 00001
holdout 80/208002001
5-fold800 (par modèle)1 0005

La troisième ligne est le tour de passe-passe de cette chaîne : mille lignes de mesure et huit cents lignes d'apprentissage, pour cinq fois le calcul.

Holdout : simple, gaspilleur, bruité

Séparer 80/20, apprendre sur 800, mesurer sur 200. Trois défauts, dans cet ordre d'importance :

Bruité. L'erreur mesurée est une proportion sur m lignes, donc elle a un écart-type

SE = √( p(1 − p) / m )

Gaspilleur : le modèle évalué n'a vu que 80 % des lignes, donc on mesure un modèle un peu moins bon que celui qu'on livrera. Arbitraire : un seul découpage, dont le hasard est entièrement dans le chiffre rapporté.

« L'erreur du holdout est une proportion mesurée sur m lignes, donc son écart-type vaut la racine de p(1 − p) sur m, donc à 200 lignes il vaut 0,024, donc deux modèles séparés par deux points d'accuracy sont indiscernables. »

Application — 200 lignes de test, accuracy 0,87
SE = √( 0,13 × 0,87 / 200 ) = 0,0238 ≈ 0,024

Intervalle à 95 % : 0,87 ± 1,96 × 0,024 = [0,823 ; 0,917]. Un concurrent mesuré à 0,89 tombe dedans : le holdout ne les départage pas.

Sur les 1 000 lignes qu'une 5-fold fait servir à la mesure, le même calcul donne SE = √(0,13 × 0,87 / 1 000) = 0,0106, soit un intervalle 2,2 fois plus serré — c'est tout le gain, et il est gratuit sauf en calcul.

À l'autre bout, un holdout 50/50 mesurerait mieux (SE 0,015) un modèle nettement moins bon. Le holdout ne sait pas sortir de cet arbitrage ; la validation croisée, si.

k-fold : chaque ligne testée une fois tronc

Découper les n lignes en k plis de taille égale. k fois : apprendre sur les k − 1 autres plis, prédire le pli restant. Puis moyenner les erreurs.

CVk = 1n Σi L( yi , f(−pli(i))(xi) )

L'exposant est tout : la prédiction de la ligne i vient du modèle qui ne l'a pas vue. Chaque modèle a vu (1 − 1/kn lignes ; les n lignes servent toutes à mesurer.

« Chaque pli sert une fois de test, donc toutes les lignes sont évaluées hors de leur apprentissage, donc l'erreur moyenne estime l'erreur test d'un modèle appris sur (1 − 1/k) des lignes, donc sur presque tout dès que k vaut 5 ou 10. »

Application — n = 1 000, k = 5

Cinq plis de 200. Cinq modèles, chacun appris sur 800 lignes et mesuré sur les 200 qu'il n'a pas vues. Au total 1 000 prédictions hors apprentissage, contre 200 pour le holdout, pour 5 ajustements au lieu d'un.

Le chiffre rapporté, CV5, estime l'erreur d'un modèle appris sur 800 lignes. Le modèle qu'on livre en verra 1 000 : l'estimation est donc légèrement pessimiste, et c'est le sens dans lequel on préfère se tromper.

Ce que ça ne fait pas. CV5 n'est l'erreur d'aucun des cinq modèles en particulier : c'est l'erreur de la procédure « apprendre ce modèle-là sur 800 lignes de cette population ». D'où le pas 5.

Figure 1 — deux modèles d'une k-fold, et ce qu'ils partagent

Les 1 000 lignes en une barre, découpées en k plis. Modèle A et modèle B sont deux des k modèles : le segment vert est le pli que chacun garde pour tester (à k = n il ne reste qu'une ligne : un simple tiret), le bleu pâle ce sur quoi il apprend. Le pointillé rouge du bas est ce que leurs deux entraînements ont en commun. Monte k : chaque modèle apprend sur davantage de lignes — et les deux entraînements deviennent presque le même. À k = n, ils partagent 99,9 % de leurs lignes, ce qui est exactement le problème du pas suivant. Le bouton « pli suivant » fait glisser le couple le long de la barre.

k = n (LOOCV) : le moyennage cesse de rapporter tronc

À k = n chaque modèle voit n − 1 lignes : c'est presque le modèle final, donc le biais est quasi nul. On aurait tort d'en conclure que c'est le meilleur réglage.

Deux modèles d'une k-fold partagent (k − 2)/(k − 1) de leurs lignes d'entraînement (figure 1). Deux modèles presque identiques font des erreurs presque identiques : la corrélation ρ entre deux erreurs de plis suit cette part. Or moyenner k termes corrélés ne vaut pas moyenner k termes indépendants (b04) :

Beff = 1 / [ ρ + (1 − ρ)/k ]  →  1   quand ρ → 1

Plus k monte, plus il y a de termes — et plus ρ monte, plus vite. Le nombre efficace de plis descend vers 1 : les n erreurs d'une LOOCV valent une seule mesure indépendante, pour n ajustements.

« À k = n deux modèles partagent 99,9 % de leurs lignes, donc leurs erreurs bougent ensemble, donc les n erreurs moyennées valent un seul pli indépendant, donc au-delà de k = 10 chaque ajustement supplémentaire n'achète rien. »

Application — ce que k achète et ce qu'il coûte

Colonnes « lignes » et « fits » : n = 1 000. « Communes » = (k − 2)/(k − 1). Dernière ligne : la LOOCV. Le ρ ci-dessous est mesuré sur le fil rouge de p06-01.

klignesfitscommunesBeff
250020 %2,00
5800575,0 %1,25
109001088,9 %1,11
509805098,0 %1,02
1 0009991 00099,9 %1,001

ρ mesurée (corrélation entre les deux fonctions apprises, 400 tirages) : 0,01 · 0,750 · 0,887 · 0,980. Elle colle à la colonne « communes » sans qu'on l'y force — ce sont bien les lignes partagées qui fabriquent la corrélation.

Mesuré (fil rouge p06-01, 120 000 répétitions ; erreur test de référence = σ²(1 + 2/n) = 0,26, exacte), en fraction de cette erreur : le biais pessimiste fond de +4,3 % (k = 2) à +1,2 % (k = 5) puis +0,6 % (k = 10) et +0,2 % à k = n ; l'écart-type de l'estimation passe de 24,4 % à 21,2 % puis 20,7 % — et ne bouge plus : 20,5 % à k = n. Entre k = 10 et k = n, cent fois le calcul pour deux dixièmes de point d'écart-type.

Donc k = 5 à 10. Tout le biais qu'il y avait à payer est payé, tout l'écart-type qu'il y avait à gagner est gagné. Ce n'est pas un compromis de paresse, c'est l'endroit où les deux courbes sont déjà plates.

Figure 2 — le compromis de k, simulé

Fil rouge de p06-01 : f(x) = x, σ = 0,5, 50 points, apprenant = droite des moindres carrés. Chaque « expérience » tire un jeu, calcule CVk pour les cinq valeurs de k, et mesure l'erreur test du modèle appris sur tout. En rouge le biais de CVk (toujours positif : pessimiste), en bleu son écart-type, tous deux en pourcentage de l'erreur test. Le graphe part de 2 000 expériences et les boutons en ajoutent : le rouge s'effondre entre k = 2 et k = 10, le bleu descend puis se fige. Il ne remonte pas — la LOOCV n'est pas plus bruitée qu'une 10-fold, elle est juste aussi bruitée pour cent fois le prix. Le curseur déplace la barre verticale et met les chiffres du k choisi dans les cases. La référence est exacte — σ²(1 + 2/n) = 0,26 — et le biais est mesuré avec un correctif de variance (on retranche l'énergie de bruit tirée, d'espérance σ²) : sans lui il faudrait cent mille expériences pour distinguer +0,6 % de +0,2 %.

Ce qu'on évalue : la procédure entière, pas le modèle

La CV n'estime pas l'erreur d'un modèle : elle estime l'erreur de la recette qui produit un modèle à partir de n lignes. Toute étape qui a lu les données fait partie de la recette — standardisation, imputation, encodage appris, sélection de features, sur-échantillonnage, choix d'hyperparamètres.

Règle opératoire : tout ce qui a un fit se refait dans chaque pli, sur le pli d'apprentissage seul. Pipeline + cross_val_score le garantissent parce que le pipeline entier est réajusté pli par pli ; un fit_transform sur tout le jeu avant la boucle ne le garantit pas.

« Ce qui est évalué est la procédure qui a produit le modèle, donc tout ce qui a lu les données en fait partie, donc chaque étape ayant un fit est réapprise dans chaque pli sur l'apprentissage seul, donc le pli de test reste réellement non vu. »

Application — dedans ou dehors, et ce qui fuit
étape faite avant la CVce qui traversegravité
StandardScaler sur tout le jeumoyenne et écart-type des lignes de testfaible
imputation par la médiane globalela médiane, donc un résumé du testfaible
encodage de cible (target encoding)les y du test, catégorie par catégorieforte
sélection de features sur yles labels du test, tousmassive (pas 6)
SMOTE / sur-échantillonnagedes copies de lignes de test dans le trainmassive

Les deux premières fuites sont réelles mais petites : un écart-type estimé sur 1 000 lignes plutôt que 800 ne change presque rien. Les trois dernières passent les labels, et là l'erreur mesurée peut devenir n'importe quoi.

Fuite de preprocessing : la sélection qui a vu les labels tronc

Le cas d'école (ESL 7.10.2). Bruit pur : aucune feature n'a le moindre rapport avec y, le vrai taux d'erreur de n'importe quel classifieur est 50 %. On sélectionne les features les plus corrélées à y sur tout le jeu, puis on fait une 5-fold honnête sur les features retenues.

La CV sort une erreur ridiculement basse. Le modèle n'y est pour rien : c'est la sélection qui a lu les labels des plis de test et retenu les features qui, sur ces lignes-là, tombent juste. Le pli de test n'est plus non vu ; la 5-fold qui suit ne fait que confirmer un tri déjà fait avec la réponse sous les yeux.

« La sélection a utilisé les labels de toutes les lignes, donc les plis de test ont été vus avant d'être testés, donc l'erreur mesurée est une erreur d'apprentissage déguisée, donc elle ment — et elle ment d'autant plus que le nombre de features est grand. »

Application — pourquoi le bruit suffit

Avec n = 50 lignes et p = 2 000 features de bruit indépendant, la meilleure corrélation empirique avec y vaut, par pur hasard, |r| ≈ 0,50 (mesuré sur 30 tirages). Retenir les 100 meilleures, c'est fabriquer un tableau qui « explique » y sur ces 50 lignes précises.

protocoleerreur CVvérité
sélection hors des plis, puis 5-fold≈ 5 %50 %
sélection dans chaque pli, puis 5-fold≈ 52 %50 %

Chiffres mesurés sur quatre séries de 20 répétitions (n = 50, p = 2 000, 100 features retenues, 1-NN) : 4,6 / 4,8 / 6,7 / 5,1 % avec la fuite, 51 à 55 % sans. ESL, avec 5 000 features et la même recette, annonce 3 %.

Le second protocole ne corrige rien du modèle — il ne corrige que la mesure. Le modèle reste mauvais dans les deux cas ; seul le second le dit.

Figure 3 — la même CV, la sélection dedans ou dehors

Chaque point est une expérience entière : 50 lignes, 2 000 features de bruit pur, classes équilibrées, 100 features retenues, 5-fold, 1-NN. En rouge la sélection faite sur tout le jeu avant la CV ; en bleu la même sélection refaite dans chaque pli. Le trait rouge fin est le vrai taux, 50 % — ce que la chance donne quand il n'y a rien à apprendre ; les deux traits épais sont les moyennes des deux nuages. Lance 20 répétitions : le bleu se tient autour du trait, le rouge s'effondre vers 5 %. Aucun modèle n'a changé, aucune feature n'est informative ; seule la place de la sélection a bougé.

Fuite de cible : le test « disponible à cet instant ? »

L'autre famille de fuite ne vient pas du découpage mais des colonnes. Une feature contient le futur si sa valeur, en production, n'existe pas encore au moment où la prédiction est faite.

Un seul test, à passer sur chaque colonne : au moment où le modèle prédira, cette valeur est-elle déjà écrite ? Une date de remboursement, un statut mis à jour après coup, un agrégat calculé sur une fenêtre qui déborde sur l'après : non.

Le symptôme est toujours le même : une métrique trop belle, et une ou deux features « magiques » en tête des importances. Une AUC de 0,99 est un bug jusqu'à preuve du contraire, pas une réussite.

« Une feature n'est utilisable que si sa valeur est déjà écrite quand la prédiction est faite, donc une date de remboursement remplie après la résiliation n'existe pas encore, donc le modèle qui s'en sert lit le futur, donc son AUC mesure une tautologie et pas une prédiction. »

Application — prédire une résiliation, colonne par colonne
featureécrite quand ?verdict
date_rembours.après la résiliationfuite — c'est la cible, déguisée
statut_comptemis à jour à la résiliationfuite — valeur lue après coup
appels_supp_30jfenêtre glissante jusqu'à aujourd'huifuite si la fenêtre déborde après la date de prédiction
anciennete_jconnue à tout instantpropre
tickets_90j_av_Tfenêtre arrêtée à la date de prédictionpropre — c'est la version corrigée de la ligne 3

La ligne 3 est la plus fréquente et la plus discrète : la feature est légitime, c'est sa fenêtre qui est mal bornée. Le correctif n'est pas de la supprimer mais de la recalculer à la date de prédiction, ligne par ligne.

Aucune validation croisée ne détecte cette famille-là : la fuite est dans la colonne, donc dans tous les plis à la fois. Seule la question « écrite quand ? » la trouve.

Hors iid : séries temporelles et groupes

Le découpage au hasard repose entièrement sur H1. Deux violations courantes, deux découpages différents.

Série temporelle. Apprendre sur des lignes postérieures au test, c'est donner au modèle une information qu'il n'aura jamais en production. Plis chronologiques : on apprend sur le passé, on teste sur le futur, on avance la frontière. Jamais de shuffle.

Groupes. Quand plusieurs lignes viennent du même individu — un patient, un utilisateur, une session — un découpage au hasard met le même individu des deux côtés. Le modèle apprend à reconnaître l'individu, pas le phénomène. GroupKFold : un groupe entier tient dans un seul pli.

« Un découpage au hasard suppose des lignes échangeables, donc une série où la ligne suivante dépend de la précédente ne l'est pas et se découpe chronologiquement, donc un individu réparti sur plusieurs lignes ne l'est pas non plus et tient tout entier dans un pli. »

Application — 1 000 lignes, 50 patients × 20 lignes, 5-fold au hasard

Pour une ligne de test donnée, combien de lignes du même patient sont dans l'entraînement ? Les 19 autres, chacune avec probabilité 4/5 :

19 × 45 = 15,2 lignes du même patient, dans le train, pour chaque ligne de test

Vérifié par simulation : 15,21 en moyenne sur 2 000 découpages. Autrement dit, aucune ligne de test n'est réellement nouvelle — son patient est toujours déjà dans le modèle. L'erreur CV mesure une capacité de reconnaissance, pas de généralisation.

Avec GroupKFold sur les 50 patients, chaque pli de test contient 10 patients entièrement absents du train : 0 ligne commune. L'erreur remonte — c'est la bonne nouvelle, c'était la vraie.

C'est le même mécanisme que le neff d'un SE sur lignes dépendantes (b04 pas 5) : ramener l'unité de découpage à ce qui est réellement indépendant.

Choisir avec la CV, mesurer ailleurs

La validation croisée sert à choisir : un hyperparamètre, un modèle, un jeu de features. Le score du gagnant est alors un maximum sur des scores bruités, donc biaisé vers le haut — il contient le bruit de la CV qui a favorisé ce candidat-là (p01-04 pas 6, b02 lieu 4).

Deux sorties propres, au choix : un test set jamais touché, ouvert une fois, à la fin ; ou une CV imbriquée — une boucle externe qui mesure, une boucle interne qui choisit, à l'intérieur de chaque pli externe.

« Le score du meilleur de plusieurs candidats est un maximum sur des scores bruités, donc il capture le bruit qui a favorisé ce candidat, donc le rapporter comme performance est optimiste, donc on mesure le modèle choisi sur un jeu que le choix n'a jamais touché. »

Application — 20 candidats strictement équivalents

Vingt hyperparamètres qui valent réellement la même chose, évalués par 5-fold sur 1 000 lignes. Chaque score est bruité d'un écart-type ≈ SE = 0,0106 (pas 2). L'espérance du maximum de 20 tirages gaussiens vaut 1,87 écart-type :

gain apparent = 1,87 × 0,0106 = +0,020

Deux points d'accuracy, gratuits, sur des candidats identiques. C'est exactement l'ordre de grandeur de l'écart qu'on croit avoir gagné en réglant.

Ce qui ne corrige pas : répéter la CV, monter k, ou refaire le grid search. Le biais est dans le max, pas dans le bruit. Ce qui corrige : un jeu que le max n'a pas vu.

Où ça casse casse

La validation croisée est une machine à imiter des données non vues. Elle casse partout où le « non vues » est faux, et à un endroit où c'est la formule qu'on récite mal.

« La CV suppose que le pli de test n'a été vu par rien, donc toute étape, toute colonne et tout découpage qui font passer de l'information vers ce pli la cassent, donc la question à poser n'est jamais « quel k » mais « qu'est-ce qui a déjà vu ces lignes ». »

Cinq limites
  • Shuffle sur une série temporelle. Le modèle apprend sur des lignes postérieures à celles qu'il teste. En production il n'aura que le passé : l'erreur CV est optimiste d'un montant impossible à borner. Plis chronologiques, et pas de shuffle.
  • Groupes ignorés. 15,2 lignes du même patient dans le train pour chaque ligne de test (pas 8) : le modèle reconnaît le patient, pas la maladie. GroupKFold, ou le bon niveau de découpage — utilisateur, session, établissement.
  • Déséquilibre sans stratification. 10 positifs sur 1 000 lignes en 10-fold : un pli donné n'a aucun positif avec probabilité 0,35, et il y a 99 % de chances qu'au moins un des dix plis soit vide. Le score de ce pli est indéfini ou trompeur. StratifiedKFold, et StratifiedGroupKFold quand les deux problèmes se cumulent.
  • Répéter la CV pour « stabiliser ». Moyenner plusieurs découpages réduit le bruit du découpage, et rien d'autre : ni le biais d'une fuite, ni le biais du max (pas 9), ni la dépendance entre lignes. Un chiffre plus stable n'est pas un chiffre plus juste.
  • « La LOOCV a une variance élevée » est un raccourci. Mesuré (pas 4, figure 2), son écart-type n'est pas supérieur à celui d'une 10-fold : il est le même, à deux dixièmes de point près (20,7 % contre 20,5 %). Ce qui est vrai, c'est que la moyenne de ses n erreurs ne réduit plus rienBeff = 1,001 — alors que le calcul, lui, est multiplié par n/10. La conclusion pratique (k = 5 à 10) ne change pas ; l'argument, si.

Résumé

À retenir
  1. Holdout : simple, gaspilleur, bruité — SE = 0,024 sur 200 lignes, de quoi rendre 0,87 et 0,89 indiscernables.
  2. k-fold : chaque ligne prédite une fois hors de son pli ; chaque modèle voit (1 − 1/kn lignes ; les n lignes servent toutes à mesurer.
  3. LOOCV : biais quasi nul, mais deux modèles partagent 99,9 % de leurs lignes ⇒ ρ ≈ 1 ⇒ Beff → 1 : les n erreurs valent un pli indépendant. k = 5 à 10, là où les deux courbes sont déjà plates.
  4. On évalue la procédure entière : tout ce qui a un fit se refait dans chaque pli, sur l'apprentissage seul.
  5. Fuite = le pli de test a déjà été vu (sélection, encodage de cible, sur-échantillonnage) ou le futur est dans une colonne. 5 % d'erreur sur du bruit pur ; une métrique trop belle est un bug.
  6. Hors iid : plis chronologiques pour une série, GroupKFold pour des groupes, StratifiedKFold pour un déséquilibre.
  7. La CV choisit ; le score du gagnant est un maximum (+0,020 sur 20 candidats identiques). Pour mesurer : test jamais touché, ou CV imbriquée.
« Je fais une validation croisée à cinq ou dix plis : chaque ligne est prédite hors de son pli, chaque modèle voit 80 à 90 % des lignes, et je ne monte pas jusqu'à n parce que des modèles qui partagent 99,9 % de leurs lignes donnent des erreurs corrélées dont la moyenne ne vaut qu'un seul pli indépendant. Tout le pipeline est refait dans chaque pli — sinon la sélection de features a vu les labels du test, et sur du bruit pur elle sort 5 % d'erreur là où la vérité est 50 %. Et devant une AUC de 0,99, je cherche la colonne qui contient le futur avant de me réjouir. »

Chaîne verbalisée — une prise, à voix haute

6 maillons · clique pour révéler après avoir dit
  1. Pourquoi pas un simple holdout ?
    Il gaspille 20 % des lignes pour l'apprentissage et ne mesure que sur 200 : SE = 0,024, deux modèles à deux points d'écart sont indiscernables. Et un seul découpage, dont le hasard est dans le chiffre.
  2. Que fait une k-fold, et que voit chaque modèle ?
    k modèles ; chaque pli sert une fois de test, donc chaque ligne est prédite une fois hors de son apprentissage. Chaque modèle voit (1 − 1/k)·n lignes ; les n lignes servent toutes à mesurer.
  3. Pourquoi ne pas monter k jusqu'à n ?
    Deux modèles partagent (k−2)/(k−1) de leurs lignes, donc ρ ≈ 1 à k = n : Beff = 1/[ρ + (1−ρ)/k] descend vers 1. Les n erreurs valent un pli indépendant, pour n ajustements. Mesuré : l'écart-type ne bouge plus après k = 10.
  4. Où mettre la standardisation et la sélection de features ?
    Dans chaque pli, sur l'apprentissage seul — tout ce qui a un fit. Sélection faite dehors sur 2 000 features de bruit pur : 5 % d'erreur CV au lieu de 50 %.
  5. Quel est le test d'une colonne contre la fuite de cible ?
    « Au moment où la prédiction sera faite en production, cette valeur est-elle déjà écrite ? » Date de remboursement, statut mis à jour après coup, fenêtre glissante qui déborde : non. Symptôme : AUC 0,99 et une feature magique.
  6. Que changent une série temporelle et des groupes ?
    Série : plis chronologiques, jamais de shuffle. Groupes : GroupKFold, le groupe entier dans un seul pli — sinon 15,2 lignes du même patient sont dans le train pour chaque ligne de test.