Skip to content
AI360Xpert
Beta

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.

MuZero searches inside its learned model: PUCT scores 1.55 for a1 against 1.10 for a2, the dynamics step pays 0.5, and backup lifts Q(a1) from 1.20 to 1.475
MuZero searches inside its learned model: PUCT scores 1.55 for a1 against 1.10 for a2, the dynamics step pays 0.5, and backup lifts Q(a1) from 1.20 to 1.475

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 p\mathbf{p}, the value vv, and the reward rr. 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: Q(s,a)Q(s, a) plus the prior P(s,a)P(s, a) 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 hh encodes past observations into a root hidden state s0s^0. The dynamics gg steps the hidden state forward: (rk,sk)=g(sk−1,ak)(r^k, s^k) = g(s^{k-1}, a^k), predicting the immediate reward and next hidden state with no obligation to decode pixels. The prediction ff reads any hidden state out: (pk,vk)=f(sk)(\mathbf{p}^k, v^k) = f(s^k), a policy prior plus a value estimate.

Search runs MCTS entirely among hidden states. Selection maximizes the PUCT score:

score(s,a)=Q(s,a)+c⋅P(s,a)⋅N(s)1+N(s,a)\text{score}(s, a) = Q(s, a) + c \cdot P(s, a) \cdot \frac{\sqrt{N(s)}}{1 + N(s, a)}

QQ exploits, the prior PP steers toward plausible moves, and the fraction explores the unvisited. Because rewards differ wildly between games, MuZero min-max normalizes every QQ into [0,1][0, 1] from the tree's own observed range before scoring. Expansion calls gg, evaluation calls ff, and backup carries G=r+γvG = r + \gamma v up the path into running averages. After search the real move is sampled from visit counts with a temperature TT.

Learning without reconstructing

Training unrolls the model K=5K = 5 steps along real trajectories and matches three targets: the search visit distribution for policy, bootstrapped nn-step returns for value, and observed rewards for rr, plus weight regularization. Gradients flow back through gg into hh, 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 c=1.0c = 1.0, γ=0.9\gamma = 0.9, parent visits 44. Edges: a1a_1 has Q=1.2Q = 1.2, prior 0.70.7, N=3N = 3; a2a_2 has Q=0.8Q = 0.8, prior 0.30.3, N=1N = 1. Since 4=2\sqrt{4} = 2:

U(a1)=1.0×0.7×2/4=0.3500,score=1.2+0.35=1.5500U(a_1) = 1.0 \times 0.7 \times 2 / 4 = 0.3500, \quad \text{score} = 1.2 + 0.35 = 1.5500 U(a2)=1.0×0.3×2/2=0.3000,score=0.8+0.30=1.1000U(a_2) = 1.0 \times 0.3 \times 2 / 2 = 0.3000, \quad \text{score} = 0.8 + 0.30 = 1.1000

Search picks a1a_1. Dynamics predicts r1=0.5r^1 = 0.5 with next hidden state, prediction returns leaf value v1=2.0v^1 = 2.0. The backup return is G=0.5+0.9×2.0=2.3G = 0.5 + 0.9 \times 2.0 = 2.3, and the edge average moves from 3×1.2=3.63 \times 1.2 = 3.6 over 33 visits to 5.95.9 over 44:

Q(a1)=5.9/4=1.4750Q(a_1) = 5.9 / 4 = 1.4750

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.4750

The printout matches the hand computation step for step: 1.551.55 against 1.101.10, backup 2.32.3, updated QQ of 1.4751.475.

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 K=5K = 5 so gradients stay well behaved.

One raw Q scale across games with different rewards

Board wins pay 11 while Atari titles pay thousands, so raw QQ 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 cc. Fix: track the tree's own minimum and maximum QQ and normalize every score into [0,1][0, 1] 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: hh encodes observations, gg steps hidden states with rewards, ff 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 QQ values and backs r+γvr + \gamma v up each path.
  • Short K=5K = 5 training unrolls and hidden state normalization keep imagined rollouts from diverging.