Skip to content

Rétrospective S04 — LightGBM capacity ablation (Block 2)

KM / lessons learnt de la Story CVN-N001-EI-S04 (wp#227, GH #1059). Rédigée à la clôture (Tested, deliverable conclu sur un négatif). Auditoire : l'équipe + le futur soi qui lancera le prochain diagnostic.

1. Objectif initial vs résultat réel

Objectif Tester si les défauts HPO de prod sur-ajustent (sur-capacité LGB) et recommander une config plus douce (HP swap).
Résultat Verdict diagnostic B_SYSTEMATIC_OVERFIT (en val-AUC, 5/5). MAIS le deliverable HP-swap a fermé sur un NÉGATIF : la reco lr-doux ne transfère pas à l'objectif trading prod. + un incident hang 16 h résolu (fix infra) + 3 ADR durables.

En une phrase : S04 a prouvé une existence (le signal sur-ajuste en AUC) mais s'est cassé en tentant une sélection (recommander lr=0.025) que seul l'objectif aval pouvait valider — et qui s'est révélée fausse.

2. Chronologie (la vraie histoire, pas la version lissée)

  1. Diagnostic construit, mergé, déployé (s42, two-layer Airflow+Hamilton).
  2. Premier full run figé 16 h (busy-wait livelock OpenMP/BLAS, 0 fit) → RCA confirmé Prometheus (pas « plausible », mesuré : ~3.2 cœurs/pod en busy-wait) → ADR-0096 (caps env-level threads+process) → PR #1097déploiement phasé WARN→observe→fail-loud → vérif 1 cellule → re-run.
  3. Re-run conclusif : B_SYSTEMATIC_OVERFIT 5/5 (ARBUSDC rattrapé sur learning_rate par le 5-axes que le smoke num_leaves ratait).
  4. Deliverable HP-swap → cascade de §0bis :
  5. dérivation (trajectoire XCom) → stabilité multi-fold : seul lr survit ; num_leaves/mcs = winner's curse (brillants in-sample, échouent OOS) ;
  6. §0bis facteur : l'env-var CVN_HPO_*_LEARNING_RATE ≠ pin (Optuna cherche le RANGE) ; pas de mode no-HPO → la PR une-ligne était morte ;
  7. §0bis verdict : prod cherche lr ∈ [0.05,0.15] sous f1_buy, pas l'AUC sur HP fixés → l'optimum ~0.025 est hors-range + hors-objectif ;
  8. §0bis lecture : objectif des runs mai non-vérifiable → bascule sur n=600 trials juin f1_buy-confirmés → la recherche prod ne favorise pas lr bas (médiane 0.106, 0% sous le plancher).
  9. Négatif documenté (« pas de support », sans brûler le compute B) + ADR-0097/0098/0099 + 4 Stories de suivi (S08-S11).

3. Lessons learnt

A. Méthodologiques (les durables)

  1. La chaîne de validité des proxies — la leçon la plus fondamentale (et celle que cette rétro a failli rater). Le diagnostic optimise une chaîne de proxies : AUC → f1_buy → valeur économique. Chaque maillon est un proxy du suivant et doit une démonstration de transfert SÉPARÉE. S04 a appris (cher) que AUC → f1_buy ne transfère pas. Mais le maillon du haut — f1_buy → valeur économique — n'est aujourd'hui PAS démontré : f1_buy (f1 de la classe buy, seuillé) est lui-même un proxy du rendement net/expectancy, magnitude-aveugle (cf. A5), dont la fidélité à l'économique n'a jamais été établie. ⚠️ Fausse clôture à ne pas commettre : ADR-0098 valide un diagnostic contre l'objectif de déploiement (= f1_buy) — donc un diagnostic « correctement cadré » peut passer la gate tout en optimisant un proxy possiblement invalide. La couture diagnostic↔déploiement est fermée ; la couture déploiement↔valeur-économique reste OUVERTE — et c'est la plus fondamentale (ADR-0099 Inv 2 l'exige, elle n'est pas encore honorée). La leçon complète n'est donc pas « utilise f1_buy au lieu de l'AUC » (la demi-leçon qui refait l'erreur un cran plus haut) mais « valide chaque maillon de la chaîne ; f1_buy → économie est le maillon ouvert à démontrer avant de s'y fier ».

  2. Existence ≠ sélection (ADR-0099). Un diagnostic (étape 1) prouve qu'un signal existe ; sélectionner la « meilleure » config exige l'objectif aval qu'il n'a pas. S04 a franchi cette frontière — c'est la leçon-mère. Sortie légitime d'un diagnostic = « X existe, d'ampleur Y », jamais « déploie Z ».

  3. Le diagnostic doit mapper le déploiement (ADR-0098) — sur métrique ET régime. s42 a mesuré l'AUC sur des HP fixés ; prod cherche sous f1_buy. Deux mismatches → verdict interne-valide mais hors-sujet pour décider.
  4. §0bis : 3 curatifs en exécution + 1 préventif ABSENT. Trois §0bis curatifs pendant l'exécution (facteur → verdict → lecture), chacun a rattrapé un faux positif. Mais le §0bis préventif de cadrage (« ce diagnostic mappe-t-il métrique+régime de la prod ? ») — une lecture de 10 min — n'a rien attrapé : il manquait au plan. La leçon de process n'est pas « on a fait 4 §0bis » mais « 3 curatifs ont rattrapé en exécution, cher, ce qu'1 préventif au plan aurait évité ». ADR-0098 = ce préventif, désormais plan-gate.
  5. Le proxy ne suit pas fidèlement l'objectif — NON-TRANSFERT (pas « anti-corrélation »). La sélection trading (recherche f1_buy) ne retient pas le lr bas que l'AUC préfère → l'AUC ne suit pas fidèlement f1_buy : non-transfert. ⚠️ Ne PAS dire « les optima pointent à l'opposé » — claim forte qu'on s'est explicitement interdite : lr est co-budgété avec n_estimators (le lr-haut retenu peut refléter un re-budgeting, pas une préférence), et on n'a pas la courbe f1-vs-lr contrôlée. On ne réclame que ce qui est montré : le proxy peut ne pas transférer. Et — cf. A0 — f1_buy lui-même n'est qu'un maillon, pas la vérité économique.
  6. « Sélectionner » réclame magnitude + objectif. Win-rate et f1 sont aveugles à la magnitude ; viser expectancy/edge net (ADR-0099 Inv 3).

B. Ce qui a marché (à répéter)

  • Filtrage stabilité multi-fold asymétrique : a tué num_leaves (5/5 in-sample, dérive OOS) sur le même critère que mcs — propre, symétrique. La contribution transférable (rapport publié).
  • Pré-enregistration de l'interprétation avant de lire (les 3 cas Q-objectif) — a gardé honnête un résultat satisfaisant (le plus dangereux).
  • Read-only avant compute : la réfutation observationnelle a économisé tout le run B.
  • RCA confirmé empiriquement (signature CPU Prometheus), pas une cause « plausible » non vérifiée.

C. Opérationnelles / pièges concrets (pour le prochain)

  • _generate_folds est now-anchored → un index de fold n'est pas reproductible cross-mois → pin les fenêtres calendaires, pas les index (et un run qui référence un fold doit tourner le même mois).
  • s42 exige l'axe primaire (num_leaves) dans axes_subset — un run mono-axe sort INCONCLUSIVE_TOOLING missing_primary_axis_probe.
  • L'XCom porte la trajectoire complète (metrics.probes, dérivation sans re-run) ; mais MLflow ne logge pas l'objectif des runs et Loki ne retient pas > ~1 mois → vérifier l'objectif par run sur events récents (hpo_complete best_<metric>).
  • reports/ est gitignored (force-add) ; ajouter à la nav avant que le fichier soit tracké = build CI cassé ; lien vers fichier non-commité = strict-build passe en local, échoue en CI.
  • Thread caps : env-level OMP/OPENBLAS/MKL/NUMEXPR_NUM_THREADS + LOKY_MAX_CPU_COUNT + OMP_WAIT_POLICY=passive, déploiement phasé WARN d'abord (blast-radius = tous les pods).
  • Scope / validité externe : tous les findings (verdict, distribution lr prod, négatif) sont defi_top5-spécifiques ; généralisation à un autre univers/timeframe = non testée.

4. Ce qu'on change (process)

Changement Porté par
§0bis de cadrage au PLAN (le diagnostic mappe-t-il métrique+régime du déploiement ?) ADR-0098 (plan-gate)
Frontière existence/sélection + lien de validité à chaque couture ADR-0099
Template rapport standardisé (pré-enregistration, limites first-class, reproductibilité) ADR-0097
Diagnostics suivants restent à l'existence Epic §1bis
Démontrer le maillon f1_buy → valeur économique (la couture la plus fondamentale, aujourd'hui OUVERTE — A0) avant de se fier à un diagnostic f1_buy-cadré ADR-0099 Inv 2 · à porter par/avant S11

5. Artefacts durables produits

  • 3 ADR : 0097 (template rapport), 0098 (cadrage diagnostic↔déploiement), 0099 (architecture étagée existence≠sélection).
  • 1 rapport publiable (méthodo réutilisable, anonymisé).
  • 4 Stories de suivi : S08 (tooling), S09 (A6), S10 (re-cadrage), S11 (successeur). ⚠️ S11 mesure si la HPO f1_buy sur-ajuste — mais doit d'abord/en parallèle établir le maillon f1_buy → valeur économique (A0), sinon il « correctement cadre » contre un proxy non démontré et refait l'erreur un cran plus haut. S11 n'est « correctement cadré » que s'il porte la chaîne complète, pas juste « mesurer f1_buy ».
  • Le fix infra (PR #1097 / ADR-0096) — réutilisé par tous les pods compute.

6. Verdict KM

Le deliverable scientifique de S04 = négatif (pas de HP swap). Mais le rendement net du fil = fortement positif : une leçon structurelle (existence≠sélection, proxy≠transfert), une méthode réutilisable, et des gates de process qui empêchent le prochain diagnostic de refaire l'erreur. Un négatif honnête + de la connaissance durable valent mieux qu'un faux positif déployé. C'est exactement ce que la discipline était censée produire.