Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

🖥️ Diapositives du cours — Séance 27 (ven. 4 déc.)

La reproductibilité est le ticket d’entrée de la confiance en science computationnelle. Si votre résultat ne peut pas être régénéré à partir de vos données et de votre code, c’est une anecdote, si belle que soit la figure.

Définitions : reproductibilité et réplicabilité

Les définitions varient d’un domaine à l’autre. Nous adoptons celles du rapport 2019 des National Academies, Reproducibility and Replicability in Science engineering2019confidence :

Deux termes voisins tirés du même rapport : la vérification demande si le code est correct, la validation demande si le modèle prédit bien des données sur lesquelles il n’a pas été construit. Attention au piège : un bogue se reproduit parfaitement. La reproductibilité exacte ne certifie pas la justesse — elle certifie que le flux de calcul est déterministe et complet. C’est la validation sur données réservées (la discipline des ensembles de test cachés du chapitre 3) qui rattrape une erreur reproductible.

Pour une analyse reproductible, le rapport demande aux scientifiques de fournir trois choses :

En apprentissage automatique, la reproductibilité s’accepte généralement à l’intérieur d’une tolérance annoncée plutôt que bit à bit, parce que l’entraînement comporte de l’aléa et du non-déterminisme en virgule flottante. Décider quelle tolérance est acceptable fait partie de votre travail de scientifique ; nous y revenons plus bas.

Pourquoi les enjeux ont grandi quand les agents se sont mis à écrire du code

Jusqu’à récemment, la principale menace pour la reproductibilité était la négligence humaine : une cellule de carnet exécutée dans le désordre et non consignée, un CSV édité à la main, un « final_v3_REAL.ipynb ». Ces menaces existent toujours. La nouveauté, c’est l’échelle. Un agent peut engendrer une analyse complète — téléchargement des données, construction des caractéristiques, modèle, figures, prose — en quelques minutes. La sortie est fluide et cohérente avec elle-même. Elle peut aussi être fausse d’une manière que cette fluidité masque : une caractéristique qui fuit, un jeu de données filtré qui a silencieusement écarté les cas difficiles, une métrique calculée sur la partition d’entraînement.

Vous ne pouvez pas relire du code produit par un agent au rythme où l’agent le produit. Ce que vous pouvez faire, c’est rendre les vérifications exécutables. Un environnement épinglé garantit que le code de l’agent tournera demain contre les mêmes bibliothèques. Des transformations scriptées garantissent que chaque étape, des données brutes à la figure, est inspectable et réexécutable. L’intégration continue garantit que chaque changement est réexécuté avant d’être intégré. C’est le fil de tout le chapitre : quand vous déléguez la frappe, vous ne devez pas déléguer la vérification. La politique IA du cours (chapitre 1.8) exige que vous puissiez défendre chaque ligne que vous rendez ; les pratiques ci-dessous sont ce qui rend cette défense possible pour du code que vous n’avez pas écrit à la main.

La pile de la reproductibilité

Cinq couches, en partant du sol.

1. Épinglage de l’environnement

« Ça marche sur ma machine » veut généralement dire « ça marche avec les versions de bibliothèques de ma machine ». Les solveurs, les valeurs par défaut et jusqu’aux flux de nombres aléatoires changent d’une version à l’autre. Le remède est un verrou : une liste lisible par machine des versions exactes de paquets, qu’un outil peut recréer n’importe où.

Trois outils courants :

Ce livre est son propre exemple traité. La racine du dépôt contient un pixi.toml qui déclare la chaîne d’outils :

[dependencies]
python = "3.12.*"
numpy = ">=2.0"
pandas = ">=2.2"
scikit-learn = ">=1.6"
pytorch = ">=2.4"
obspy = ">=1.4"
# ...

[pypi-dependencies]
mlgeo-synth = { path = ".", editable = true }

Les contraintes déclarées sont lâches (>=), mais le pixi.lock validé les résout en versions exactes. Chaque étudiante et étudiant, chaque exécuteur d’intégration continue et chaque agent travaillant dans ce dépôt exécute la même pile. Quand nous mettons à jour une bibliothèque, le fichier de verrouillage change dans un commit — l’environnement a une histoire, comme le code.

Pour votre projet : validez le manifeste et le fichier de verrouillage. Un environment.yml sans versions est une suggestion, pas un environnement.

2. Graines aléatoires et déterminisme

L’aléa entre en ML par de nombreuses portes : mélange des données, partitions entraînement/test, initialisation des poids, dropout (l’extinction aléatoire de neurones pendant l’entraînement, leçon 4.2), optimiseurs stochastiques. Contrôlez-le explicitement :

import numpy as np
import torch

rng = np.random.default_rng(42)   # NumPy: pass rng around, do not use global state
torch.manual_seed(42)             # PyTorch: CPU and GPU generators

Préférez np.random.default_rng(seed) au np.random.seed() hérité : un objet Generator est local, donc deux parties de votre code ne peuvent pas silencieusement partager et perturber un même flux global. Dans scikit-learn, passez random_state= à chaque estimateur et à chaque séparateur qui l’accepte.

Connaissez les limites. Sur GPU, certaines opérations emploient des algorithmes non déterministes pour aller plus vite (opérations atomiques dans les réductions, autotuning de cuDNN). torch.use_deterministic_algorithms(True) force des noyaux déterministes là où ils existent, au prix de la performance, et lève une erreur là où ils n’existent pas. Les réductions parallèles peuvent aussi différer d’un matériel à l’autre, parce que l’addition en virgule flottante n’est pas associative. La position pratique : rendez déterministe tout ce qui peut l’être à peu de frais, puis mesurez la variance résiduelle d’une exécution à l’autre et rapportez vos résultats avec cette dispersion. Une amélioration annoncée plus petite que votre variance d’une graine à l’autre n’est pas un résultat. L’exercice de 5.2 quantifie exactement cela.

3. Les données brutes sont immuables ; toute transformation est scriptée

Le répertoire des données brutes est en lecture seule. Personne — ni vous, ni un agent — n’édite un fichier brut. Tout changement de forme (nettoyage, rééchantillonnage, extraction de caractéristiques, étiquetage) est un script qui lit dans data/raw/ et écrit dans data/processed/. Si les données traitées deviennent douteuses, vous les supprimez et vous réexécutez les scripts. C’est la discipline des données prêtes pour l’IA du chapitre 2, reformulée en règle de système de fichiers, et c’est la pratique de reproductibilité la moins chère qui existe. Corollaire : si une étape n’a eu lieu que dans une cellule de carnet que vous avez depuis écrasée, elle n’a pas eu lieu.

4. Les conteneurs, en un paragraphe

Les fichiers de verrouillage épinglent vos paquets, mais pas le système d’exploitation, les bibliothèques système ni les compilateurs qui les portent. Les conteneurs (Docker, Apptainer/Singularity sur HPC) figent toute cette couche dans une image exécutable n’importe où. Pour la plupart des projets du cours, un fichier de verrouillage suffit ; passez au conteneur quand vous devez tourner sur une grappe (cluster) que vous ne contrôlez pas, livrer un service, ou archiver un résultat sur le long terme (revues et archives acceptent de plus en plus une image à côté du code). Même principe, un cran plus bas dans la pile.

5. Vérifications exécutables : l’intégration continue de ce livre

La revendication de reproductibilité la plus forte est celle qu’une machine vérifie à chaque changement. La construction de ce livre est l’étude de cas : un workflow (flux de travail) GitHub Actions (.github/workflows/build.yaml) s’exécute à chaque pull request, installe l’environnement verrouillé par pixi, et exécute tous les carnets du livre pendant la construction MyST (myst build --execute --html). Si une cellule de code lève une erreur — parce qu’une bibliothèque a changé, qu’un jeu de données a déménagé ou qu’une modification a cassé une cellule antérieure — la construction échoue et la pull request ne peut pas être fusionnée. Un vérificateur de liens tourne dans le même travail.

La conséquence est une garantie que la prose seule ne pourrait jamais donner : chaque résultat que vous voyez dans ce livre a été calculé, de zéro, dans un environnement propre, à la validation que vous êtes en train de lire. La section 5.3 montre comment recopier ce motif dans le dépôt de votre propre projet, et le classement de la classe (chapitre 3.5) transforme la même idée en notation : votre soumission, c’est ce que l’intégration continue parvient à exécuter, rien de plus.

Liste de contrôle

Avant d’affirmer qu’un résultat est reproductible, vérifiez :

Pour aller plus loin

References
  1. Reproducibility and Replicability in Science. (2019). National Academies Press. 10.17226/25303