Python interface to Stan, a package for Bayesian inference
—
MCMC sampling methods for drawing from posterior distributions. PyStan provides multiple sampling algorithms including HMC-NUTS (Hamiltonian Monte Carlo with No-U-Turn Sampler) and fixed parameter sampling for models without parameters to estimate.
The primary sampling method using HMC-NUTS with diagonal euclidean adaptation.
def sample(self, *, num_chains: int = 4, **kwargs) -> Fit:
"""
Draw samples from the model.
Parameters in kwargs will be passed to the default sample function.
The default sample function is currently stan::services::sample::hmc_nuts_diag_e_adapt.
Parameter names are identical to those used in CmdStan.
Args:
num_chains: PyStan-specific keyword argument. Number of independent processes
to use when drawing samples. Default: 4
**kwargs: Additional parameters passed to Stan sampling function:
- num_samples (int): Number of post-warmup samples per chain. Default: 1000
- num_warmup (int): Number of warmup samples per chain. Default: 1000
- init (list): Initial parameter values for each chain
- adapt_delta (float): Target acceptance rate. Default: 0.8
- max_treedepth (int): Maximum tree depth. Default: 10
- stepsize (float): Initial step size. Default: 1.0
Returns:
Fit: Instance of Fit allowing access to draws
Examples:
User-defined initial values for parameters must be provided for each chain.
Typically they will be the same for each chain:
>>> program_code = "parameters {real y;} model {y ~ normal(0,1);}"
>>> posterior = stan.build(program_code)
>>> fit = posterior.sample(num_chains=2, init=[{"y": 3}, {"y": 3}])
"""Explicit HMC-NUTS sampling with diagonal euclidean adaptation.
def hmc_nuts_diag_e_adapt(self, *, num_chains: int = 4, **kwargs) -> Fit:
"""
Draw samples from the model using stan::services::sample::hmc_nuts_diag_e_adapt.
Parameters in kwargs will be passed to the (Python wrapper of)
stan::services::sample::hmc_nuts_diag_e_adapt. Parameter names are
identical to those used in CmdStan.
Args:
num_chains: PyStan-specific keyword argument. Number of independent processes
to use when drawing samples. Default: 4
**kwargs: Additional parameters passed to Stan sampling function
Returns:
Fit: Instance of Fit allowing access to draws
"""Sampling for models with no parameters to estimate (e.g., for generated quantities only).
def fixed_param(self, *, num_chains: int = 4, **kwargs) -> Fit:
"""
Draw samples from the model using stan::services::sample::fixed_param.
Used for models with no parameters, typically when only generated quantities
are needed or for forward simulation.
Parameters in kwargs will be passed to the (Python wrapper of)
stan::services::sample::fixed_param. Parameter names are
identical to those used in CmdStan.
Args:
num_chains: PyStan-specific keyword argument. Number of independent processes
to use when drawing samples. Default: 4
**kwargs: Additional parameters passed to Stan sampling function
Returns:
Fit: Instance of Fit allowing access to draws
"""import stan
program_code = """
parameters {
real mu;
real<lower=0> sigma;
}
model {
mu ~ normal(0, 1);
sigma ~ exponential(1);
}
"""
model = stan.build(program_code)
# Sample with default settings
fit = model.sample()
# Sample with custom settings
fit = model.sample(
num_chains=4,
num_samples=2000,
num_warmup=1000,
adapt_delta=0.95,
max_treedepth=12
)import stan
program_code = """
parameters {
real alpha;
real beta;
}
model {
alpha ~ normal(0, 10);
beta ~ normal(0, 10);
}
"""
model = stan.build(program_code)
# Provide initial values for each chain
init_values = [
{"alpha": 1.0, "beta": 0.5},
{"alpha": -1.0, "beta": 1.5},
{"alpha": 0.0, "beta": -0.5},
{"alpha": 2.0, "beta": 2.0}
]
fit = model.sample(num_chains=4, init=init_values)import stan
# Model with only generated quantities
program_code = """
generated quantities {
real y_pred = normal_rng(0, 1);
real z_pred = exponential_rng(1);
}
"""
model = stan.build(program_code)
# Use fixed_param for models without parameters
fit = model.fixed_param(num_chains=1, num_samples=1000)
print(fit['y_pred'])
print(fit['z_pred'])import stan
import numpy as np
# Hierarchical model
program_code = """
data {
int<lower=0> J;
real y[J];
real<lower=0> sigma[J];
}
parameters {
real mu;
real<lower=0> tau;
real theta[J];
}
model {
mu ~ normal(0, 5);
tau ~ cauchy(0, 5);
theta ~ normal(mu, tau);
y ~ normal(theta, sigma);
}
"""
# Eight schools data
data = {
'J': 8,
'y': [28, 8, -3, 7, -1, 1, 18, 12],
'sigma': [15, 10, 16, 11, 9, 11, 10, 18]
}
model = stan.build(program_code, data=data)
# Sample with tight adaptation for difficult geometry
fit = model.sample(
num_chains=4,
num_samples=2000,
num_warmup=2000,
adapt_delta=0.99,
max_treedepth=15,
stepsize=0.01
)Install with Tessl CLI
npx tessl i tessl/pypi-pystan