MCMC by editing executions · independent and single-site proposals · addressing · the acceptance ratio
2026-06-22
\[ \newcommand\given{{\,\vert\,}} \]
MCMC builds a Markov chain whose stationary distribution is the posterior \(p(X \given y)\). We estimate any \(\mathbb{E}[r(X)]\) by averaging \(r\) along the chain, using only ratios of the unnormalized target \(p(y, X)\), never the evidence \(p(y)\).
Metropolis-Hastings is one recipe for such a chain. From the current state \(X\):
The state is an execution trace
In a PPL the chain’s state is the trace \(\mathcal{X}\): the random choices a run made. A proposal re-runs the program. Today we build two of them: independent (a whole fresh run from the prior) and single-site (change one choice, reuse the rest).
In the likelihood-weighting activity you measured the ESS with a prior sitting far from the data:
There run(program, seed) returns (value, log_w) with \(\log W = \log p(y \given X)\) (only observe contributes, since the prior is the proposal).
In the same notebook, implement independent MH and run it here. The chain barely moves: explain why, in terms of what MH does with a proposal that likelihood weighting would merely down-weight.
def independent_mh(program, S=20000, seed=0):
rng = np.random.default_rng(seed)
x, logw = run(program, seed=0) # current run
chain = []
accept = 0
for i in range(S):
x2, logw2 = run(program, seed=i+1) # propose a fresh run
if np.log(rng.random()) < logw2 - logw: # accept w.p. min(1, W'/W)
x, logw = x2, logw2
accept += 1
chain.append(x)
print("acceptance rate:", accept / S)
return np.array(chain)run.Eight bits: each bit is \(1\) when a fresh uniform(0,1) falls below \(0.5\), else \(0\). We observe their sum near \(7\), a \(\mathcal{N}(7, 1)\) likelihood.
(let [b1 (if (< (sample (uniform-continuous 0 1)) 0.5) 1 0)
b2 (if (< (sample (uniform-continuous 0 1)) 0.5) 1 0)
b3 (if (< (sample (uniform-continuous 0 1)) 0.5) 1 0)
b4 (if (< (sample (uniform-continuous 0 1)) 0.5) 1 0)
b5 (if (< (sample (uniform-continuous 0 1)) 0.5) 1 0)
b6 (if (< (sample (uniform-continuous 0 1)) 0.5) 1 0)
b7 (if (< (sample (uniform-continuous 0 1)) 0.5) 1 0)
b8 (if (< (sample (uniform-continuous 0 1)) 0.5) 1 0)
total (+ b1 b2 b3 b4 b5 b6 b7 b8)]
(observe (normal 7 1) total) ; soft evidence: the sum is near 7
total)Why single-site fits
Eight latent choices, one uniform per bit. A whole-run proposal must land all eight at once, and the prior rarely puts the sum near \(7\). Single-site MH instead flips one bit and reuses the other seven, so progress compounds bit by bit.
Reading
Focus while reading
observe defines an intermediate target densityPlan ahead for Friday
Friday moves to Chapter 5: recursion, higher-order functions, dynamic structure. Start reading now.
Solutions
Introduction to Probabilistic Programming