Step 3 - Sample the Posterior (MCMC)
Notation
The model from Step 2 has no closed-form posterior available here by choice (see MCMC — Why MCMC for this project), so the posterior for $(\mu_i, \sigma_i^2)$, $i \in {1,2,3}$, is instead approximated by drawing correlated samples with NUTS (the No-U-Turn Sampler, PyMC's default gradient-based MCMC algorithm).
Multiple independent chains are run from different starting points; each chain discards an initial "tuning" period (used by the sampler to adapt its step size) before its draws are kept. The output is not the posterior itself but a large set of samples whose distribution approximates it — Step 4 checks whether that approximation is trustworthy before anything downstream relies on it.
step 1 - run the sampler
%run ./bayesian/step3_sample.py
trace = sample_posterior()
Python
filename: step3_sample.py
import pymc as pm
from bayesian.step2_model import build_model
'''
draws samples from the posterior via MCMC (NUTS), for the model built in step 2.
returns an arviz InferenceData trace, used by step 4 for convergence diagnostics.
'''
def sample_posterior(draws=2000, tune=1000, chains=4, random_seed=42):
model = build_model()
with model:
trace = pm.sample(draws=draws, tune=tune, chains=chains, random_seed=random_seed)
return trace
runs NUTS over the Step 2 model, returning an arviz InferenceData trace for Step 4's diagnostics