mixle.ppl package¶
mixle.ppl — an elegant probabilistic-programming surface over mixle.
A model is plain mixle construction with two new things allowed in a parameter
slot: the token free (estimate it) or another distribution (make it random). Fit
with .fit(data); query with .sample / .log_prob / .posterior.
from mixle.ppl import Normal, free m = Normal(free, free).fit(data) m.sample(100)
The 86 mixle.stats distribution classes are untouched; this is a thin, optional
dialect. See notes/ppl-syntax-spec.md.
Layout: the modeling surface and constraints are in mixle.ppl.core; the dialect
constructors (Normal/Gamma/Markov/…) in mixle.ppl.distributions; the
family/composite lowering registry in mixle.ppl._lowering (imported for its
registration side effects); fields/regression/conformal and the PDE-inverse stack in
their own modules. This package init only re-exports.
- class RandomVariable(kind, *, family=None, args=(), name=None, keys=None, dist=None, result=None, scope='shared', reparam=None)[source]
Bases:
objectThe single user-facing PPL type (immutable).
Two states:
sample(a symbolic draw: a family + argument expressions, some of which may befree) andbound(wraps a concrete fitted distribution). The verb surface is fixed and state-independent (invariant I3); validity depends on state. Construct via the family functions inmixle.pplorfit.- Parameters:
result (PosteriorResult | None)
- property certificate
The estimation certificate, when a fit attached one (penalized fits downgrade honestly; E2).
- each(by=None)[source]
Mark this prior as per-group (a random effect / local latent). Used in a parameter slot:
Normal(Normal(m, t).each(), s)is a hierarchical model.Two data layouts are supported:
nested –
each()with no argument:.fit(groups)wheregroupsis a list of per-group observation lists (one list per group).indexed-flat –
each(by="g"):.fit(y, given={"g": labels})whereyis one flat observation array andlabels[i]is observationi’s group. This is the varying-intercepts / 8-schools idiom; groups are taken in sorted order of the unique labels.
- Parameters:
by (str | None)
- Return type:
RandomVariable
- noncentered()[source]
Sample this location-scale prior in non-centered form (offset/multiplier).
For
mu = Normal(loc, scale)with a randomscale(a hierarchical prior), the centered parameterization couplesmu’s range toscaleand creates Neal’s funnel – a geometry HMC/NUTS samples badly.Normal(loc, scale).noncentered()instead samples a standard normalzand setsmu = loc + scale * z, whose geometry is independent ofscale. Mathematically identical posterior, far better mixing (fewer divergences) when the data are weakly informative. Applies toNormalpriors; a no-op marker on others.- Return type:
RandomVariable
- property scope: str
- exp()[source]
- Return type:
RandomVariable
- log()[source]
- Return type:
RandomVariable
- eq(other)[source]
- ne(other)[source]
- given(constraint)[source]
Condition this RV on a constraint over itself (e.g.
x.given(x > 0)-> truncation). The result samples by rejection and scores with the renormalized density. For relations among several RVs (a < b) useconstrain(...).- Return type:
RandomVariable
- property is_bound: bool
- property has_free: bool
- property columns: list
the variable names, in sample-column order. A vector-valued variable expands to one name per entry (
v[0],v[1], …).- Type:
For a
constrain(...)joint RV
- property dist
The lowered concrete distribution — the full original mixle API (escape hatch).
- property components
Fitted sub-models of a composite (mixture components, HMM state emissions, sequence element) as RandomVariables — query each with the same verbs (
.params,.sample,.log_prob). Raises for non-composite models.
- property params
Fitted parameters in the same parameterization used to construct the model (e.g.
{'mean': 5.0, 'sd': 2.0}for Normal — not the internalsigma2). Falls back to.distfor families without a registered reader.
- property result: PosteriorResult | None
Inference metadata (EM history / MCMC chain) when present; else None.
- log_prob(x)[source]
- log_likelihood(data)[source]
Total log-likelihood of
dataunder the fitted model (sum of log_prob).- Return type:
- aic(data, k=None)[source]
Akaike information criterion (lower is better).
kdefaults to a heuristic parameter count from.params.
- bic(data, k=None)[source]
Bayesian information criterion (lower is better).
- pointwise_log_likelihood(data)[source]
Return the
(n_draws, n_obs)log-likelihood matrix used by WAIC / PSIS-LOO.For a Bayesian fit (
how='mcmc'|'hmc'|'ensemble'|'vi') each row is the log-likelihood of the data under one posterior draw; for a point-estimate fit it is a single row.- Return type:
- waic(data)[source]
Widely Applicable Information Criterion from the posterior (lower
waicis better).Returns
{elpd_waic, p_waic, waic, se, n_draws, pointwise}. Estimates out-of-sample predictive accuracy by integrating over parameter uncertainty – the Bayesian analogue ofaic/bic– and falls back to a point estimate for non-Bayesian fits.- Return type:
- loo(data)[source]
Pareto-Smoothed Importance-Sampling Leave-One-Out cross-validation (lower
loobetter).Returns
{elpd_loo, p_loo, loo, se, khat_max, n_draws, pointwise}.khat_maxabove ~0.7 signals an unreliable estimate (refit with more posterior draws or preferwaic).- Return type:
- summary()[source]
Posterior summary of a Bayesian fit, or the fitted params for a point estimate.
For
how='mcmc'|'hmc'|'ensemble'|'vi'returns a per-parameter dict of{mean, std, q2.5, q97.5}(the 95% credible interval) plus_acceptance_rateand, for multi-chain runs,_rhat/_ess/_n_chains. Formap/emit returns.params.
- mean(samples=20000, seed=0)[source]
Expected value of the random variable (Monte-Carlo; works for any RV — concrete, transformed, convolved, or conditioned). For a joint
constrain(...)RV this is the per-variable mean vector.
- var(samples=20000, seed=0)[source]
Variance of the random variable (Monte-Carlo); per-variable for a joint RV.
- prob(samples=40000, seed=999)[source]
Probability that the relation holds (Monte-Carlo), for a
constrain(...)RV.
- prob_of_event()[source]
P(event) under the base distribution (Monte-Carlo), for a conditioned RV.
- predict(n=1, rng=None)[source]
Posterior-predictive draws. For a Bayesian fit (conjugate/mcmc/hmc) this integrates over parameter uncertainty (draw params from the posterior, then data); for a point fit (EM/MAP) it is the plug-in predictive (sample from the fitted distribution).
- Parameters:
n (int)
- posterior(x)[source]
Posterior over a latent or a parameter.
posterior(data)-> latent-state posterior (the E-step; e.g. mixture responsibilities), routed to the lowered distribution’sseq_posterior.posterior(handle | name | index)-> parameter posterior draws, when this RV was fit withhow='mcmc'(read from.result).
- explain_fit(*, how='auto', constraints=None, potentials=None, **_)[source]
Report which inference route
.fit(how=...)will take, and why – without fitting.Returns
{'route', 'reason', 'caveats'}. This is the teaching surface for mixle’s automatic cross-family inference selection:rv.explain_fit()answers “how will this be fit, and what are the honest limits of that choice?”. The route mirrorsfit()exactly (it shares_resolve_auto()for the flat tree and re-checks the same structural short-circuits).- Return type:
- fit(data, *, how='auto', max_its=100, delta=1e-8, backend='local', num_workers=None, engine=None, precision=None, print_iter=0, missing='error', **kw)[source]
Estimate / infer parameters from
dataand return a bound RV.how:'em'(EM/MLE, default for plainfreemodels),'map'(maximize the joint with priors),'mcmc'(posterior samples over parameters with priors),'auto'picksmapwhen the model has priors elseem. EM threads mixle’s parallel/distributed backends (backend='mp'|'mpi'|'dask').missing:'error'(default) rejects non-finite entries;'marginalize'integrates a missing entry (NaNin the data) out of the likelihood instead of imputing it – each leaf is fit from its present rows only, so you get a well-defined mode/posterior over the present data (no fabricated values). Supported on the EM path (the default forfreemodels, i.e. the posterior mode under flat priors); forhow='map'/'mcmc'with missing data build the model withmixle.stats.marginalized()leaves directly.
- lower(rv, *, target='dist')[source]
The one routing site: symbolic RandomVariable -> existing mixle object.
target='dist'returns a concrete*Distribution(needs nofreeholes);target='estimator'returns a*Estimator. Results are cached per RV (I7).- Parameters:
rv (RandomVariable)
target (str)
- class Guide(**latents)[source]
Bases:
objectA declared mean-field variational approximation: named latents, each an independent q-factor.
Build it with
Guide(name=handle, ...)where eachhandleis the sameRandomVariableobject used in the model (latents are matched by object identity). To pin and validate the variational family, passname=(handle, 'gaussian'|'gamma'|'dirichlet'); otherwise the conjugate factor implied by the latent’s prior is used.- Parameters:
latents (Any)
- class StructuredVIPosterior(gres, guide)[source]
Bases:
objectPosterior from
structured_vi(): per-latent variational factors + the ELBO trace.posterior(name)returns the factor’s hyperparameters (e.g.{'mean','sd'}for a Gaussian,{'alpha','mean'}for a Dirichlet,{'shape','rate','mean'}for a Gamma);mean/samplesgive the posterior mean / exact draws of that latent. Names are the guide’s keys (the latent handle itself is also accepted).- Parameters:
guide (Guide)
- mean(name)[source]
- structured_vi(observations, guide, *, max_its=300, tol=1e-8)[source]
Fit a structured model by mean-field VMP / coordinate-ascent VI under a declared
Guide.- Parameters:
observations – a list of
(model, data)pairs – eachmodelis a PPLRandomVariableobservation factor,dataits observed values. Factors that reuse the same latent handle share that latent (their evidence is combined). A single factor may be passed as(model, data)directly.guide (Guide) – the
Guidenaming the latents to approximate and (optionally) their q-families.tol (float) – CAVI sweep budget and ELBO convergence tolerance.
max_its (int)
tol
- Returns:
A
StructuredVIPosteriorover the guide’s latents (monotone ELBO).- Raises:
ValueError – if a guide latent is not actually an inferred latent of the model, or its declared q-family does not match the model’s conjugate factor (the projection constraint is checked).
- Return type:
StructuredVIPosterior
- admixture(docs, topics, *, alpha=1.0, max_its=100, inner_its=40, tol=1e-5, seed=0)[source]
Fit an admixture (LDA-class) model by mean-field VI built from this surface’s Dirichlet primitives.
docsis a corpus – a list of documents, each a sequence of integer word ids over the vocabulary.topicsare theDirichletRandomVariablehandles you declare as the per-topic variational factors q(beta_k); their prior alpha vectors set the vocabulary size V and the topic-word prior eta.alphais the per-document topic Dirichlet prior. Returns anAdmixturePosterior.This is “LDA via the guide”: LDA = an admixture whose emission is Categorical over words. The same coordinate-ascent (q(theta_d), q(beta_k) Dirichlet + categorical responsibilities q(z)) fits any admixture over a categorical vocabulary – no
LDADistributioninvolved.
- class AdmixturePosterior(lam, gamma, topic_handles, ll_trace)[source]
Bases:
objectPosterior from
admixture()(LDA-class mean-field VI).posterior(topic_handle)returns that topic’s fitted Dirichlet{'alpha','mean'};topics()isE[beta](K x V);doc_topicsis the per-document mixingE[theta_d];log_likelihoodis the fitted-model corpus LL trace.- topics()[source]
- doc_topics(d=None)[source]
- posterior(topic)[source]
- Normal(mean, sd, *, name=None, keys=None)[source]
Normal with mean and standard deviation (lowers to GaussianDistribution(mu, sd**2)).
- Poisson(rate, *, name=None, keys=None)[source]
- Gamma(shape, rate, *, name=None, keys=None)[source]
Gamma with shape and rate (lowers to GammaDistribution(k=shape, theta=1/rate)).
- Exponential(rate, *, name=None, keys=None)[source]
Exponential with rate (mean 1/rate; lowers to ExponentialDistribution(beta=1/rate)).
- Categorical(probs=None, *, logits=None, dim=None, name=None, keys=None)[source]
Categorical from a probability dict {value: p} or a list of probabilities. The probability vector is also an inferable parameter.
Categorical(free)learns the category probabilities by maximum likelihood, discovering the categories (and their count) from the data – nodim=needed; passdim=Kto request the explicit simplex-parameter treatment forhow='mcmc'|'ensemble'|'map'.Categorical(logits=Net(out=K))is neural classification:p(y|x) = softmax(Net(x)), the softmax-link sibling of logistic regression. Fit with the conditional verb.fit(y, given={"x": X}).
- Bernoulli(p, *, name=None, keys=None)[source]
- Geometric(p, *, name=None, keys=None)[source]
- Binomial(n, p, *, name=None, keys=None)[source]
Binomial with n trials and success probability p (n is fixed/known).
- Weibull(shape, scale, *, name=None, keys=None)[source]
Weibull with shape (k) and scale (lambda).
- Laplace(loc, scale, *, name=None, keys=None)[source]
Laplace (double-exponential) with location and scale (b).
- Logistic(loc, scale, *, name=None, keys=None)[source]
Logistic with location and scale.
- Uniform(low, high, *, name=None, keys=None)[source]
Continuous uniform on [low, high].
- Rayleigh(sigma, *, name=None, keys=None)[source]
Rayleigh with scale sigma.
- Pareto(scale, shape, *, name=None, keys=None)[source]
Pareto with minimum value xm (scale) and tail index alpha (shape).
- Beta(a, b, *, name=None, keys=None)[source]
- StudentT(df, loc, scale, *, name=None, keys=None)[source]
Student-t with degrees of freedom, location, scale (heavy-tailed Normal).
- LogNormal(mu, sigma, *, name=None, keys=None)[source]
Log-normal: log(X) ~ Normal(mu, sigma).
- EMG(mu, sigma, rate, *, name=None, keys=None)[source]
Exponentially-modified Gaussian:
X = Normal(mu, sigma) + Exponential(rate)(right-skewed).Lowers to
ExponentiallyModifiedGaussianDistribution(mu, sigma**2, lam=rate);rateis the exponential component’s rate (its mean is1/rate). The MLE is iterative with no closed form, soEMG(free, free, free).fit(data)uses a consistent method-of-moments estimate.
- NegativeBinomial(r, p, *, name=None, keys=None)[source]
Negative binomial with r failures and success probability p.
- HalfNormal(sigma, *, name=None, keys=None)[source]
Half-normal on
[0, inf)with scalesigma– the standard weakly-informative scale prior.
- InverseGamma(alpha, beta, *, name=None, keys=None)[source]
Inverse-gamma(
alpha,beta) – the classic conjugate prior for a variance.
- InverseGaussian(mu, lam, *, name=None, keys=None)[source]
Inverse-Gaussian (Wald) with mean
muand shapelam– a positive, right-skewed law.
- Gumbel(loc, scale, *, name=None, keys=None)[source]
Gumbel (type-I extreme-value) with
locandscale– for maxima / extremes.
- SkewNormal(loc, scale, shape, *, name=None, keys=None)[source]
Skew-normal with
loc,scale, andshape(skewness;shape=0recovers the Normal).
- Skellam(mu1, mu2, *, name=None, keys=None)[source]
Skellam: the difference of two independent
Poisson(mu1)andPoisson(mu2)counts.
- LogSeries(p, *, name=None, keys=None)[source]
Logarithmic (log-series) distribution on
{1, 2, ...}with parameterpin(0, 1).
- VonMises(mu, kappa, *, name=None, keys=None)[source]
Von Mises (circular normal) on the angle
(-pi, pi]with meanmuand concentrationkappa.
- GEV(loc, scale, shape, *, name=None, keys=None)[source]
Generalized extreme value with
loc,scale,shape(the block-maxima limit law).
- Tweedie(mu, phi, *, name=None, keys=None)[source]
Tweedie compound Poisson-Gamma (power
p=1.5) with meanmuand dispersionphi.A positive distribution with an atom at zero – the standard model for non-negative data that is part-zero, part-continuous (insurance claims, rainfall, ecological biomass).
- GeneralizedGaussian(mu, alpha, beta, *, name=None, keys=None)[source]
Generalized Gaussian (exponential power) with
mu, scalealpha, shapebeta.beta=2is the Normal andbeta=1is the Laplace, so it interpolates between light and heavy tails – a flexible symmetric error model.
- GeneralizedPareto(scale, shape, loc=0.0, *, name=None, keys=None)[source]
Generalized Pareto (
scale, tailshape, thresholdloc) – the peaks-over-threshold tail law.
- Nakagami(m, omega, *, name=None, keys=None)[source]
Nakagami-
mdistribution with shapemand spreadomega(signal-fading amplitudes).
- Rician(nu, sigma, *, name=None, keys=None)[source]
Rician (Rice) distribution with non-centrality
nuand scalesigma(signal-plus-noise magnitude).
- Dirichlet(alpha, *, dim=None, name=None, keys=None)[source]
Dirichlet over a simplex; used as a prior on Categorical probabilities (VMP). The concentration
alphais also an inferable parameter.Dirichlet(free)learns the concentration by maximum likelihood, inferring the dimensionKfrom the observed simplex data (nodim=needed); passdim=Kto request the explicit positive-K-vector parameter treatment forhow='mcmc'|'ensemble'|'map'.
- class Conv(field='x', *, channels=(64, 128, 256), out=10)[source]
Bases:
_NeuralPredictorA conv-net predictor over image covariates
(C, H, W).Conv(channels=[64,128,256], out=10)is a VGG-style stack (two 3x3 convs + BatchNorm + max-pool per channel stage), global-pooled into a linear head. Use it exactly likeNet:Categorical(logits=Conv(out=10)).fit(y, given={"x": images}).- Parameters:
field (Any)
channels (Any)
out (int)
- field
- channels
- out
- Embedding
alias of
CategoricalEmbedding
- Mix(components, weights=None, *, name=None)[source]
Finite mixture over component RandomVariables (or concrete distributions).
Mix([Normal(free, free), Normal(free, free)]).fit(data)fits a 2-component Gaussian mixture;.posterior(data)returns the responsibilities.- Parameters:
name (str | None)
- Return type:
RandomVariable
- class Net(field='x', *, hidden=(64,), out=1)[source]
Bases:
_NeuralPredictorAn MLP predictor over vector covariates.
Net(hidden=[256], out=10)is a one-hidden-layer ReLU net.- Parameters:
field (Any)
hidden (Any)
out (int)
- field
- hidden
- out
- class Transformer(field='x', *, out, d_model=128, n_layer=3, n_head=4, embedding=None)[source]
Bases:
_NeuralPredictorA causal decoder-only Transformer predictor over a
(block,)context of token ids.Categorical(logits=Transformer(out=vocab, d_model=256, n_layer=6, n_head=8))is autoregressive next-token predictionp(token | context)– it lowers to the sameSoftmaxNeuralLeafasNet/Conv(cross-entropy = next-token NLL) and fits through the unchangedestimate()loop with.fit(next_tokens, given={"x": context_windows}). The context width is theblockinferred from the data.- field
- out
- d_model
- n_layer
- n_head
- embedding
- Flow(dim, *, hidden=32, layers=4, m_steps=80, lr=5e-3)[source]
An exact
p(x)overR^dimvia a RealNVP coupling flow. Fit with.fit(x).
- MAF(dim, *, hidden=64, blocks=3, m_steps=80, lr=5e-3)[source]
An exact
p(x)overR^dimvia a masked autoregressive flow (richer dependence). Fit with.fit(x).
- VAE(dim, *, latent=2, hidden=32, m_steps=120, lr=5e-3)[source]
A latent-variable
p(x)overR^dimvia a VAE.log_densityis the ELBO (a lower bound); fit.fit(x).
- DiscreteAR(dim, cats, *, hidden=64, m_steps=100, lr=5e-3)[source]
An exact
p(x)over discrete vectorsx in {0..cats-1}^dim(autoregressive). Fit with.fit(x).
- EBM(dim, *, hidden=64, layers=3, noise_ratio=2, m_steps=250, lr=5e-3)[source]
An energy-based
p(x) ∝ exp(-E(x))overR^dim, trained by NCE (approximately normalized). Fit.fit(x).
- MDN(x_dim, y_dim, *, k=5, hidden=32, field='x', m_steps=120, lr=5e-3)[source]
A multimodal, heteroscedastic
p(y | x)via a mixture density network. Fit.fit(y, given={"x": X}).
- CondFlow(x_dim, y_dim, *, hidden=32, layers=4, field='x', m_steps=100, lr=5e-3)[source]
An exact conditional
p(y | x)via a conditional coupling flow (needsy_dim >= 2). Fit with covariates.
- CondDiscreteAR(x_dim, y_dim, cats, *, hidden=64, field='x', m_steps=120, lr=5e-3)[source]
An exact conditional
p(y | x)over discretey(autoregressive, conditioned onx). Fit w/ covariates.
- SemiMix(components, weights=None, *, name=None)[source]
Semi-supervised finite mixture over component RandomVariables (or concrete distributions).
Like
Mix(), but each observation is a(value, prior)pair whereprioris eitherNone(unlabeled) or a sequence of(component_index, probability)pairs giving a partial label. Labeled rows restrict/re-weight the responsibilities to the listed components, so a few labels can anchor the components.SemiMix([Normal(free, free), Normal(free, free)]).fit(data)fits a 2-component Gaussian mixture from a mix of labeled and unlabeled rows.- Parameters:
name (str | None)
- Return type:
RandomVariable
- Seq(element, *, name=None)[source]
IID sequence of
element. Fit on a list of sequences (each a list/array).- Parameters:
name (str | None)
- Return type:
RandomVariable
- Markov(emission, states=None, *, transitions=None, initial=None, name=None)[source]
Hidden Markov model over latent states emitting
emission.Markov(Normal(free, free), states=2).fit(sequences)fits a 2-state Gaussian HMM by EM (emissions k-means++ seeded so states separate);.posterior(sequences)gives state posteriors. For per-state priors pass a list of emissions, one per state:Markov([Normal(m0, 1), Normal(m1, 1)]). The transition matrix and initial distribution are inferable parameters too: passtransitions=free/transitions=Dirichlet(alpha)(each row a simplex) and/orinitial=free/initial=Dirichlet(alpha)and fit withhow='mcmc'|'ensemble'|'map'(typically with an ordered-emission constraint for identifiability).
- LDA(num_topics, vocab_size, *, alpha=1.0, name=None)[source]
Latent Dirichlet allocation. Fit on a list of documents, each a bag of
(word_id, count)pairs over word ids0..vocab_size-1. Topics are recovered as word distributions; alpha (the document-topic Dirichlet) is fixed by default.
- MVN(dim, *, mean=None, cov=None, name=None)[source]
Multivariate Gaussian of dimension
dim(full covariance). Fit on a list of length-dimvectors;MVN(dim).fit(X)recovers mean and covariance by EM.The mean vector and covariance matrix are also inferable parameters: pass
mean=free(adim-vector on the real line) ormean=ordered(increasing entries, for identifiability) and/orcov=free(a full SPD covariance via its Cholesky factor) and fit withhow='mcmc'|'ensemble'|'map'.
- DiagGaussian(dim, *, mean=None, var=None, name=None)[source]
Diagonal-covariance multivariate Gaussian of dimension
dim.DiagGaussian(dim).fit(X)recovers mean and per-axis variance by EM; the mean vector (mean=free/ordered) and diagonal variances (var=free, a positive vector) are also inferable parameters viahow='mcmc'|'ensemble'|'map'.
- LocalLevel(*, name=None)[source]
Local-level state-space model (random walk + noise) for a time series. Fit on a 1-D series; recovers level/observation noise and smoothed states (Kalman/RTS + EM).
- Parameters:
name (str | None)
- Return type:
RandomVariable
- AR1(*, name=None)[source]
AR(1)-plus-noise state-space model; estimates the autoregressive coefficient phi.
- Parameters:
name (str | None)
- Return type:
RandomVariable
- Graph()[source]
A VMP factor graph for arbitrary conjugate-Gaussian DAGs with shared variables. See mixle.ppl.vmp.Graph.
- class Field(name)[source]
Bases:
objectA named covariate (data column) for regression:
a * Field("x") + b.- Parameters:
name (str)
- name
- class Group(name, slopes=())[source]
Bases:
objectA by-group random-effects term for mixed-effects models.
Group("subject")is a random intercept (lme4’s(1|subject));Group("subject", slopes=["x"])adds a correlated random slope onx((1 + x | subject)).- Parameters:
name (str)
- name
- slopes
- compare(models, data, *, by='aic')[source]
Compare fitted models on
data. Returns rows sorted best-first byby(‘aic’ | ‘bic’ | ‘loglik’ | ‘waic’ | ‘loo’).'waic'and'loo'are the Bayesian predictive criteria (integrating over parameter uncertainty via the posterior draws of a Bayesian fit);'aic'/'bic'use the point estimate. Each row also reportselpddifferences from the best model (d_elpd) for waic/loo.- Parameters:
by (str)
- posterior_predictive_check(fitted, data, *, statistics=None, n_rep=1000, seed=0)[source]
Posterior predictive check of a fitted PPL model against
data.Draws
n_repreplicate datasets (each the size ofdata) fromfitted.predict– which integrates over parameter uncertainty for a Bayesian fit (conjugate/mcmc/hmc) and is the plug-in predictive for a point fit (em/map) – evaluates each named statistic on every replicate and on the observed data, and returns the Bayesian p-value per statistic.Returns
{'observed', 'replicated', 'p_value', 'n_rep'}:observed[name]the statistic on the data,replicated[name]its(n_rep,)replicate values,p_value[name] = P(T_rep >= T_obs).
- prior_predictive(model, size, *, n_rep=1000, statistics=None, seed=0)[source]
Prior predictive simulation:
n_repdatasets ofsizedrawn frommodel’s prior.For each replicate it draws every prior parameter (and hyperparameter) and then
sizedata points, so the result reflects what the model believes before seeing data – the check that a prior is neither absurdly tight nor absurdly diffuse. Returns{'replicated': {stat: (n_rep,)}, 'samples': (n_rep, size), 'n_rep'}with the per-replicate statistics and the raw simulated datasets.
- prior_predictive_check(model, data, *, statistics=None, n_rep=1000, seed=0)[source]
Prior predictive check: where the observed statistics sit in the prior predictive distribution.
Like
posterior_predictive_check()but the replicates come from the prior (viaprior_predictive()), so a p-value near 0 or 1 flags a prior that is inconsistent with the data before any fitting – often a sign the prior is mis-scaled.
- fit_censored(model, time, *, event=None, lower=None, upper=None, seed=0)[source]
Fit a distribution’s free parameters to right-censored and/or truncated data by ML.
modelis a flat PPL distribution withfreeparameter slots, e.g.Weibull(free, free)orExponential(free).timeare the (possibly censored) values;eventflags which are observed events vs right-censored (default all observed);lower/uppermark truncation of the sampling window. Maximizescensored_loglik()over the free slots (Nelder-Mead in the unconstrained space, respecting each slot’s positivity/unit support) and returns the fitted model as a boundRandomVariable(with.summary()).
- fit_with_provenance(rv, data, *, seed=None, **fit_kw)[source]
Fit a PPL
RandomVariableondataand return(fitted_rv, header)with full provenance.fit_kwis passed through torv.fit(how=,max_its=,delta=,backend=, …). The header is built from the fitted model’s lowered distribution so it carries schema + final log-likelihood where available;methodrecords the requestedhow. The header is returned regardless; it is also attached asfitted.headerwhen the RandomVariable allows it (RVs with__slots__do not).
- censored_loglik(dist, time, *, event=None, lower=None, upper=None)[source]
Total log-likelihood of right-censored and/or truncated
timeunder a fitteddist.event[i]true (default all true) meanstime[i]is an observed event contributinglog f(time[i]); false means it is right-censored, contributing the log-survivallog(1 - F(time[i])).lower/uppertruncate the support: every point then also subtractslog(F(upper) - F(lower))(useNonefor an open end). Requiresdist.cdf.
- kaplan_meier(time, event=None)[source]
Kaplan-Meier nonparametric survival estimate
S(t)from right-censored data.Returns
{'time', 'survival', 'at_risk', 'events'}over the distinct event times – the standard model-free survival curve to plot against, or compare a fitted parametric model to.
- hdi(samples, prob=0.94)[source]
Highest-density interval: the narrowest interval containing
probof the posterior mass.For a unimodal posterior this is the shortest
(low, high)such thatP(low <= x <= high) = prob; unlike an equal-tailed interval it tracks an asymmetric or bounded posterior correctly.
- posterior_summary(fitted, *, hdi_prob=0.94)[source]
Per-parameter posterior summary table for a fitted PPL model (best after
how='mcmc').Returns
{param_name: {'mean', 'sd', 'hdi_low', 'hdi_high', 'ess', 'r_hat'}}.mean/sdcome from the fit’s own summary; the HDI is computed from the posterior draws (when the fit exposes them);ess(effective sample size) andr_hat(Gelman-Rubin, multi-chain) come from the sampler’s diagnostics when present. A point fit (em/map) yields justmean/sd.
- constrain(*constraints)[source]
A joint random variable formed by conditioning several RVs on a relation among them.
constrain(a < b)is the pair(a, b)restricted toa < b; pass several constraints (or combine with& | ~) for richer regions, e.g.constrain(a < b, b < c)orders three variables. The result samples by joint rejection and answers.sample(n)(an(n, k)array, columns in.columnsorder),.mean()/.var()(per-variable),.prob()(probability the relation holds), and.log_prob(x)(renormalized joint density of the independent variables on the region).- Return type:
RandomVariable
- class Constraint(leaves, pred, desc, residual=None, soft=False)[source]
Bases:
objectA boolean relation over one or more random variables.
Produced by comparisons on RVs —
x > 0(RV vs constant),a < b(RV vs RV), or2 * a - b >= 1(linear/transformed expressions on either side) — and combined with&(and),|(or),~(not). A constraint over a single RV is consumed byrv.given(c)(truncation); a constraint over several RVs is consumed byconstrain(c)(joint conditioning) orfit(..., constraints=c)(feasible region).leavesare the distinct leaf RVs the relation depends on;pred(env)evaluates the relation givenenv, a dict mapping each leaf RV to its value(s).- leaves
- pred
- desc
- residual
- soft
- property rv
The single RV this constraint restricts (back-compat for one-variable events).
- eval(env)[source]
- contains(x)[source]
Evaluate a single-variable constraint directly on that variable’s value(s).
- Event
alias of
Constraint
- eq(lhs, rhs)[source]
Build an equality relation
lhs == rhsover RVs/expressions/constants.==is not overloaded onRandomVariable(RVs are used as dict keys by identity), so build equalities with this function orrv.eq(...). Equalities have measure zero and cannot be honored by rejection, so consume them with the soft-penalty inference path, e.g.model.fit(data, constraints=eq(a + b, 1.0), penalty=100.0).- Return type:
Constraint
- equal(lhs, rhs)
Build an equality relation
lhs == rhsover RVs/expressions/constants.==is not overloaded onRandomVariable(RVs are used as dict keys by identity), so build equalities with this function orrv.eq(...). Equalities have measure zero and cannot be honored by rejection, so consume them with the soft-penalty inference path, e.g.model.fit(data, constraints=eq(a + b, 1.0), penalty=100.0).- Return type:
Constraint
- ne(lhs, rhs)[source]
Build an inequality relation
lhs != rhs(boolean only; no smooth penalty surface).- Return type:
Constraint
- potential(fn, *vars, name=None)[source]
Add a custom log-factor
fn(*values)to a model’s joint log-density.varsare random-variable parameters of the model (named priors, orparam(...)vector/matrix handles) – exactly the references aconstrain()/eq()constraint may use. At each inference evaluation they are resolved to their current values and passed tofnpositionally;fnreturns a scalar log-weight that is added tolog p(data, theta). Use it for anything the distribution slots can’t say directly: a soft coupling between two latents, a bespoke log-prior, a penalty/regularizer:a = Normal(0, 10, name="a"); b = Normal(0, 10, name="b") m = Normal(a, 1.0).fit(data, potentials=potential(lambda av, bv: -0.5 * (av - bv) ** 2, a, b))
Pass one potential or a list via
fit(..., potentials=...). Potentials route inference through the numerical target (howinmap/mcmc/hmc/nuts/ensemble;autopicksmap); like constraints, every referenced variable must be a parameter of the fitted model.- Return type:
_Potential
- increasing(v, *, strict=False)[source]
The entries of a vector RV/expression are non-decreasing (
strict-> strictly increasing).- Parameters:
strict (bool)
- Return type:
Constraint
- decreasing(v, *, strict=False)[source]
The entries of a vector RV/expression are non-increasing (
strict-> strictly decreasing).- Parameters:
strict (bool)
- Return type:
Constraint
- monotone(v)[source]
The entries are monotone — non-decreasing or non-increasing.
- Return type:
Constraint
- convex(v)[source]
The entries are convex: the second difference is non-negative everywhere.
- Return type:
Constraint
- concave(v)[source]
The entries are concave: the second difference is non-positive everywhere.
- Return type:
Constraint
- lipschitz(v, bound)[source]
Bounded first difference:
|v[i+1] - v[i]| <= bound(a discrete smoothness constraint).- Parameters:
bound (float)
- Return type:
Constraint
- ode_residual(v, f, dt=1.0, *, tol=1e-2)[source]
A differential-equation constraint:
v(a function sampled on a uniform grid of spacingdt) satisfiesdv/dt = f(v). The signed residualdiff(v)/dt - f(v[:-1])feeds the soft-penalty inference path —fit(..., constraints=ode_residual(y, f), penalty=w)fits a physics-informed curve. Like an equality it is measure-zero, so consume it withpenalty=rather than by rejection.
- class GaussianField(index, kernel, name='field')[source]
Bases:
objectA latent field: an index grid plus a Gaussian (GP/GMRF) prior over its node values.
- index: ndarray
- kernel: FieldKernel
- name: str = 'field'
- class FieldSystem(fields, coregion=None)[source]
Bases:
objectSeveral named latent fields fit jointly – the spine for coupled multiphysics / multivariate earth-science models (e.g. an ore-grade field constrained by several geophysical surveys, or coupled paleo-environment fields like temperature + salinity + pCO2 read through many proxies).
By default the prior is block-diagonal over the fields (each keeps its own kernel precision) and cross-field dependence is expressed in the proxy likelihoods: a proxy
loglik(field_t, params, torch)receives the fullparamsdict, so it can read any field by name and couple them (a coupling PDE residual, a grade that depends on density + susceptibility, …). Attach a proxy to a particular field withproxy.on('name'); an unattached proxy defaults to the first field.Pass
coregion=B(aK x Kbetween-field covariance for theKfields) for prior-level coregionalization – the intrinsic coregionalization model, joint prior precisionB^-1 (x) Lambda, where the fields share one spatial structureLambda(the first field’s kernel) and are correlated a priori throughB(e.g. temperature and salinity covary before any data). Requires all fields to share one index/dim.Bmust be symmetric positive-definite.- fields: Sequence[GaussianField]
- class FieldKernel[source]
Bases:
objectA Gaussian field prior over an index grid, expressed as a precision matrix.
- covariance(index)[source]
The prior covariance matrix, when available cheaply (a kernel defined by its covariance). Used by the low-rank Gauss-Newton posterior to get field marginals without a dense precision inverse;
None(the default) falls back to the dense path.
- class GreatCircleRBF(lengthscale=1.0, amplitude=1.0, jitter=1e-06, radius=1.0)[source]
Bases:
FieldKernelSquared-exponential GP prior on the sphere for a
(lat, lon)index (degrees).K[i,j] = amplitude^2 exp(-0.5 chord_ij^2 / lengthscale^2)wherechordis the straight-line distance through the R^3 embedding – so the kernel is positive-definite on the sphere at every lengthscale (a geodesic-distance RBF is not). For nearby points the chord matches the great-circle distance, solengthscalereads as a spatial correlation length in the same units asradius(radius=6371.0088-> kilometres on Earth; default unit sphere -> radians of arc).- lengthscale: float = 1.0
- amplitude: float = 1.0
- jitter: float = 1e-06
- radius: float = 1.0
- covariance(index)[source]
The prior covariance matrix, when available cheaply (a kernel defined by its covariance). Used by the low-rank Gauss-Newton posterior to get field marginals without a dense precision inverse;
None(the default) falls back to the dense path.
- class GreatCircleMatern(lengthscale=1.0, amplitude=1.0, nu=1.5, jitter=1e-06, radius=1.0)[source]
Bases:
FieldKernelMatern GP prior on the sphere for a
(lat, lon)index (degrees) – the geostatistics default.A Matern covariance of the R^3 chordal distance (so PD on the sphere at every lengthscale), giving rougher, more realistic spatial fields than the infinitely-smooth RBF.
nuin {0.5, 1.5, 2.5} (0.5 = exponential / Ornstein-Uhlenbeck, 1.5 and 2.5 are the common once/twice-differentiable choices).lengthscaleandradiuscarry the same spatial-units meaning as inGreatCircleRBF.- lengthscale: float = 1.0
- amplitude: float = 1.0
- nu: float = 1.5
- jitter: float = 1e-06
- radius: float = 1.0
- covariance(index)[source]
The prior covariance matrix, when available cheaply (a kernel defined by its covariance). Used by the low-rank Gauss-Newton posterior to get field marginals without a dense precision inverse;
None(the default) falls back to the dense path.
- great_circle_distance(latlon_a, latlon_b=None, *, radius=1.0)[source]
Great-circle (geodesic) distance between
(lat, lon)points in degrees.Returns
radius * thetawherethetais the central angle (radians). Withradius=1the result is the angle itself;radius=6371.0088gives kilometres on Earth.latlon_b=Nonereturns the full pairwise(n, n)matrix forlatlon_a; otherwise the(na, nb)cross matrix (a float when both are single points). Uses the haversine formula for accuracy at small angles.
- class RandomWalk(scale=1.0, order=1, ridge=None)[source]
Bases:
FieldKernelA Gaussian-Markov-random-field smoothness prior via finite differences.
order=1penalizessum (f[i+1]-f[i])^2 / scale^2(a random-walk / integrated-noise prior);order=2penalizes the discrete curvature (an integrated-Wiener / thin-plate prior).ridgeaddsI / ridge^2so the otherwise-improper prior is proper (it anchors the level/trend).- scale: float = 1.0
- order: int = 1
- class RBF(lengthscale=1.0, amplitude=1.0, jitter=1e-06)[source]
Bases:
FieldKernelA squared-exponential (RBF) GP prior:
K[i,j] = amplitude^2 exp(-0.5 (d_ij/lengthscale)^2).The precision is
inv(K + jitter*I).indexmay be 1-D (a grid) or 2-D (coordinates, one row per node) – distances are Euclidean, so this is the spatial-field prior as well.- lengthscale: float = 1.0
- amplitude: float = 1.0
- jitter: float = 1e-06
- covariance(index)[source]
The prior covariance matrix, when available cheaply (a kernel defined by its covariance). Used by the low-rank Gauss-Newton posterior to get field marginals without a dense precision inverse;
None(the default) falls back to the dense path.
- class AnisotropicRBF(ranges=(1.0, 1.0), angle=0.0, amplitude=1.0, jitter=1e-06, metric=None)[source]
Bases:
FieldKernelA geometrically-anisotropic squared-exponential GP prior – correlation that is longer along one direction than another (geological layering / bedding, faulted fabric, flow channels).
The squared distance is the Mahalanobis form
(x-y)^T M (x-y)withMbuilt from per-axis correlationrangesafter rotating the coordinates: in 2-D,angle(radians, counter-clockwise from the x-axis) sets the principal direction andranges=(major, minor)the correlation length along/across it. For >2-D, supplyrangesper axis (axis-aligned) or a fullmetricmatrixMdirectly. Provably positive-definite – it is an ordinary RBF on linearly-transformed coordinates.- Parameters:
- angle: float = 0.0
- amplitude: float = 1.0
- jitter: float = 1e-06
- covariance(index)[source]
The prior covariance matrix, when available cheaply (a kernel defined by its covariance). Used by the low-rank Gauss-Newton posterior to get field marginals without a dense precision inverse;
None(the default) falls back to the dense path.
- class Proxy[source]
Bases:
objectA likelihood hung off the shared field. Subclasses declare params and score the data in torch.
- prefix: str = 'proxy'
- class GaussianProxy(y, index=None, slope=1.0, intercept=0.0, scale=1.0, prefix='gauss')[source]
Bases:
ProxyA linear-Gaussian forward model:
y_j ~ N(intercept + slope * field[index_j], scale).slope,interceptandscaleare each a fixed float or thefreetoken (estimated). With everything fixed this is the exact linear-Gaussian observation that makes the joint posterior exactly Gaussian – the closed-form check on the Laplace covariance.- y: ndarray
- slope: Any = 1.0
- intercept: Any = 0.0
- scale: Any = 1.0
- prefix: str = 'gauss'
- loglik(field_t, params, torch)[source]
- residual(field_t, params, torch)[source]
The standardized Gaussian residual
(y - prediction) / scale(1-D), orNoneif this proxy is not a Gaussian-misfit observation. Used by the Gauss-Newton posterior (how='gauss_newton').
- class LogisticNicheProxy(presence, mu_scale=2.0, prefix='niche')[source]
Bases:
ProxyThermal-niche occupancy:
presence[i,t] ~ Bernoulli(sigmoid(b - 0.5 kappa_i (field[t] - mu_i)^2)).Each row of
presenceis one taxon’s presence/absence across the field’s index bins; the latent niche locationmu_iand precisionkappa_iare co-estimated, andbis a shared baseline. The assemblage acts as a community thermometer – a unimodal response peaked at the niche optimum.- presence: ndarray
- mu_scale: float = 2.0
- prefix: str = 'niche'
- loglik(field_t, params, torch)[source]
- class PoissonProxy(counts, index=None, offset=0.0, prefix='cox')[source]
Bases:
ProxyA log-Gaussian Cox process:
counts[j] ~ Poisson(exp(offset_j + field[index_j])).The field is the latent log-intensity; counts are the point/aggregate observations. This is the canonical Cox-process proxy – the namesake of the foundation.
- counts: ndarray
- offset: Any = 0.0
- prefix: str = 'cox'
- loglik(field_t, params, torch)[source]
- class CustomProxy(loglik_fn, param_specs=(), prefix='custom')[source]
Bases:
ProxyAn arbitrary proxy: supply a torch log-likelihood
loglik_fn(field_t, params, torch)and the parameter specs it reads fromparams(each(name, shape, support, init)).- loglik_fn: Callable
- prefix: str = 'custom'
- loglik(field_t, params, torch)[source]
- fit_field(field, proxies, *, how='laplace', max_iter=500, lr=0.4, init=None, vi_steps=400, vi_lr=0.05, vi_samples=4)[source]
Fit a latent field jointly to a list of proxy likelihoods.
field=Noneruns pure-parameter inference (the proxies carry all the latents, e.g. ODE/PDE coefficients) with no shared field.how='map'returns the joint MAP (no covariance);how='laplace'adds the Gaussian posterior (the inverse-Hessian covariance, exact when every factor is Gaussian; needs a twice-differentiable forward);how='gauss_newton'builds the posterior fromJ^T J + priorwithJthe Jacobian of the standardized residual – first-order only, so it is the posterior for the sparse adjoint solve (wherehow='laplace'cannot run) and is exact for a linear forward;how='vi'fits a mean-field Gaussian variational posterior (reparameterized ADVI on the unconstrained vector), the calibrated approximation for genuinely non-Gaussian posteriors (e.g. with total-variation / Potts priors), and it too is first-order so it works through the sparse solve. Posteriors over any node are read off the returnedFieldPosterior.
- class FieldPosterior(map_values, _cov, _layout, _field_name, _hessian, objective, _field_prior=<factory>, _proxy_info=<factory>, _supports=<factory>, _marg_var=<factory>)[source]
Bases:
objectThe joint posterior.
posterior(node)returns(mean, sd)for the field or any proxy param.The Laplace covariance is the inverse of the joint negative-log-posterior Hessian at the MAP – the prior precision plus every proxy’s Fisher information.
posterior(field, coupling=False)instead inverts only the field’s own Hessian block (the posterior conditional on the other nodes at their MAP), which is the per-proxy additive-information picture.- Parameters:
- map_values: dict
- objective: float
- cov(node)[source]
Posterior covariance of
nodein its natural space (delta method applied for positive nodes).
- posterior(node, *, coupling=True)[source]
(mean, sd)fornodein its natural space.coupling=True(default) marginalizes the other nodes (the honest marginal);coupling=Falsefixes them at the MAP (additive information).
- field_posterior(include=None)[source]
The field posterior
(mean, sd)under a subset of proxies, evaluated at the one joint MAP.Because information is additive, the field posterior precision under any subset of proxies is the prior precision plus those proxies’ Fisher-information blocks.
include=Noneuses every proxy (the joint posterior);include=["gauss"]uses only that proxy – so you can read how much each proxy sharpens the shared field without re-fitting (which would be ill-posed for a single proxy with a free forward-model gain). The mean is the joint MAP for every subset.
- sample(size=1, rng=None, *, nodes=None, given=None)[source]
Draw joint samples from the Gaussian posterior, returned in each node’s natural space.
The Laplace / Gauss-Newton posterior is the Gaussian
N(map, _cov)in the unconstrained parameter space; this draws via a Cholesky factor of that joint covariance (so cross-node and within-field correlations are preserved) and maps each draw back through the node’s support transform (expfor positive nodes). That back-transform is exact – unlikecov(), which linearizes it with the delta method – so a positive node’s draws are properly lognormal. A mean-fieldhow='vi'(or low-rank Woodbury) fit exposes only per-node marginal variances, so there the draws are independent across nodes (which is exactly the mean-field assumption).given(a{node: value}dict) conditions the draw on fixed node values – the closed-form Gaussian conditional of the remaining coordinates given the observed ones (e.g. draw the field consistent with a pinned measurement or a fixed proxy parameter). Conditioning couples nodes through the joint covariance, so it requires the full-covariance fit (how='laplace'/'gauss_newton'); the fixed nodes come back at their given values.- Parameters:
size (int) – number of joint draws.
rng – a
numpy.random.RandomState, an integer seed, orNone.nodes (Sequence[str] | None) – which nodes to return (default: all). The draw is always joint over the full vector.
given (dict | None) – optional
{node: value}to condition on (values in each node’s natural space).
- Returns:
{node: ndarray}with shape(size,)for scalar nodes and(size, dim)otherwise.- Return type:
- class GP(name, index, kernel)[source]
Bases:
objectA latent field node for the equation-style surface:
T = GP("T", index=grid, kernel=...).Supports affine algebra (
c0 - c1*T,T + b) so a linear forward model reads as math; the result carries the field, the gain and the offset tojoint().- Parameters:
name (str)
index (np.ndarray)
kernel (FieldKernel)
- Gaussian(y, *, mean, sd)[source]
A linear-Gaussian observation
y ~ N(gain*field + offset, sd);meanis an affine in a GP.- Return type:
- Niche(presence, *, over, mu_scale=2.0)[source]
Logistic thermal-niche occupancy of
presenceover the fieldover(a community thermometer).
- Cox(counts, *, log_intensity, offset=0.0)[source]
A log-Gaussian Cox process
counts ~ Poisson(exp(offset + field));log_intensityis a GP.- Return type:
- joint(observations)[source]
Assemble a latent-field model from equation-style observations; call
.fit(how=...)to fit.Each item is the
(field, proxy)pair returned byGaussian(),Niche(),Cox()ormixle.ppl.Differential(). Observations sharing a field must name the same one (this surface targets one shared field); field-free observations (a pure-parameter ODE inverse problem) are allowed.
- class FieldModel(field, proxies)[source]
Bases:
objectA latent-field model built from equation-style observations; fit with
.fit(how=...).The one fit verb, matching the rest of
mixle.ppl:joint([...]).fit(how='map'|'laplace')returns aFieldPosteriorwith a posterior over any node. Delegates tofit_field().- Parameters:
field (GaussianField | None)
proxies (list)
- field: GaussianField | None
- proxies: list
- TotalVariation(over, shape, *, weight=1.0, eps=1e-3)[source]
A smoothed total-variation prior on the field over a structured
shapegrid:weight * sum over neighbour pairs sqrt((f_a - f_b)^2 + eps^2). Edge-preserving (it does not penalize a jump as harshly as the squared GMRF prior). Returns the(field, proxy)pair forjoint().
- Potts(over, levels, *, weight=1.0)[source]
A discrete-composition prior:
weight * sum_i prod_k (f_i - level_k)^2– a multi-well potential whose minima are the givenlevels, pulling the field toward a few discrete material values (a smooth relaxation of the Potts model). Combine withTotalVariation()for piecewise-constant regions. Returns the(field, proxy)pair forjoint().
- multistart(model, inits, *, how='map', **kw)[source]
Fit
modelfrom several initializations and keep the best (lowest-objective) fit.For the multimodal posteriors of nonlinear inverse problems (e.g. scattering / FWI cycle-skipping), a single optimization can land in a poor local mode;
initsis a list of{node: value}dicts and the fit with the smallestobjectiveis returned. (Frequency continuation – fit a coarse/low- frequency model, then seed a finer one viafit(init=...)– is the complementary strategy.)
- conformal(result, y_cal, *, given, alpha=0.1)[source]
Split-conformal calibration of a fitted regression
resultinto prediction intervals.Mirrors
fit’s convention (labels positional,given=keyword), a one-liner overConformalRegressor:m = Normal(free * Field("x") + free, free).fit(y_tr, given={"x": x_tr}) cp = conformal(m.result, y_cal, given={"x": x_cal}, alpha=0.1) lo, hi = cp.interval({"x": x_te}) cp.covers(y_te, given={"x": x_te}).mean() # ~ 0.9
- loo_stack(logliks)[source]
Stack K candidate models by LOO predictive performance.
logliksis a sequence of(n_draws_k, n_obs)pointwise log-likelihood matrices over the same, aligned observations. Returns the stackingweights, the(n_obs, K)per-model pointwise LOO densities, each model’selpd_loo, and thestacked_elpd_looof the weighted predictive (which is >= the best single-model elpd_loo, since a one-hot weight is feasible).
- loo_stacking_weights(pointwise_lpd, iters=2000, tol=1.0e-10)[source]
Return LOO stacking weights (Yao, Vehtari, Simpson & Gelman, 2018).
pointwise_lpdis an(n_obs, K)matrix of per-model pointwise LOO log-predictive densities (each column ispsis_loo(model_k)["pointwise"]). The returned simplex weightswmaximize the LOO log-score of the weighted predictive distribution,sum_i log(sum_k w_k * exp(lpd_ik)). This is concave inwand solved here by the standard mixture-weight EM update (no external optimizer), which respects the simplex by construction.
- class ConformalRegressor(result, y_cal, *, given, alpha=0.1)[source]
Bases:
objectSplit-conformal prediction intervals around a fitted regression
result.Calibrates the absolute-residual nonconformity score on held-out
(given, y_cal)and produces symmetric intervalspredict(x) +/- qhatwith marginal coverage at least1 - alpha.resultis any object with apredict(given)method returning the fitted mean (aRegressionResult, a location-scale result, or a GP regressor).- interval(given)[source]
Return
(lower, upper)arrays of the conformal interval at covariatesgiven.
- class ConformalClassifier(proba_cal, y_cal, *, alpha=0.1)[source]
Bases:
objectSplit-conformal label sets from per-class probabilities.
proba_calis an(n, K)matrix of calibration probabilitiesp(y | x)(any proper classifier — a mixle generative classifier’s class posterior, a softmax, …) andy_calthe integer labels. The nonconformity score is1 - p(true)and the calibrated set keeps every label whose score is within the conformal quantile, so it covers the true label with probability at least1 - alphaand grows from one label (confident) to several (hedging) as the model is unsure.- Parameters:
proba_cal (Any)
y_cal (Any)
alpha (float)
- predict_set(proba)[source]
Boolean
(n, K)label-inclusion matrix at probabilitiesproba.
- covers(proba, y)[source]
Boolean array: is each true label
yin the predicted set.
- class ConformalQuantileRegressor(lo, hi, y_cal, *, given, alpha=0.1)[source]
Bases:
objectConformalized quantile regression (Romano, Patterson, Candes 2019).
Combines two fitted quantile regressions (a lower and an upper conditional quantile) with a split-conformal calibration so the band has exact marginal coverage and the adaptive, heteroscedastic width of quantile regression — wide where the data is noisy, narrow where it is tight, unlike the constant-width absolute-residual band of
ConformalRegressor.The nonconformity score is the signed distance outside the predicted band,
E_i = max(qlo(x_i) - y_i, y_i - qhi(x_i))(negative wheny_iis comfortably inside), and the calibrated band is[qlo(x) - qhat, qhi(x) + qhat]withqhatthe conformal quantile of the calibration scores.loandhiare fitted quantile-regression results (from...fit(..., quantile=tau)), typically attau = alpha/2and1 - alpha/2.- interval(given)[source]
Return
(lower, upper)arrays of the calibrated adaptive band at covariatesgiven.
- class ConformalStructure(dist, calibration, *, alpha=0.1)[source]
Bases:
objectSplit-conformal credible sets over combinatorial structures (rankings, matchings, spanning trees, permutations, …) from a fitted mixle distribution’s exact log-density.
The nonconformity of a structure
sis-log p(s): the lower its model probability, the more surprising it is. Calibrating on held-out true structures yields a log-probability threshold, and the conformal set is{s : log p(s) >= threshold}— it contains the true structure with probability at least1 - alphawhenever the calibration and test structures are exchangeable (for example iid draws), with no assumption on the model being correct.distis any structure distribution exposinglog_density(PlackettLuceDistribution,MallowsDistribution,MatchingDistribution,SpanningTreeDistribution, …);calibrationis a sequence of observed structures. Membership is always available; listing or counting the set additionally needs the distribution’s exactenumerator().- Parameters:
dist (Any)
calibration (Any)
alpha (float)
- property log_prob_threshold: float
Structures with
log p(s)at or above this value are in the conformal set.
- contains(structure)[source]
Is
structurein the conformal set (its log-probability above the threshold).
- covers(structures)[source]
Boolean array: membership of each structure (use on held-out truths to check coverage).
- members()[source]
List the structures in the conformal set, highest-probability first.
Requires the distribution’s exact
enumerator()(raisesEnumerationErrorotherwise). The enumerator yields structures in descending log-probability, so the scan stops at the threshold.- Return type:
- class ConformalLinkPredictor(edge_prob, cal_edges, *, alpha=0.1)[source]
Bases:
objectSplit-conformal candidate-neighbor sets for a random-graph model from its edge-probability matrix
P(P[i, j] = p(edge i--j), e.g.X @ X.Tfrom a fitted RDPG, or an Erdos-Renyi / stochastic-block-model edge probability).The nonconformity of a present edge
(i, j)is1 - P[i, j]. Calibrating on held-out true edges gives a threshold; the predicted neighbor set of a node keeps every candidatejwith1 - P[i, j] <= tau, so it contains a true neighbor with probability at least1 - alphaover exchangeable held-out edges (a random split of the observed edges).- Parameters:
edge_prob (Any)
cal_edges (Any)
alpha (float)
- neighbor_set(i, candidates=None)[source]
Candidate nodes
jin nodei’s conformal neighbor set.
- covers(edges)[source]
Boolean array: is each held-out true edge’s endpoint in the predicted neighbor set.
- class ConformalKnowledgeGraph(kg, calibration, *, slot='tail', alpha=0.1)[source]
Bases:
objectSplit-conformal completion sets for a knowledge-graph model (any-slot UQ).
Calibrating on held-out true triples turns the model’s completion posterior into a set of candidate fillers that contains the true one with probability at least
1 - alphaover exchangeable held-out triples.slotselects which slot is predicted –'tail'for(h, r, ?),'head'for(?, r, t),'relation'for(h, ?, t)– using the model’stail_log_posterior/head_log_posterior/relation_log_posterior. The nonconformity of a triple is1 - p(true filler), so a confident model gives small completion sets and a recommended completion carries a coverage guarantee.- completion_set(h=None, r=None, t=None)[source]
Candidate fillers in the conformal set for the missing slot of a query.
- covers(triples)[source]
Boolean array: is each held-out true triple’s filler in the completion set.
Submodules¶
- mixle.ppl.autograd module
- mixle.ppl.conformal module
- mixle.ppl.core module
- mixle.ppl.density module
- mixle.ppl.diagnostics module
- mixle.ppl.distributions module
- mixle.ppl.field module
- mixle.ppl.guide module
- mixle.ppl.inference module
- mixle.ppl.neural module
- mixle.ppl.predictive module
- mixle.ppl.priors module
- mixle.ppl.provenance module
- mixle.ppl.regression module
- mixle.ppl.rough_paths module
- mixle.ppl.statespace module
- mixle.ppl.summarize module
- mixle.ppl.survival module
- mixle.ppl.vmp module