Example 01 · Your first posterior
Start here after installation: this first tutorial teaches the complete declare → compile → sample → check loop. Infer one latent level from three measurements. The whole model is one exact block, so the posterior draws are independent and exact.
Model
A sample node contributes a prior. An observe node contributes a likelihood and attaches data. Parent references express dependencies; ordinary JAX operations live inside the functions attached to nodes.
Complete runnable script
"""Run with: python first_model.py"""
import jax
import jax.numpy as jnp
import numpyro.distributions as dist
import bayesmith as bs
DATA = jnp.array([0.8, 1.0, 1.2])
def model(data):
level = bs.sample("level", lambda: dist.Normal(0.0, 2.0))
bs.observe("signal", lambda x: dist.Normal(x, 0.5), level, obs=data)
def main():
graph = bs.trace(model, DATA)
plan = bs.compile(graph)
print(plan)
posterior = plan.sample(jax.random.key(7), num_samples=256)
print("Posterior sample shape:", posterior.samples["level"].shape)
print("Posterior mean estimate:", posterior.samples["level"].mean())
return posterior
if __name__ == "__main__":
main()
Data
Three measurements of one level, 0.8, 1.0 and 1.2, each with known noise standard deviation 0.5. The prior on the level is Normal with mean 0 and standard deviation 2.
Infer
Read the plan before the samples:
| Block | Latents | Route | Why |
|---|---|---|---|
| 0 | level | GCR exact | structurally certified; numerical check 3 scales x 3 at-points (max 0.00e+00) |
| Execution | iid draws, no chain | ||
Printed plan
block 0 {level} GCR exact structurally certified; numerical check 3 scales x 3 at-points (max 0.00e+00)
kappa=49 -> tol=2.0408163e-05, guard reachable, off by default
(require_convergence=)
exact block ['level']: sigma does not move with the block (0.000e+00 relative,
rtol=1.0e-08), so the covariance is fixed and one Wiener solve is exact
execution: iid draws, no chainfirst_model.py. Condition numbers and tolerances in the printout depend on the BLAS; block membership and routes are re-checked by the test suite. Full record.The prior is Normal, the prediction is the level itself and the noise is fixed, so the whole graph is one exact block. The execution line says each draw is independent and exact: there is no chain, no warmup and no convergence to diagnose.
See the posterior
Scroll the figure horizontally, or open it for a full-size view.
| Quantity | Closed form | Recorded draws |
|---|---|---|
| Posterior mean | 0.9796 | 0.9816 |
| Posterior sd | 0.2857 | 0.2923 |
Check
This model has a closed-form posterior. With prior standard deviation 2 and measurement standard deviation 0.5:
The mean of 256 independent draws differs from 0.9796 by Monte Carlo error with standard deviation \sigma_{\mathrm{post}}/\sqrt{256}\approx0.018.
Move to named questions and stored results
plan.sample returns a runtime posterior. The typed interface adds task identity, a compute budget, immutable metadata and run provenance. Continue to Partial structure for a model with an exact block inside NUTS, or to five statistical questions for a posterior → predictive → artifact workflow.