mixle.lifecycle module¶
mixle.Model – the model lifecycle as one object with consistent verbs.
Everything here exists elsewhere in the library; this facade makes the lifecycle discoverable without knowing which subpackage owns which verb:
m = mixle.propose(data) # a model shape recommended from the data (with confidence + caveats)
m.fit(data) # inference chosen from the structure (EM / MLE / closed form)
m.evaluate(holdout) # held-out scores
m.sample(5) # draw new records
m.enumerate().top_k(3) # most-probable support (discrete/structured families)
m.posterior(x) # latent posteriors (mixtures, HMMs, ...)
m.distill(teacher, inputs) # tiny deployable student in front of the teacher (task spine)
m.deploy("artifacts/m") # durable artifact directory; Model.load() restores it
m.explain() # what it is, what it supports, and how it was proposed
m.explain_prediction(x) # exact per-part attribution of one score
m.forecast(history, h) # horizon predictions with honest intervals (HMMs)
m.do({field: value}) # graph-surgery intervention (learned Bayesian networks)
m(x) # use it: log-density of an observation
Model wraps a prototype distribution, an estimator, or nothing (the estimator is inferred from the
data); verbs delegate to mixle.inference.optimize(), dist.enumerator(), mixle.task.solve,
and mixle.describe(). It adds no new inference – only one place to stand.
- saddle_suspect(fitted, data, *, sample=200, tol=0.02)[source]
Family-agnostic symmetric-saddle check for latent-variable fits.
At the symmetric saddle every component is identical, so every observation’s component posterior is (numerically) uniform. Suspect when, over a data sample, NO observation’s posterior deviates from uniform by more than
tol. Non-latent models (noposterior/components) return False.
- class Model(spec=None, *, notes=None)[source]
Bases:
objectOne object over the model lifecycle: build / fit / evaluate / enumerate / distill / deploy / use.
- fit(data, *, restarts='auto', calibrate=False, **optimize_kw)[source]
Fit via
mixle.inference.optimize(); the algorithm follows from the model’s structure.restarts="auto"(default) makes latent-variable fitting genuinely automatic: after the plain fit, a family-agnostic saddle check runs (a mixture stuck at the symmetric saddle gives every observation a ~uniform component posterior), and on suspicion the fit silently reruns as multi-restart EM (mixle.inference.best_of()), keeping the better log-likelihood and recording what happened innotes. Pass an int to force that many restarts up front, orrestarts=Nonefor the raw single fit.calibrate(opt-in, default off): reserve a holdout slice (a fraction, orTruefor 25%), fit on the rest, and attach aCalibrationReportonself.calibrationmeasuring whether the model’s uncertainty is honest on the held-out data (PIT test + held-out log-density). Off by default because it costs training data.
- evaluate(data)[source]
Held-out fit quality: total and mean log-density over
data.
- sample(size=None, *, seed=None)[source]
- enumerate()[source]
The fitted distribution’s enumerator (top-k / top-p / rank / seek), where supported.
- Return type:
- posterior(x)[source]
Latent posterior for one observation (mixtures, HMMs, …), where supported.
- distill(teacher=None, inputs=None, **solve_kw)[source]
Distill a tiny deployable student via
mixle.task.solve().With
teacher=Nonethe fitted model itself teaches: inputs are labeled by their most-probable latent component (posteriorargmax), so a fitted mixture becomes a fast, calibrated classifier of its own clusters. Returns amixle.task.Solution(call it,report(),improve()).
- deploy(path)[source]
Persist a durable artifact directory (model + manifest);
Model.load()restores it.
- explain_prediction(x)[source]
Exact per-part attribution of
log p(x)—mixle.inference.explain().- Parameters:
x (Any)
- forecast(history, horizon, **kw)[source]
Horizon predictions with honest intervals —
mixle.inference.forecast()(HMMs).
- do(interventions, **kw)[source]
Graph-surgery intervention —
mixle.inference.do()(learned Bayesian networks).
- propose(data, *, fit=False, llm=None, holdout=0.25, seed=0, max_its=25, **recommend_kw)[source]
Propose a model for
datafrom a verified frontier of candidates and return the winner.Candidates come from every proposer the library has — the heuristic recommendation (
mixle.task.recommend.recommend_model(), dependency-aware), the plain independence baseline (mixle.utils.automatic.get_estimator()), and, when anllmhandle is given, an LLM-designed structure (mixle.task.design.design_model(), allowlisted-spec, fit-validated). Each candidate is fitted on a train split and scored on held-out data, so the ranking is out-of-sample, not a guess. The winner becomes the returnedModel; the full ranking lands inModel.frontierand the per-field confidence / dependency / candidate notes inModel.notes(shown byexplain()). Passfit=Trueto also fit the winner to all ofdatabefore returning.