Code Architecture — World Models
This document describes the notebook structure, key functions/classes, data flow, and deliberate simplifications versus the original paper.
Notebook Structure
1. Setup & Imports
Installs torch, numpy, matplotlib. All modules implemented from scratch — no external RL framework or environment library beyond numpy/gym-free toy env.
2. Toy Environment: PointMassNav
A minimal 2D navigation environment (instead of CarRacing-v0):
- State:
(x, y)position of a point-mass in a [-1, 1]² arena - Action: 2D continuous velocity vector
(dx, dy)(clipped) - Observation: 64×64 grayscale image with the agent rendered as a bright dot + a target rendered as a cross
- Reward: −distance to target at each step; +10 on reaching target
- Episode length: 100 steps
Why PointMassNav? CarRacing-v0 requires Box2D + rendering, is GPU-heavy, and episodes take hundreds of steps. PointMassNav captures the essence — a visual observation, continuous control, sequential dynamics — in a lightweight package that trains in minutes on CPU.
3. VAE Module (“V”)
A convolutional variational autoencoder:
- Encoder: 64×64×1 → conv(32,4,2,1) → conv(64,4,2,1) → conv(128,4,2,1) → flatten → FC(256) → μ(32), logσ²(32)
- Reparameterization: z = μ + σ ⊙ ε, where ε ~ N(0, I)
- Decoder: z(32) → FC(8×8×128) → reshape → deconv(128,4,2,1) → deconv(64,4,2,1) → deconv(1,4,2,1) → 64×64×1
- Loss: BCE reconstruction + KL divergence (β=1.0)
Key shapes:
- Input frame:
(B, 1, 64, 64) - Latent z:
(B, 32) - Reconstructed frame:
(B, 1, 64, 64)
4. MDN-RNN Module (“M”)
An LSTM with a mixture-density-network output head:
- Input:
[z_t (32), a_t (2)]concatenated → 34 dims - LSTM: 1 layer, hidden_size=128, processes a sequence of (z, a) pairs
- MDN head: FC from hidden(128) → (K × (2 mean + 2 log_std + 1 mixture_weight)) where K=5 mixtures, output dim = K × 5 = 25
- MDN loss: negative log-likelihood of z_{t+1} under the predicted mixture
Data flow:
- Collect random rollouts in the real env
- Encode all frames through trained VAE → z sequences
- Train MDN-RNN to predict z_{t+1} from (z_t, a_t, hidden_t)
5. Controller (“C”)
A linear policy:
- Input:
[z_t (32), h_t (128)]→ 160 dims - Output:
a_t (2)— continuous action - Parameters: 160 × 2 + 2 = 322 weights (a single linear layer, no hidden layer)
- Activation: tanh (to bound actions to [-1, 1])
6. Dream Environment
A DreamEnv class that replaces the real simulator:
- `reset(): Sample initial z_0 from the VAE prior (or from a random real frame), reset LSTM hidden state h_0
- `step(action): Feed (z_t, a_t) to MDN-RNN → get next z distribution → sample z_{t+1}, update h_{t+1}. Reward = −||decoded_z − target||² (or proxy reward from latent space).
- The controller never sees real pixels during dream training.
7. Training Loop (CMA-ES on Controller)
- Use a simple evolutionary strategy (CMA-ES via
cmapackage, or a basic random-search evolution if cma unavailable):- Sample N controller parameter vectors from a Gaussian
- Evaluate each in the DreamEnv for M episodes
- Rank by cumulative reward, update mean/covariance
- Repeat for ~20 generations
- Result: The trained controller is then tested in the real PointMassNav environment to measure transfer.
8. Evaluation & Visualization
- Run the trained controller in both the dream and real environment
- Plot: (a) VAE reconstructions (original vs decoded frames), (b) MDN-RNN prediction error over time, (c) controller reward curves (dream vs real), (d) sample trajectories in the real env
- Print final metrics: VAE loss, MDN NLL, average real-env reward
Data Flow Summary
Real Env → collect random rollouts → frames
↓
VAE Encoder → z sequences + actions
↓
MDN-RNN trained on (z_t, a_t → z_{t+1})
↓
DreamEnv = [VAE prior + MDN-RNN dynamics]
↓
Controller trained in DreamEnv (CMA-ES)
↓
Controller tested in Real Env (transfer)
Deliberate Simplifications vs Full Paper
| Aspect | Paper | This Notebook |
|---|---|---|
| Environment | CarRacing-v0 (Box2D, top-down car) | PointMassNav (numpy 2D arena) |
| VAE latent dim | 32 (same) | 32 |
| MDN mixtures | 5 (same) | 5 |
| RNN | LSTM (same) | LSTM, hidden=128 |
| Controller | Linear (z,h → a), CMA-ES | Linear, CMA-ES (or random search) |
| Observation | 64×64 color (3ch) | 64×64 grayscale (1ch) |
| Training scale | GPU, hours | CPU, minutes |
| Dream rollout reward | From real env proxy | Proxy reward from latent distance |
The algorithm and architecture are faithful; only the environment and scale are reduced for CPU trainability.