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)

Steppred_losscopy_lossratio
201.01930.071014.36
400.57210.09056.32
600.28190.10152.78
800.18770.10261.83
1000.13380.08061.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,086ratio=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.