Evolution and Analysis¶
This tutorial connects analysis diagnostics to an auditable improvement loop. It is for cases where you already have a working model and want controlled change, not blind hyperparameter search.
Start With a Champion¶
Assume a champion model already exists. The improvement loop needs data, an objective, and a verification standard.
from mixle.evolve import EvolutionLedger, improve, nll_objective
ledger = EvolutionLedger()
result = improve(
champion,
data,
objective=nll_objective(),
holdout=0.25,
alpha=0.05,
min_effect=0.01,
ledger=ledger,
)
champion = result.model
The returned model is only a verified challenger if result.verified is
true. Otherwise the original champion remains in place.
Record both outcomes. A rejected challenger is useful evidence: it tells future searches which direction did not clear the gate.
Keep the champion fixed while a challenger is evaluated. Search state, diagnostics, and validation results should be attached to the challenger record instead of mutating the deployed model in place. That distinction is what makes the ledger useful after the run is over.
Add a Tail Diagnostic¶
Likelihood can improve while tail behavior gets worse. Use analysis utilities to inspect the residuals or losses that matter operationally.
import numpy as np
from mixle.analysis import peaks_over_threshold, return_level
residuals = np.asarray([abs(y - champion.predict(x)) for x, y in validation])
tail = peaks_over_threshold(residuals, threshold=np.quantile(residuals, 0.95))
level = return_level(tail, period=100)
You can track this diagnostic in the ledger metadata or use it to define a custom objective.
The reason to keep this separate from the primary likelihood objective is governance. A model can improve average log score while becoming worse exactly where the application is most sensitive.
Use the same validation slice for the tail diagnostic that you use for the promotion decision, or record why a different slice is appropriate. Tail estimates can be noisy; for high-impact applications, report uncertainty or repeat the diagnostic across time windows before treating it as a hard gate.
Define a Promotion Gate¶
A promotion decision should combine the objective result and the diagnostics that matter for the application.
passed = (
result.verified
and level < champion_tail_limit
and result.delta >= 0.01
)
if passed:
champion = result.model
ledger.record(
operator="promotion_gate",
delta=result.delta,
verdict={"promote": True},
cost=0.0,
parent_hash=result.parent_hash,
meta={"tail_level": level},
)
else:
ledger.record(
operator="promotion_gate",
delta=result.delta,
verdict={"promote": False},
cost=0.0,
parent_hash=result.parent_hash,
meta={"tail_level": level},
)
The exact fields depend on the ledger object and your application, but the principle is stable: the gate should be explicit enough to audit later.
Promotion gates should be written before reading the final challenger result. Changing the threshold after seeing a favorable run turns verification into retrofitted justification. If a threshold needs to change, record that as a new experiment with its own rationale.
Search a Typed Space¶
For a larger model-design question, define a typed search space and a builder.
from mixle.evolve import Categorical, Integer, Real, Space, search
space = Space({
"components": Integer(1, 5),
"alpha": Real(0.1, 4.0, log=True),
"family": Categorical(["gaussian", "student_t"]),
})
def build_fn(config):
return fit_candidate(data, config)
found = search(
space,
data,
objective=nll_objective(),
build_fn=build_fn,
method="bo",
n_iter=25,
)
challenger = found.best_model
Search proposes candidates. Verification still decides promotion.
Typed spaces are preferable to loose dictionaries because the search algorithm knows which dimensions are categorical, integer, continuous, or log-scaled.
Constrain the search space to values that can be served, monitored, and explained. A candidate that only appears better because it exceeds latency, memory, or operational limits is not a viable challenger.
Promote Deliberately¶
Before replacing a model, ask:
Did the challenger improve the primary objective?
Did it preserve calibration?
Did it avoid worse tail behavior or decision regret?
Is the evaluation split representative of production traffic?
Are the rejected candidates and reasons recorded?
Also check the negative evidence. A professional release note should say which reasonable challengers failed, what gate they failed, and whether the failure was numerical, statistical, operational, or data-related.
That discipline is what makes automatic improvement compatible with professional model governance.
Read Analysis Utilities for diagnostics and Evolution and Search for search spaces, objectives, verification, and ledgers.