MuZero and AlphaZero
AlphaZero plans with a perfect rulebook and deep search; MuZero learns its own compact rulebook from play and searches inside it instead.
Why Does This Exist?
AlphaZero (Silver and colleagues, 2017) mastered chess, shogi, and Go from scratch by pairing a neural network with Monte Carlo tree search. But it cheated in one respectable way: at every new node it asked the true game engine for the exact next board. Take away the rulebook, put it in front of pixels or a robot, and planning stalls because there is no simulator to query.
Early model-based RL answered by reconstructing observations, predicting next video frames pixel by pixel. That spends capacity on leaves fluttering in the background while errors compound down the imagined rollout. MuZero (Schrittwieser and colleagues, 2020) cut the knot: a planner only needs the three quantities that steer decisions, the policy , the value , and the reward . It learns a compact latent simulator for exactly those, searches inside it, and matched AlphaZero on board games while topping the Atari benchmark with no rules given. For the sibling that dreams in latent space differently, see Dreamer.
The one idea you need first
Tree search picks moves with a policy guided bonus. AlphaZero and MuZero use PUCT: plus the prior times an exploration fraction that shrinks as the edge gets visits. The network supplies the prior and the value; search sharpens both into visit counts; self-play turns those visits into the next training targets.
Think of It Like This
Two explorers in an unmapped cave
AlphaZero carries a perfect survey map and a rulebook for every door. Before each step it studies the map, tests every tunnel on paper, and strides ahead. Superb until you take the map away: then it cannot plan a single step.
MuZero carries no map, only a cane and a notebook. Tapping ahead it records three sensations per step: which ways feel open, whether the step paid or stung, and whether the air smells closer to the exit. Linked together, those notes become a mental simulator good enough to rehearse five steps ahead without seeing a single wall.
Where it stops: cane notes stay near physical space, while MuZero's hidden states are abstract vectors shaped by gradient descent, free to encode anything that predicts policy, value, and reward, and nothing else.
How It Actually Works
Three learned functions replace the simulator. The representation encodes past observations into a root hidden state . The dynamics steps the hidden state forward: , predicting the immediate reward and next hidden state with no obligation to decode pixels. The prediction reads any hidden state out: , a policy prior plus a value estimate.
Search runs MCTS entirely among hidden states. Selection maximizes the PUCT score:
exploits, the prior steers toward plausible moves, and the fraction explores the unvisited. Because rewards differ wildly between games, MuZero min-max normalizes every into from the tree's own observed range before scoring. Expansion calls , evaluation calls , and backup carries up the path into running averages. After search the real move is sampled from visit counts with a temperature .
Learning without reconstructing
Training unrolls the model steps along real trajectories and matches three targets: the search visit distribution for policy, bootstrapped -step returns for value, and observed rewards for , plus weight regularization. Gradients flow back through into , so hidden states keep exactly the information the three targets need. No pixel loss exists anywhere, which is why the model stays small and the rollouts stay honest.
Worked example
Root hidden state with , , parent visits . Edges: has , prior , ; has , prior , . Since :
Search picks . Dynamics predicts with next hidden state, prediction returns leaf value . The backup return is , and the edge average moves from over visits to over :
The diagram draws this selection, expansion, and backup with the same numbers.
Code
This snippet replays the worked example: PUCT scoring, the dynamics reward plus leaf value backup, and the averaged update.
import math
def puct(q: float, p: float, n_parent: int, n_child: int, c: float = 1.0) -> tuple[float, float]: """Exploration bonus and total PUCT score for one latent edge.""" u = c * p * math.sqrt(n_parent) / (1 + n_child) return u, q + u
u1, s1 = puct(1.2, 0.7, 4, 3)u2, s2 = puct(0.8, 0.3, 4, 1)print(f"a1: U={u1:.4f} score={s1:.4f}") # -> a1: U=0.3500 score=1.5500print(f"a2: U={u2:.4f} score={s2:.4f}") # -> a2: U=0.3000 score=1.1000g = 0.5 + 0.9 * 2.0print(f"G={g:.4f} Q={((3 * 1.2) + g) / 4:.4f}") # -> G=2.3000 Q=1.4750The printout matches the hand computation step for step: against , backup , updated of .
Watch Out For
Latent rollouts drifting off the training manifold
The dynamics function is applied repeatedly with no fresh observation to ground it, so small errors compound and deep imagined states land where the prediction head never trained. Symptom: search trees go flat or fixate on phantom lines late in training while one step predictions still look fine. Fix: normalize hidden activations each step, and train with short unrolls of so gradients stay well behaved.
One raw Q scale across games with different rewards
Board wins pay while Atari titles pay thousands, so raw values would make the PUCT bonus meaningless in one game or invisible in another. Symptom: search over explores in low reward games and under explores in high reward ones with a single . Fix: track the tree's own minimum and maximum and normalize every score into before selection, as MuZero does.
The Quick Version
- AlphaZero plans with a perfect simulator plus search; MuZero learns the simulator from play and searches inside it.
- Three networks split the job: encodes observations, steps hidden states with rewards, reads out policy and value.
- Nothing reconstructs observations; policy, value, and reward targets shape the hidden states alone.
- Latent MCTS uses PUCT selection with min-max normalized values and backs up each path.
- Short training unrolls and hidden state normalization keep imagined rollouts from diverging.