Importance and Rejection Sampling
Hard distributions are sampled through easy ones. Rejection throws away the mismatches, while importance keeps everything and reweights it.
Why Does This Exist?
Many distributions cannot be sampled directly. A posterior over parameters or a rare-event model has a density we can evaluate but no direct sampler, yet Monte Carlo averages need draws from exactly it. Drawing from the wrong distribution and averaging naively answers the wrong question.
Two corrections fix the mismatch. Rejection sampling draws from an easy proposal inside an envelope and discards draws that fall above the target. Importance sampling keeps every draw and multiplies it by . Both rest on integrals in probability, resampling ideas in bootstrap, and they motivate gradient-friendly samplers like Hamiltonian Monte Carlo.
The one idea you need first
Expectations are integrals. The mean of under is in discrete form. If draws come from instead, multiplying each term by restores the integral, provided wherever .
Think of It Like This
Counting fish with a biased net
A net catches big fish twice as often as their share in the lake. Throwing back catches by a rule restores fairness: keep a small fish always, keep a big one only half the time. That is rejection. Alternatively keep everything but count each big fish as half a fish in the tally. That is importance weighting.
It stops at support. If the net mesh lets every minnow escape, no rerule or reweight recovers them. The proposal must reach everywhere the target lives.
How It Actually Works
Pick a proposal that is easy to sample with wherever . For rejection, find with for all . Draw from and uniform in , and accept when . Accepted draws follow exactly, and the overall acceptance rate is .
For importance, skip . Draw from and weight each by . Then estimates the mean of under . In plain words: proposes, corrects, prices rejection.
Worked example
Values have target and uniform proposal with .
Weights are . For : . For : . For : . So .
The envelope constant is the largest weight: . Then , which covers entry by entry. Per-value acceptance is : . Overall acceptance is , so about two of three proposals survive.
The true mean is . The importance form with exact weights gives , divided by , which is . The diagram draws these three weights beside the envelope.
Code
The point is the correction factor. Unweighted proposal draws average to , while the weights move the answer to .
import numpy as np
def importance_weights(p: np.ndarray, q: np.ndarray) -> np.ndarray: return p / q # q must be positive wherever p is positive
p = np.array([0.2, 0.5, 0.3])q = np.array([1.0 / 3, 1.0 / 3, 1.0 / 3])w = importance_weights(p, q)print(np.round(w, 2)) # -> [0.6 1.5 0.9]vals = np.array([1.0, 2.0, 3.0])print(float(np.sum(vals * w) / np.sum(w))) # -> 2.1print(float(1.0 / np.max(w))) # -> 0.6666666666666666The last line is : two of three proposals accepted on average, matching the hand rate of .
Watch Out For
Proposing zero where the target is positive
If while , the weight divides by zero and rejection can never propose that . The symptom is a confidently wrong mean: the missing region never appears, variance estimates look small, and more draws do not fix it. Check support first, and fatten proposal tails until every target region gets samples.
Setting M below the true maximum
Rejection needs above everywhere, but the maximum ratio is often guessed from a short pilot run. Too-small when the truth needs over-accepts the peak at and biases the sample toward it. The symptom is a sampler that looks efficient because it rarely rejects, yet histograms pile up at the mode. Track the largest observed and add margin, or switch to importance weights which need no .
The Quick Version
- Proposal draws, weight corrects, envelope enables rejection.
- Here with uniform gives weights .
- Envelope needs , acceptance is , per-value rates are .
- Weighted mean is , exactly the target mean.
- Missing support cannot be reweighted back, and too-small biases toward the mode.