CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pystan

Python interface to Stan, a package for Bayesian inference

Pending
Overview
Eval results
Files

bayesian-sampling.mddocs/

Bayesian Sampling

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.

Capabilities

Default Sampling

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}])
    """

HMC-NUTS Sampling

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
    """

Fixed Parameter Sampling

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
    """

Usage Examples

Basic Sampling

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
)

Custom Initialization

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)

Fixed Parameter Model

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'])

Advanced Sampling Control

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

docs

bayesian-sampling.md

index.md

model-building.md

parameter-operations.md

results-analysis.md

tile.json