Inference

mixle.inference is the concern for turning data and a model specification into a fitted or posterior-bearing model. The core entry points share one encoder/estimator loop and differ mainly in how much control you want over initialization, objectives, streaming, restarts, and diagnostics.

Entry Points

Function

Use when

optimize(data, estimator)

you want the standard fit route for an estimator, prototype, or inferred model

fit(data, estimator)

you want the posterior-oriented wrapper with Bayesian defaults

initialize(data, estimator)

you want the initial model before iteration

estimate(data, estimator, prev_estimate=model)

you want one explicit estimate pass

best_of(...)

you want repeated random starts for a latent model

StreamingEstimator / BayesianStreamingEstimator / IncrementalEstimator

data arrive in batches or posterior state should carry forward

create(data, ...)

you want a certified fitted artifact with optional calibration and UQ post-conditions

simulate(model)

you want to turn a fitted generative model into a reusable simulator

synthesize(source, label=..., verify=...)

you want a verified synthetic or teacher-labeled dataset

certify(model) / plan_placement(certificate)

you want an auditable estimate of how each block was solved and where it should run

record_fit / verify_reproducible

you want to replay a fit and check that the same parameters are recoverable

uq(thing, data)

you want method-selected uncertainty over a fitted model, point predictor, ensemble, or LLM-style callable

Estimator, Prototype, or Inferred Model

optimize accepts three model specifications:

from mixle.inference import optimize
from mixle.stats import GaussianDistribution, GaussianEstimator, MixtureDistribution

# explicit estimator
m1 = optimize(data, GaussianEstimator(), out=None)

# prototype distribution: derive the estimator shape from the model object
proto = MixtureDistribution(
    [GaussianDistribution(-1.0, 1.0), GaussianDistribution(1.0, 1.0)],
    [0.5, 0.5],
)
m2 = optimize(values, proto, prev_estimate=proto, out=None)

# inferred estimator from raw data
m3 = optimize(data, out=None)

Use explicit estimators for production or publication-quality workflows. Use prototype or inferred estimators for exploration. Passing a prototype as the second argument tells optimize which estimator tree to build. Passing the same object as prev_estimate also uses its parameter values as the starting estimate, which is important for latent models such as mixtures and HMMs.

What optimize Does

At a high level, optimize:

  1. resolves the estimator;

  2. chooses or reuses an encoder;

  3. encodes raw records into chunks;

  4. initializes a model;

  5. repeats an E/M-style update loop;

  6. scores convergence on the selected objective;

  7. returns the best model under the training or validation objective.

The same outer loop supports closed-form leaves, mixtures, HMMs, variational families, MAP objectives, neural leaves, and distributed encoded data.

Certified Creation

create is the higher-level creation verb. It infers and fits a model, attaches an estimation certificate, and can reserve held-out data for a calibration report or attach a UQ handle.

from mixle.inference import create

artifact = create(rows, calibrate=0.2, quantify_uq=True, seed=0)

print(artifact.guarantee)
print(artifact.why())
print(artifact.is_calibrated())

The returned CreatedModel is deliberately not just the fitted distribution. It carries:

  • model: the fitted model;

  • certificate: how each estimation block was solved;

  • calibration: optional held-out PIT/log-density report;

  • uq: optional uncertainty object;

  • provenance: record counts, seed, budget/device constraints, and the exchangeability check when applicable.

Use optimize when you need direct control over the estimator route. Use create when the artifact boundary and post-conditions matter.

Common Fit Knobs

max_its

Maximum number of iterations.

delta

Convergence tolerance. Use None when you want exactly max_its iterations.

rng

Random state for initialization and stochastic routes.

out

Progress output stream. Pass out=None for quiet code.

vdata

Validation data for selecting the best model.

prev_estimate

Resume or continue from an existing fitted model. When fitting from a prototype distribution, pass prev_estimate=proto if the prototype’s parameter values should seed the fit.

backend

Encoded-data backend, such as local, mp, spark, dask, or mpi.

engine

Compute engine, such as TorchEngine(device="cuda").

precision

Explicit precision, "auto", or "minimal".

strategy

EM strategy object or callable for specialized update loops.

on_step

Callback receiving per-iteration EMStep records, useful for checkpointing.

Objectives

objective= controls the convergence and selection objective.

Objective

Meaning

"auto"

choose MLE, MAP, or variational objective from model capabilities and priors

"mle"

observed-data likelihood

"map"

penalized likelihood with parameter priors

"vb"

variational evidence lower bound

The default "auto" is usually correct. Force an objective when comparing routes or debugging prior behavior.

Latent Models and Restarts

Mixtures and HMMs can have local optima. Use best_of with a validation set when random initialization matters.

import numpy as np
from mixle.inference import best_of
from mixle.stats import GaussianEstimator, MixtureEstimator

est = MixtureEstimator([GaussianEstimator(), GaussianEstimator()])

score, model = best_of(
    train,
    valid,
    est,
    trials=8,
    max_its=100,
    init_p=0.1,
    delta=1e-8,
    rng=np.random.RandomState(0),
    out=None,
)

EM Strategies

mixle.inference.em contains strategy objects for variants of the EM loop: hard EM, annealed EM, generalized EM, monotonic EM, ECM, Monte-Carlo EM, variational EM, online EM, accelerated EM, and restart EM.

Use strategies when the default exact E/M update is not the right numerical or statistical route for the model.

Bayesian and Gradient Routes

Conjugate families use closed-form posterior updates through priors and conjugate_posterior helpers. Non-conjugate differentiable targets can use MAP, Laplace, variational, HMC, or NUTS-oriented routes. is_conjugate_family is the guard used by the higher-level inference path to decide whether a fitted estimator/prior pair can take the analytic posterior route or should fall back to a numerical approximation.

from mixle.inference.priors import NormalGammaPrior
from mixle.stats import GaussianEstimator

est = GaussianEstimator(prior=NormalGammaPrior())
posterior_model = optimize(data, est, objective="auto", out=None)

For gradient objectives, see mixle.inference.gradient_fit and mixle.inference.target.

Certificates And Placement

certify classifies the fitted model’s estimation blocks along an ordered guarantee ladder:

HEURISTIC

Gradient descent or another heuristic local route.

STATIONARY

EM or coordinate ascent fixed point.

STATIONARY_ESCAPE_TESTED

EM with explicit restart or saddle-escape testing.

GLOBAL

Convex objective such as least squares or IRLS.

GLOBAL_UNIQUE

Closed-form unique optimum, such as many exponential-family and count-rate MLEs.

from mixle.inference import PoolSpec, certify, plan_placement

certificate = certify(model)
placement = plan_placement(certificate, PoolSpec(available=False))

print(certificate.table())
print(placement.report())

Placement is advisory: closed-form, convex, and EM blocks stay local; gradient blocks can become pool-eligible when a pool is configured and the estimated work clears the threshold.

Streaming

Streaming estimators update across batches. Bayesian streaming can carry a posterior forward as the next batch’s prior.

from mixle.inference import BayesianStreamingEstimator

stream = BayesianStreamingEstimator(estimator)
for batch in batches:
    model = stream.update(batch)

Use streaming when the dataset is naturally batched, too large for one pass, or needs recursive updating.

Simulation And Verified Synthesis

simulate packages a fitted generative model as a data generator. For Bayesian-network-like models, named scenarios can apply interventions.

from mixle.inference import simulate

sim = simulate(model)
baseline_rows = sim.run(100, seed=0)

For learned Bayesian networks, sim.scenario(name, interventions) registers a named do-operator scenario and compare estimates scenario effects.

synthesize builds a dataset by drawing inputs, optionally labeling them with a teacher, and keeping only rows that pass a verifier:

from mixle.inference import synthesize

def draw(rng):
    return float(rng.normal())

dataset = synthesize(
    draw,
    label=lambda x: "positive" if x > 0 else "negative",
    verify=lambda x, y: y in {"positive", "negative"},
    n=50,
    seed=0,
)

print(dataset.acceptance_rate)
print(dataset.recheck())

When the source is a list of real rows, synthesize records an exchangeability check in the dataset provenance because sampling “more rows like these” assumes the source rows can be pooled.

Reproducibility Receipts

record_fit captures the data fingerprint, seed, estimator type, and fitted parameter fingerprint. verify_reproducible refits and checks whether the same parameters are recovered.

from mixle.inference import record_fit, verify_reproducible

receipt = record_fit(model, rows, seed=0, estimator=estimator)
check = verify_reproducible(estimator, rows, receipt, seed=0)

print(check["reproducible"])

Fingerprints round floating-point values to a fixed precision before hashing, so last-bit platform noise does not invalidate an otherwise equivalent fit.

Uncertainty Dispatch

uq chooses an uncertainty route from the object it receives:

  • fitted Mixle model plus fitting data: Laplace parameter posterior;

  • point predictor or Torch module plus (X_cal, y_cal): split-conformal prediction intervals;

  • list of predictors: ensemble disagreement plus conformal intervals;

  • LLM-like callable: semantic entropy over sampled generations.

from mixle.inference import uq

uncertainty = uq(model, rows)
lo, hi = uncertainty.credible_interval(lambda m: float(m.log_density(rows[0])))

Use specialized UQ functions when you already know the route. Use uq when the caller owns a heterogeneous object and wants a single front door.

Backends and Engines

The same model can be fitted locally, on a device engine, or on a distributed encoded-data backend.

from mixle.engines import TorchEngine
from mixle.inference import optimize

local = optimize(data, est, out=None)
gpu = optimize(data, est, engine=TorchEngine(device="cuda"), out=None)
mp = optimize(data, est, backend="mp", num_workers=4, out=None)

Use Compute Engines for engine details and Data Layer for sources and encoded payloads.

Learned Orchestration

mixle.inference.orchestration learns from telemetry rows produced by the runtime layer. The initial policies defer to static rules when the feature region is thin, and use historical outcomes only where nearby examples support the learned decision.

from mixle.inference import learn_action_policy
from mixle.telemetry import Telemetry

telemetry = Telemetry()
rows = telemetry.training_rows("route")
# policy = learn_action_policy(rows)

Use these helpers with Local Reasoning Ecosystem. They are for application routing, placement, and scheduling decisions, not for replacing the statistical fit route itself.

Event Studies

hierarchical_event_study estimates confirmed-exposure influence from per-subject pre/post effects and optional exposed-non-actor controls. Helpers compute Gaussian mean shifts and Poisson log-rate shifts, then pool them with a random-effects meta-analysis and report a difference-in-differences contrast when controls are present.

Use this for timestamped interventions with a defensible exposure time. The result includes a sensitivity bound via tipping_drift; it does not remove the need for study-design assumptions.

Diagnostics and Comparison

The inference namespace also includes:

  • calibration diagnostics and conformal prediction;

  • cross-validation splitters;

  • model comparison tests and ELPD comparison;

  • MCMC diagnostics such as R-hat, ESS, Geweke, and MCSE;

  • bootstrap and permutation inference;

  • robust and sandwich covariance estimators;

  • proper scoring rules.

See Inference Toolkit for the detailed map of scoring rules, calibration, conformal prediction, cross-validation, model comparison, multiple testing, regression, nonparametric tests, survival models, posterior helpers, MCMC diagnostics, resampling, and decision utilities.

Production

mixle.inference.production adds provenance headers, registries, scoring services, drift detection, monitors, and checkpointing. See Production Workflows.

API Map

Area

Imports

fitting

optimize, fit, initialize, estimate, best_of

EM

EMStrategy, run_em and strategy classes in mixle.inference.em

streaming

StreamingEstimator, BayesianStreamingEstimator

priors and Bayes

mixle.inference.priors, conjugate_posterior

diagnostics

Inference Toolkit, mixle.inference.diagnostics, scoring, calibration, model comparison

production

mixle.inference.production

creation and certificates

create, CreatedModel, certify, plan_estimation, schedule, plan_placement

simulation and synthesis

simulate, Simulator, synthesize, Dataset

reproducibility

record_fit, verify_reproducible, ReproReceipt

UQ dispatch

uq, UQResult

learned orchestration

learn_action_policy, learn_placement_policy, learn_schedule_policy, meta_improve

reusable capabilities

skill, Skill, SkillRegistry

event studies

gaussian_effect, poisson_lograte_effect, hierarchical_event_study, tipping_drift