JEPA & World Models
Modern AI is converging on a single bet: that the right way to learn about the world is to predict — but in an abstract embedding space, not in pixels. This essay walks through that idea, lets you poke at every part of it, and watches a tiny model collapse and recover in real time.
What is a world model?
When you reach for a glass of water without spilling it, your brain is silently running a tiny physics simulation: how heavy the glass is, where your hand needs to go, how the water will slosh. You don't try the motion in reality first — you imagine it, then act. Predictive coding (Rao & Ballard 1999, Friston) hypothesizes the cortex maintains generative models of its sensorimotor input and minimizes prediction error. A world model is the same thing built inside a computer: the part of an agent that says “if I do X, what happens?”.
Formally, a world model is a learned function $$ f_\theta:\; (s_t,\, a_t) \;\to\; s_{t+1} $$ that maps state and action to the next state. The interesting word is “state” — almost nobody works in raw pixel space anymore.
Below is a 2D world with a moving ball. Drag the ball, drag the prediction horizon, toggle the noise. The prediction cone shows where the ball could end up. This is the intuition for why pure pixel-prediction fails over time: long-horizon futures fan out, and forcing the model to pick one pixel-perfect outcome wastes capacity.
Three families of world models are being pursued in 2026: predict embeddings (the JEPA family), predict pixels (Sora, Genie, GAIA), and learn a latent dynamics + reward model (the Dreamer line). This essay is mostly about the first — but section 8 puts them side by side.
The core JEPA idea
JEPA — Joint-Embedding Predictive Architecture — trains by predicting one embedding from another, not by predicting raw pixels. Hide half a photo of a forest. There are billions of valid pixel arrangements that all look like “a forest”. A pixel-predictor has to commit to one and is punished for every wrong leaf. A JEPA punts: “I'll predict an embedding — a compressed summary that says forest, dappled light, late afternoon. That's the part that matters.”
The loss is a regression in embedding space: $$ \mathcal{L}_{\text{JEPA}} \;=\; \big\|\, P_\psi(s_x, z) \;-\; \mathrm{sg}(s_y)\, \big\|_2^2 $$ where $s_x$ is the context embedding, $s_y$ is the target embedding produced by an EMA target encoder (no gradient flows back through it — that's $\mathrm{sg}$), and $z$ is an optional latent that absorbs irreducible uncertainty about the masked region.
Below is the centerpiece interactive of this essay. Pick an image, drag to draw a target block, and watch a real (toy) JEPA-style forward pass: tokenize → encode context → predict target embedding. Toggle the comparison with MAE-style pixel prediction to see what each is committing to.
Context Target Predictor Encoder
JEPA is not contrastive (no negatives) and is not generative (no pixel decoder). That raises a question: what stops it from learning the trivial constant solution?
The self-supervised landscape
JEPA sits in one specific corner of a busy field. Self-supervised learning splits into three big families, with characteristic tricks:
- Contrastive — SimCLR, MoCo, CPC. Pull two views together; push others apart; use InfoNCE.
- Non-contrastive joint-embedding — BYOL, DINO, SimSiam, VICReg, Barlow Twins. No negatives; collapse prevented by EMA / stop-grad / explicit regularizers.
- Masked-prediction — MAE, BEiT, data2vec, I-JEPA. Mask, predict the missing chunk (pixels, discrete tokens, or embeddings).
JEPA borrows the EMA target trick from the non-contrastive family and the masking strategy from the masked-prediction family. Drag the nodes below to rearrange the map; click any method to read its one-liner.
Watching collapse, live
The easiest way to win the JEPA loss is to output zero for every patch. Embeddings of context and target are now identical (both zero), loss is zero, and the model has learned nothing. This is representation collapse, the central problem of non-contrastive SSL. Every method has a clever fix.
The widget below trains a tiny 2-layer MLP in your browser on synthetic 2D data (four Gaussian blobs, one per quadrant) with a JEPA-style two-view loss. The two views are small random noise perturbations of the same point. You can switch the anti-collapse mechanism on the fly. Run with no tricks — the scatter implodes to a point and the singular-value spectrum drops to one nonzero value. Enable EMA + stop-grad — it doesn't.
Stop-grad here is the full SimSiam recipe: stop-grad on the target branch plus a small predictor MLP (16→32→16, ReLU) on the online branch. Without the predictor, stop-grad alone collapses (try the debug toggle). EMA target (BYOL-style, also with a predictor) is the trick I-JEPA inherits. VICReg uses explicit variance + covariance regularizers. SIGReg — the LeJEPA recipe — matches the standard-normal characteristic function at a few projection directions × evaluation points (a toy approximation of the Epps–Pulley test). None is magic: switch back to “none” mid-training and watch the scatter implode.
Debug: — turn this off to see the textbook SimSiam result: stop-grad without a predictor collapses faster than EMA.
Build it from scratch
You just saw collapse on a slider. Here's the same thing from the other end:
four short Python files, ~600 lines total, that rebuild JEPA from
nothing → naive → BYOL/I-JEPA → LeJEPA. Three of them run in
your browser right now. Click Run on a cell and watch the
scatter plot — the rank number is only one piece of the story; the
actually-visible signal is whether the four colored clusters stay separated
or smear together. Full Python in code/workshop/.
The simplest thing — and it collapses
Two views, one shared encoder. The loss is MSE directly between the two embeddings. No predictor. No EMA. No stop-grad. The simplest thing that could possibly work — and after ~1k steps the model has squashed its embedding into a low-rank subspace, regardless of what the loss says.
encoder = Encoder() # 2 → 16 → 16
opt = AdamW(encoder.parameters(), lr=1e-3)
for step in range(2000):
v1, v2, _ = make_batch()
s1 = encoder(v1) # shared encoder
s2 = encoder(v2) # gradient flows BOTH branches
loss = mse(s1, s2) # MSE directly in embedding space
loss.backward(); opt.step()
Add an EMA target — and a predictor
The BYOL/I-JEPA fix: split into online + target encoders, EMA-update the target, stop-gradient the target branch, and add a small predictor MLP on the online branch (SimSiam recipe). Three extra lines, totally different result.
online = Encoder()
target = copy.deepcopy(online) # EMA target
for p in target.parameters(): p.requires_grad = False
predictor = Predictor() # sits on the ONLINE branch
@torch.no_grad()
def ema_update(target, online, tau=0.996):
for tp, op in zip(target.parameters(), online.parameters()):
tp.data.mul_(tau).add_(op.data, alpha=1 - tau)
for step in range(2000):
s1 = online(v1) # gradient flows
with torch.no_grad():
s2 = target(v2) # stop-grad
loss = mse(predictor(s1), s2)
loss.backward(); opt.step()
ema_update(target, online, tau=0.996)
Now do it on images
Same recipe, real data. Chop a 28×28 MNIST image into 49 patches of 4×4. Pick one patch at random to be the target; the rest is the context. Encoder takes a single patch and outputs an embedding; predictor takes (context summary, target position) → predicted target embedding. That's it.
patches = patchify(image) # (B, 49, 1, 4, 4)
target_idx = torch.randint(0, 49, (B,))
target_patch = patches[arange(B), target_idx] # (B, 1, 4, 4)
context = patches.clone()
context[arange(B), target_idx] = 0 # zero out target slot
s_ctx = online(context) # (B, 49, 64)
with torch.no_grad():
s_tgt = target(target_patch.unsqueeze(1)).squeeze(1) # (B, 64)
s_hat = predictor(s_ctx, position_of(target_idx)) # (B, 64)
loss = mse(s_hat, s_tgt) # same as Attempt [2]
code/workshop/03_masked_patches.py
(runs in ~7 min on a laptop CPU).
Replace the EMA with SIGReg (LeJEPA)
Back to Attempt [1]'s simplicity — one shared encoder, no predictor, no stop-grad, no EMA — but with one regularizer added. SIGReg pushes the joint embedding distribution toward an isotropic Gaussian via characteristic-function matching on K random 1-D projections. Same downstream behavior as Attempt [2], fewer moving parts, and now there's a proof. (This is a toy SIGReg — 4 fixed t-values instead of the Gaussian-weighted Epps–Pulley integral the LeJEPA paper uses; same spirit.)
def sigreg(embeds, K=8, ts=(0.5, 1.0, 1.5, 2.0)):
e = embeds - embeds.mean(0)
e = e / e.std(0).clamp_min(1e-6) # standardize per-dim
u = torch.randn(D, K); u = u / u.norm(dim=0) # K random unit dirs
p = e @ u # project → (B, K)
loss = 0
for t in ts:
cos_p = torch.cos(t*p).mean(0)
sin_p = torch.sin(t*p).mean(0)
target_re = math.exp(-t*t/2) # N(0,1) char. func.
loss += ((cos_p - target_re)**2 + sin_p**2).mean()
return loss / len(ts)
# Training loop: shared encoder. NO predictor. NO stop-grad. NO EMA.
for step in range(2000):
s1, s2 = encoder(v1), encoder(v2)
loss = mse(s1, s2) + 1.0 * sigreg(torch.cat([s1, s2], 0))
loss.backward(); opt.step()
What we built
| # | Mechanism | Cluster separation | Linear probe |
|---|---|---|---|
[1] | naive JEPA, no tricks | arc / squashed | degrades on hard tasks |
[2] | + EMA target + stop-grad + predictor | 4 clean clusters | ~99% on 4 clusters |
[3] | [2] applied to MNIST 4×4 patches | — | ~92–95% on 10 MNIST digits |
[4] | replace EMA with SIGReg | 4 clean clusters | ~99% on 4 clusters |
The whole arc — naive → BYOL → I-JEPA → LeJEPA — is ~600 lines of Python.
Bigger encoders, bigger data, smarter masking, action-conditioning — those are quantitative,
not conceptual. Files: code/workshop/0{1..4}_*.py.
Narrative companion: topics/21-build-jepa-from-scratch.md.
A note on numbers: the live widgets above use a tiny SGD trainer with limited
steps to stay snappy in your browser, so effective-rank numbers stay around 3–5 / 16
(the 4-cluster toy can't exercise more than that). The full .py files use
AdamW for longer and reach higher rank. The visible signal in both is the same:
naive smears the clusters; EMA and SIGReg keep them separated.
I-JEPA in motion
I-JEPA (Assran et al., CVPR 2023) is the first JEPA that worked at scale on images. It uses three ViTs: a context encoder, an EMA target encoder, and a small predictor. The masking strategy is unusual: instead of tiny patches, target blocks are 4 random large rectangles (~15-20% of the image each), forcing the predictor to commit to semantic rather than local prediction.
Step through the forward pass below. Each step highlights what's happening and what the relevant tensor shapes are.
Anatomy&How the parts fit together
The same architecture, drawn the way an old service manual would draw it. Four cutaway plates of the JEPA machine — pull the parts apart, watch the spring tension on the EMA teacher, follow a single image patch through the token matrix, and tilt the energy landscape until collapse is no longer a valley. Every diagram below is custom SVG; every slider drives the picture in real time.
Note on
[CLS]: in classification-style ViTs (and at probe time)
a learned [CLS] token is prepended at row 0 to act as a sequence-summary slot.
I-JEPA / V-JEPA context encoders operate on patch tokens only — no learned
[CLS] in the input sequence. We show the CLS row greyed-out to mark it as
optional / classification-ViT only.
SIGReg vs EMA / stop-grad: these are mechanistically different and would deform the landscape in different ways. This widget only shows SIGReg's effect; EMA + stop-grad does not literally add a term to a loss surface in the same closed-form way.
Planning in latent space (V-JEPA 2 style)
V-JEPA 2 (June 2025) does two things: pretrain on 1M+ hours of video with a JEPA objective, then train a small action-conditioned predictor on 62 hours of robot data. At inference time, give the robot a goal image, encode it, and plan a short action sequence by optimizing $a_{t:t+H}$ to minimize $\|\hat{s}_{t+H} - s_{\text{goal}}\|$ through the predictor — model-predictive control with cross-entropy method in latent space.
The widget below is that exact loop on a 2D point-mass world. Click anywhere to set the goal.
The planner samples thousands of candidate action sequences in the model's latent space,
keeps the elites, and executes the first action. The grey rectangle is a wall.
It is the same code as code/toy_world_model.py, ported to JavaScript.
Honest disclosure. This toy substitutes the true 2D environment dynamics for the learned latent model — the educational point is the CEM optimization loop itself. V-JEPA 2 plans by rolling out a learned embedding-space predictor instead, and the goal is a goal image encoded into the same embedding space (not a $(x,y)$ coordinate).
This planner has no reward function, no policy network. The whole loop is: encode the current state, encode the goal image, sample latent action rollouts, keep the ones that end closest to the goal embedding, refit the action distribution to those elites. That's it. LeCun's vision in toy form.
Three paradigms, side by side
Click a card to highlight its row in the comparison table and play its mini-animation.
| Property | Predict embeddings (JEPA) | Predict pixels (Sora / Genie) | Latent dynamics + reward (Dreamer) |
|---|---|---|---|
| What's predicted | target embedding | next-frame pixels or tokens | next latent + reward |
| Loss | $\|\hat s - s\|^2$ in embedding space | diffusion or AR loss on pixels/tokens | ELBO: recon + KL + reward + continue |
| Decoder? | no | yes (huge) | yes (small) |
| Reward built in? | no (goal-image cost) | no (separate) | yes |
| Pretrain cost | low–med (1B params, ~1k GPU-days) | very high (10–50B params, >10k GPU-days) | per-env (small) |
| Best at | perception, planning, transfer | synthesis, sim data | sample-efficient RL |
The world-model races
A non-exhaustive timeline of the last eight years. Hover the cards for details.
Who is building what?
Each cell links a lab to its bet across paradigms. Hover for the names of the systems.
Open problems
Even after V-JEPA 2, Genie 3, GAIA-3, π0, DreamerV4 — the field is stuck on a small number of hard, well-known problems. Spin the wheel.
Teaching ladder
The same idea — predict in embedding space — explained at five ability levels. Drag the slider.
References & further reading
Starred items are the must-reads.
- ★ LeCun (2022). A Path Towards Autonomous Machine Intelligence. OpenReview · The JEPA blueprint.
- ★ Assran et al. (CVPR 2023). Self-Supervised Learning from Images with a Joint-Embedding Predictive Architecture (I-JEPA). arXiv:2301.08243.
- ★ Bardes et al. (2024). Revisiting Feature Prediction for Learning Visual Representations from Video (V-JEPA). arXiv:2404.08471.
- ★ Assran et al. (June 2025). V-JEPA 2: Self-Supervised Video Models Enable Understanding, Prediction and Planning. arXiv:2506.09985.
- ★ Balestriero & LeCun (Nov 2025). LeJEPA: Provable and Scalable Self-Supervised Learning Without the Heuristics. arXiv:2511.08544.
- ★ Hafner et al. (Nature 2025). Mastering Diverse Domains through World Models (DreamerV3). arXiv:2301.04104.
- Ha & Schmidhuber (2018). World Models. arXiv:1803.10122.
- Bruce et al. (ICML 2024 best paper). Genie: Generative Interactive Environments. arXiv:2402.15391.
- He et al. (2022). Masked Autoencoders Are Scalable Vision Learners (MAE). arXiv:2111.06377.
- Grill et al. (2020). Bootstrap Your Own Latent (BYOL). arXiv:2006.07733.
- Caron et al. (2021). Emerging Properties in Self-Supervised Vision Transformers (DINO). arXiv:2104.14294.
- Bardes, Ponce, LeCun (2022). VICReg. arXiv:2105.04906.
- Hafner et al. (2019). PlaNet: Learning Latent Dynamics for Planning from Pixels. arXiv:1811.04551.
- Tian, Chen, Ganguli (2021). Understanding Self-Supervised Learning Dynamics without Contrastive Pairs. arXiv:2102.06810.
- OpenAI (Feb 2024). Sora — video generation models as world simulators. openai.com.
- DeepMind (Aug 2025). Genie 3: a new frontier for world models. deepmind.google.
- Wayve (Dec 2025). GAIA-3. wayve.ai.
- Physical Intelligence (Oct 2024). π0: our first generalist policy. pi.website.
- NVIDIA (Jan 2025). Cosmos World Foundation Model Platform for Physical AI. research.nvidia.com.
- Survey: Understanding World or Predicting Future? A Comprehensive Survey of World Models, arXiv:2411.14499 (Dec 2025).