Computing Library › Worked Examples
Worked Examples

Sampling with Metropolis-Hastings

Draw samples from a distribution you can only evaluate up to a constant, using a random walk with an accept-reject rule.

The problem it solves

Often you know a probability density p(x) only up to normalization - you can compute p(x) but not the integral that scales it. Metropolis-Hastings builds a Markov chain whose stationary distribution is exactly p, using only ratios where the unknown constant cancels.

The algorithm

Kronos motion — training from sim
python
import numpy as np
target=lambda x: np.exp(-0.5*x*x)     # unnormalized N(0,1)
x=0.0; samples=[]
for i in range(100000):
    xp=x+np.random.randn()*1.0
    if np.random.rand()<target(xp)/target(x): x=xp
    samples.append(x)
s=np.array(samples[1000:])            # drop burn-in
print(round(s.mean(),3), round(s.std(),3))  # ~0, ~1

Practical concerns

The step size must be tuned: too small and the chain crawls with high autocorrelation; too large and most proposals are rejected. An acceptance rate near 0.234 is a rule of thumb for high-dimensional targets. Early samples are discarded as burn-in while the chain forgets its starting point.

Where it matters

Metropolis-Hastings underpins Bayesian inference, statistical mechanics simulations, and any setting where the posterior or Boltzmann distribution is known only up to a constant. Modern samplers like Hamiltonian Monte Carlo refine the proposal to explore faster, but the accept-reject core is the same.