Chapitre 3
Apprendre au modèle à imaginer la suite
Prérequis : Chapitres 1 à 2.
Piste débutant
Comprendre une photo, ce n'est pas prédire la suivante
À la fin des Chapitres 1 et 2, l'encodeur a appris à transformer une image de Minecraft/Crafter en
une courte liste de nombres (un embedding) qui capture vraiment quelque chose de réel sur le jeu —
pas une « triche » qui s'effondre vers une seule réponse constante, mais un résumé sincère de ce
qui se passe à l'écran.
Mais savoir résumer une image, ce n'est pas la même chose que savoir jouer. Pour jouer, l'agent
doit répondre à une question plus difficile : « si j'appuie sur ce bouton maintenant, à quoi
ressemblera le monde un instant plus tard ? » C'est exactement ce que la Phase 2 de ce projet — le
world model (modèle du monde) — est construite pour répondre.
Le test du flipbook
Voici une image simple pour comprendre la différence entre un modèle qui prédit vraiment et un
modèle qui triche en ne faisant rien. Imagine un flipbook — ce petit carnet où l'on dessine une
image légèrement différente sur chaque page, pour qu'en feuilletant vite ça donne un mini-film. Il
y a deux façons très différentes de « remplir » la page suivante d'un flipbook :
- Recopier la page actuelle. Retracer le dernier dessin, sans rien changer. Techniquement, on a
produit une page suivante, et si rien ne bouge beaucoup dans la scène d'une image à l'autre,
cette « prédiction » n'aura même pas l'air si fausse.
- Dessiner vraiment ce qui se passe ensuite. Si le personnage donne un coup de bâton sur un
arbre, dessiner l'arbre avec un morceau manquant, ou un éclat de bois qui s'envole. Ça demande
une vraie compréhension de « ce qui se passe quand on fait X ».
Un world model qui se contente de recopier discrètement l'embedding de l'image précédente fait
l'équivalent, pour un flipbook, de retracer sans arrêt la même page. Il peut même obtenir un score
correct sur un test naïf, parce que dans beaucoup de jeux, la plupart des instants ne changent
pas énormément d'une image à l'autre. Le vrai test doit être : fait-il mieux que simplement
recopier ?
Le test que le projet utilise réellement
C'est exactement le contrôle utilisé par ce projet. Deux chiffres sont comparés :
- copy_loss : à quel point on se tromperait en supposant « rien ne change » — c'est-à-dire en
réutilisant littéralement l'embedding actuel comme supposition pour le suivant.
- pred_loss : à quel point le predictor entraîné se trompe réellement.
On regarde ensuite le ratio : predloss / copyloss. Si ce ratio est supérieur à 1, le
modèle est pire que ne rien faire — un signal d'alarme. S'il est nettement inférieur à 1, le
modèle bat la solution « paresseuse » — une preuve réelle qu'il a appris quelque chose sur la
cause et l'effet, et pas seulement de l'inertie.
Ce qui s'est vraiment passé
Dans les cent premières étapes d'entraînement de la Phase 2 (sur Crafter, en utilisant l'encodeur
de la Phase 1), le ratio a démarré très haut — autour de 14, ce qui veut dire que le
predictor non entraîné était quatorze fois pire que ne rien faire — puis a rapidement chuté au fur
et à mesure de l'entraînement, jusqu'à environ 1,66 à l'étape 100. C'est attendu : au tout
début, le predictor n'a rien appris encore, donc bien sûr « deviner au hasard » est pire que
« deviner que rien ne change ».
Après l'entraînement complet (30 epochs), le projet a mesuré val_pred = 0,033 contre
val_copy = 0,086 — un ratio de 0,38. Ça veut dire que l'erreur du predictor entraîné
représente bien moins de la moitié de l'erreur de la solution « ne rien faire » : une vraie preuve
que le modèle a appris une structure de cause à effet réelle dans le jeu (ce qui se passe quand on
frappe un outil, qu'on marche dans un mur, etc.), et pas seulement qu'il répète l'image
précédente.
Le projet ne s'est pas arrêté à un seul chiffre : il a aussi vérifié que ça tenait sur plusieurs
étapes imaginées d'affilée (imaginer l'étape 2 à partir de l'étape 1 imaginée, l'étape 3 à partir
de l'étape 2 imaginée, et ainsi de suite, sans jamais regarder une vraie image entre les deux). Sur
10 étapes de ce genre, la trajectoire imaginée par le predictor est restée sous la base
« ne rien faire » à chaque fois (10 fois sur 10). L'erreur grossit un peu plus on imagine loin —
c'est attendu, puisque les petites erreurs s'accumulent — mais le contrôle clé est qu'elle
n'explose pas, et qu'elle ne s'écroule pas non plus vers un zéro suspect (ce qui voudrait dire
que le predictor a appris à complètement ignorer l'action).
Pourquoi c'est important pour jouer au jeu
Une fois qu'un modèle sait imaginer de façon fiable « si je fais X, le monde ressemblera à ceci »,
il peut essayer plusieurs plans différents dans sa tête, comparer quel résultat imaginé se
rapproche le plus de ce qu'il veut, et n'agir réellement qu'ensuite — plutôt que de simplement
réagir à l'aveugle. C'est le germe de la planification, et c'est là que le projet va ensuite.
Piste expert
Objectif
La Phase 2 entraîne un predictor conditionné par l'action g(st, at) → ŝ_{t+1} par-dessus
l'encodeur figé de la Phase 1 (st = fθ(x_t), poids fixés après la Phase 1). Seul le
predictor reçoit des gradients ; la représentation de l'encodeur est traitée comme un espace cible
stable, ce qui se justifie directement par les garanties anti-collapse établies au Chapitre 02 —
une cible qui a déjà une variance saine et non dégénérée (~1,15 mesurée au moment de la sonde
Phase 1) est intrinsèquement difficile à faire collapser, puisque VICReg n'est même pas réappliqué
ici.
Architecture
class ActionConditionedPredictor(nn.Module):
def __init__(self, embed_dim=128, n_actions=17, action_dim=32):
self.action_embed = nn.Embedding(n_actions, action_dim)
self.net = nn.Sequential(
nn.Linear(embed_dim + action_dim, 256), nn.GELU(),
nn.Linear(256, 256), nn.GELU(),
nn.Linear(256, embed_dim),
)
~140K paramètres — délibérément petit comparé aux 688K paramètres de l'encodeur de la Phase 1
(docs/04worldmodel.md). L'intention de design : la capacité représentationnelle pour
« comprendre la scène » doit vivre dans l'encodeur ; le rôle du predictor est étroitement limité à
la dynamique de transition. Un predictor surdimensionné risquerait de compenser les faiblesses de
l'encodeur plutôt que de les révéler, ce qui brouillerait la séparation entre les gates Phase 1 et
Phase 2. GELU est utilisé plutôt que ReLU pour des gradients plus lisses sur des entrées
d'embedding centrées sur zéro (pas de zone à zéro dur qui bloque la rétropropagation pour de
petites activations négatives).
Perte
L = MSE(ŝ_{t+1}, s_{t+1}) = ‖ g(s_t, a_t) - f_θ(x_{t+1}) ‖²
Un simple MSE latent contre la sortie de l'encodeur figé sur l'image suivante réelle — pas de
terme VICReg ici (contraste avec l'objectif composé de la Phase 1 au Chapitre 02) ; les garanties
anti-collapse de la Phase 1 sont héritées, pas re-dérivées.
La base de référence et la métrique du gate
copy_loss = MSE(s_t, s_{t+1}) # base de référence « rien ne change »
pred_loss = MSE(ŝ_{t+1}, s_{t+1}) # erreur du predictor entraîné
ratio = pred_loss / copy_loss
ratio > 1 → le predictor fait moins bien que la base de référence à état constant (gate raté).
ratio < 1 → le predictor bat le « copy-last » (gate validé). Cette métrique de ratio
(valpred/valcopy) est la même construction introduite par LeWorldModel (Maes, Le Lidec,
Scieur, LeCun, Balestriero, arXiv:2603.19312, 2026) — le design du gate Phase 2 de Mine-JEPA suit
directement cette convention d'évaluation, et le projet utilise plus tard un ratio empirique
« sweet spot » documenté (~0,93, tiré de l'ablation Phase 4) comme mise en garde contre l'idée
qu'un ratio plus bas serait toujours meilleur — une nuance simplement signalée ici comme un
pointeur vers un chapitre futur, pas retro-appliquée au résultat de ce chapitre sur Crafter Phase
2, qui se juge sur ses propres critères de gate.
Trajectoire d'entraînement mesurée (100 premières étapes, Crafter, encodeur Phase 1 figé val_loss=0,080)
| Step | pred_loss | copy_loss | ratio |
|---|---|---|---|
| 20 | 1.0193 | 0.0710 | 14.36 |
| 40 | 0.5721 | 0.0905 | 6.32 |
| 60 | 0.2819 | 0.1015 | 2.78 |
| 80 | 0.1877 | 0.1026 | 1.83 |
| 100 | 0.1338 | 0.0806 | 1.66 |
La descente rapide en début d'entraînement (14,4x → 1,66x en 100 étapes) reflète le fait que le
predictor capture très vite le mode de transition le plus fréquent (quasi-identité — l'agent bouge
souvent très peu d'une image à l'autre dans Crafter), cohérent avec le fait que copy_loss est
elle-même une base de référence assez forte au début.
Résultat du gate Phase 2 (CLAUDE.md, après le run complet de 30 epochs)
valpred=0,033 contre valcopy=0,086 → ratio=0,38 (0,033/0,086 = 0,384, arrondi à 0,38 —
c'est la valeur exacte rapportée par CLAUDE.md). Ce même gate liste, sur une ligne distincte,
« erreur latente à 1 pas < base de référence : ratio 0,367 » — un second chiffre issu d'une mesure
séparée (le check 1-step de eval_wm.py), pas une reformulation du premier ; les deux figurent
explicitement dans CLAUDE.md et sont rapportés ici tels quels, sans tenter de les faire
coïncider artificiellement. Ce gate passe la barre ratio < 1,0 avec une large marge. Le gate de
rollout multi-étapes (scripts/eval_wm.py) a en plus confirmé 10/10 k (k=1..10) avec une
erreur de rollout restant sous la base de référence à chaque étape — c'est-à-dire que l'imagination
latente n'explose pas et ne dégénère pas vers une insensibilité totale à l'action sur un horizon
déroulé de 10 étapes :
s_1 = g(s_0, a_0); s_2 = g(s_1, a_1); ...; s_k = g(s_{k-1}, a_{k-1})
L'accumulation d'erreur avec k croissant est attendue (erreur composée à chaque étape) et n'est
pas en elle-même une signature de défaillance ; les signatures de défaillance explicitement
surveillées par le projet sont soit la divergence (erreur qui explose plus vite que la base de
référence), soit le collapse du predictor vers l'invariance à l'action (apprendre à ignorer a_t,
ce qui se traduirait par un ŝ_{t+1} restant presque identique pour des actions différentes
depuis le même s_t) — le résultat 10/10 sous la base de référence est incompatible avec l'une ou
l'autre.
Note sur l'interprétation du ratio pour la suite
Ce chapitre rapporte le gate Phase 2 tel qu'il est : ratio=0,38 passe le gate nettement. Une phase
ultérieure de ce projet (Phase 4, ablation MineRL) a trouvé qu'un ratio plus bas n'est pas
monotonement « meilleur » pour le succès de la planification en aval — un world model surentraîné
avec un ratio plus bas (~0,88) s'est comporté moins bien qu'un modèle avec un ratio plus haut
(~0,93). Ce constat est spécifique au world model conditionné par l'action de MineRL et au cadre
de planification de la Phase 4 ; il est signalé ici comme un pointeur vers l'avant, pas
rétro-appliqué au résultat Crafter de la Phase 2 de ce chapitre, qui reste valide sur ses propres
critères.
Références (vérifiées, tirées de docs/references/index.md)
- Maes, Le Lidec, Scieur, LeCun, Balestriero, LeWorldModel, arXiv:2603.19312 (2026) — origine de
la convention d'évaluation ratio = valpred/valcopy adoptée ici.