# Kernodeck Reprise v1 — un checkpoint réellement relancé

Cet exercice original apprend une petite relation numérique sur 24 lignes synthétiques. Son objectif est de **vérifier la reprise d’un entraînement**, pas d’obtenir le meilleur modèle ou de mesurer un GPU. Le calcul est explicitement forcé sur **CPU**, en `float64`, avec un thread PyTorch.

Le contrôle compare 10 étapes continues à 5 étapes, un checkpoint, puis 5 nouvelles étapes dans **un autre processus Python**. Un quatrième processus omet volontairement la restauration des générateurs aléatoires : sa dérive doit être détectée. Aucune ressource distante, donnée client ou poids préentraîné n’est téléchargé.

## Prérequis

- Un environnement Python avec PyTorch et NumPy déjà installés. La preuve fournie a été exécutée avec **Python 3.14.6, PyTorch 2.11.0+cu128 et NumPy 2.4.4**.
- Environ 1 Mo disponible pour les quatre petits dossiers de sortie. Les dépendances Python occupent leur propre espace.
- Exécuter les commandes depuis le dossier extrait `kernodeck-reprise-v1`.

Le suffixe `+cu128` décrit le paquet présent lors du test ; il ne signifie pas que cet exercice a utilisé CUDA. **Aucun calcul CUDA, ROCm, AMP, multicarte ou distribué n’est validé par cette ressource.** Elle n’utilise pas de workers DataLoader. Un autre environnement doit produire sa propre preuve ; l’égalité n’est pas promise entre versions ou plateformes.

## La commande de vérification

```console
python -B verify_resume.py --output runs/preuve-cpu
```

`-B` évite les caches de bytecode dans le dossier du projet. Le répertoire de sortie doit être nouveau : aucun essai existant n’est écrasé. Pour recommencer, utilisez par exemple `runs/preuve-cpu-2`.

Le programme exécute quatre commandes avec le même interpréteur Python, puis écrit `runs/preuve-cpu/verification.json`. Une exécution complète attend :

```json
{"device":"cpu","all_checks_passed":true,"positive":true,"negative_divergence_detected":true,"report":"verification.json"}
```

Le code de sortie vaut **0** si le protocole réussit, **1** si la comparaison échoue, **2** si la vérification n’a pas pu être terminée. Le succès exige à la fois la reprise positive et l’échec observable du contrôle négatif. Un fichier de checkpoint simplement présent ne suffit pas.

## Faire les trois étapes à la main

```console
python -B train.py --steps 10 --output runs/continu
python -B train.py --steps 5 --output runs/coupure
python -B train.py --steps 5 --resume runs/coupure/checkpoint.pt --output runs/reprise
```

Chaque ligne lance un processus distinct. `--steps` signifie **étapes supplémentaires**, donc la troisième commande termine à l’étape 10. Chaque dossier contient `checkpoint.pt`, son empreinte `checkpoint.pt.sha256` et un résumé lisible `summary.json`. Les checkpoints sont créés par l’exercice lors de l’exécution ; ils ne sont pas distribués dans l’archive.

Pour observer le cas incomplet, utilisez un nouveau dossier :

```console
python -B train.py --steps 5 --resume runs/coupure/checkpoint.pt --omit-rng-restore --output runs/reprise-incomplete
```

Cette dernière commande peut terminer sans erreur Python. **Cela ne prouve pas une reprise correcte.** La commande `verify_resume.py` compare les résultats et constate la différence.

## Ce que le modèle fait réellement

`data.csv` contient une grille de deux variables et une cible synthétique : `target = 0.7*x1 - 0.4*x2 + 0.15*x1*x2 + 0.1`. Elle n’imite aucun relevé client. Le réseau comporte deux entrées, une couche de huit neurones, `Tanh`, un dropout de 0,25 et une sortie, soit 33 paramètres.

L’entraînement utilise Adam avec un taux initial de 0,03. StepLR divise ce taux par deux toutes les trois étapes. Chaque batch comporte quatre lignes : 10 étapes consomment donc 40 observations, en parcourant de nouveau certaines lignes après la première époque. La permutation, l’époque, le curseur et le nombre d’observations consommées sont conservés. À la coupure après cinq étapes, le curseur vaut 20 sur 24 : la reprise a lieu **à l’intérieur du parcours de données**.

Trois sources aléatoires influencent le travail : Python règle un léger gain sur les entrées, un générateur NumPy PCG64 produit le bruit et les permutations, PyTorch produit le dropout. Fixer de nouveau le seed initial ne reconstitue pas les états atteints à la coupure.

## Ce que le checkpoint conserve et dans quel ordre il est relu

Le dictionnaire contient les poids, l’état Adam, l’état StepLR, la progression des données, les trois RNG, l’historique des pertes et taux, ainsi que les empreintes du code et du CSV. Le mode `train()` est rétabli pour la reprise ; la mesure de MSE finale utilise `eval()` et ne consomme pas le dropout.

À la reprise, le code construit d’abord le modèle, l’optimiseur et **l’ordonnanceur**, puis charge les poids, l’état de l’ordonnanceur et celui de l’optimiseur. Les RNG sont restaurés en dernier, après les constructions qui consomment de l’aléatoire. Ce choix respecte l’avertissement de la documentation [Optimizer.load_state_dict](https://docs.pytorch.org/docs/2.11/generated/torch.optim.Optimizer.load_state_dict.html).

L’état Python est une structure de primitives. PCG64 fournit un dictionnaire d’entiers et de chaînes ; aucun objet `ndarray` NumPy n’est sérialisé comme état RNG. L’état PyTorch CPU est un tenseur d’octets. Les prochains tirages sont contrôlés sans modifier l’état sauvegardé.

## Lecture de la preuve et tolérance

`verification-cpu.json` est la preuve publique issue d’une exécution réelle de cette version. `source` contient les SHA-256 des scripts et du CSV. `protocol` décrit les quatre processus, la précision et la tolérance. `resume_boundary` vérifie le prochain tirage de chaque RNG et le prochain taux utilisé après coupure.

La comparaison exige le même ordre de lignes, la même progression et le même état d’ordonnanceur. L’écart absolu maximal accepté pour les poids, l’état de l’optimiseur, les pertes, la MSE et les taux est **1e-12**, sans tolérance relative (`rtol=0`). Le rapport conserve les écarts mesurés, même lorsqu’ils valent zéro. Il vérifie également le prochain tirage des RNG à la fin des deux parcours.

Le contrôle négatif doit montrer que l’oubli des RNG change le résultat. Sa MSE peut être plus basse ou plus haute : ce test vérifie une trajectoire de reprise, pas un classement de qualité. Une divergence attendue donne donc `passed: false` dans ce sous-test et `divergence_detected: true` ; le protocole global peut alors réussir.

## Charger seulement son propre checkpoint

Le chargeur utilise explicitement `torch.load(..., map_location="cpu", weights_only=True)` et ne propose aucun fallback vers `weights_only=False`. Il vérifie d’abord l’empreinte associée, limite la taille et vérifie le schéma, les versions, le code et les données. Il rejette un état incomplet au lieu de réinitialiser silencieusement une partie de l’entraînement.

Utilisez uniquement les checkpoints que **vous avez créés avec cet exercice et conservés sous votre contrôle**. L’empreinte sert à détecter une modification ; elle n’authentifie pas un expéditeur. Le chargement restreint ne rend pas un fichier inconnu digne de confiance. Voir [torch.load](https://docs.pytorch.org/docs/2.11/generated/torch.load.html) et [la sérialisation PyTorch](https://docs.pytorch.org/docs/2.11/notes/serialization.html).

## Adapter l’exercice à votre projet

Identifiez les états que votre propre entraînement consomme réellement : sampler, augmentation, optimiseur, ordonnanceur et générateurs particuliers. Si vous utilisez AMP, ajoutez l’état du scaler à une frontière cohérente ; cet exercice ne le fait pas. Un entraînement distribué demande aussi de traiter ses processus et leur répartition de données.

Ne déduisez pas de cette petite preuve une durée de location, un débit, une empreinte VRAM ou une garantie de reprise pour un modèle différent. Reprenez la méthode : jeu court représentatif, coupure au milieu du travail, autre processus, comparaison explicite et contrôle négatif.

## Contenu et licences

- `train.py`, `verify_resume.py`, cette documentation et le manifeste : licence MIT, voir `LICENSE-MIT.txt`.
- `data.csv` : données synthétiques originales proposées sous CC0 1.0, voir `DATA-LICENSE-CC0.txt`.
- `verification-cpu.json` : mesures de cet exercice, sans données personnelles, environnement complet, chemins du poste, jetons ou identifiants de session.
- `manifest.json` : liste exacte des fichiers distribués et de leurs SHA-256. Le manifeste ne se référence pas lui-même.
- `SOURCES.md` : liens officiels et limites documentaires.

Les dépendances PyTorch, NumPy et Python conservent leurs propres licences. Elles ne sont pas redistribuées dans le ZIP.


## Présentation Kernodeck et compatibilité du projet

Cette réédition du 25 septembre 2026 actualise le nom de l’archive, la documentation et la marque. Les scripts `train.py` et `verify_resume.py`, le CSV et `verification-cpu.json` restent identiques à la livraison exécutée le 24 septembre 2026. Le champ technique `project` conserve son identifiant pour les lecteurs de rapports existants. Aucun calcul ni contrôle CPU/GPU n’a été relancé pour cette réédition.
