mixle.task.regress module¶
solve_regression for calibrated replacement of numeric task functions.
The regression shape of the solve loop. teacher(x) -> float is the scorer/pricer/estimator being
replaced; a small student learns it, and calibration is split conformal for regression: on held-out
CALIBRATION rows the absolute-residual quantile qhat is set so the interval
[yhat - qhat, yhat + qhat] covers the teacher’s answer with probability >= 1 - alpha
(finite-sample, distribution-free, exchangeable inputs). The escalate-or-answer rule is a precision
rule: answer locally only when the interval is tight enough for the caller’s purpose (qhat <= tol);
otherwise run the real code. If the student cannot achieve the required precision, every request
escalates.
What the coverage statement is – and what deployment does to it. The 1 - alpha statement is
marginal over the calibration draw AND the query jointly. Split conformal’s randomness includes the
calibration sample, so conditioning on the deployment decision – the gate event qhat <= tol is a
function of the calibration draw – is selection, and coverage conditional on deploying is NOT
guaranteed to be 1 - alpha. Exact counterexample (external review pass eleven): iid Uniform(0,1)
residuals, n=19, alpha=0.1, tol=0.8 – the gate opens with probability 0.083, and coverage
conditional on opening is 0.751, not 0.90. The effect shrinks as the calibration slice grows and as
tol moves away from qhat’s sampling distribution, but it is not zero and this module does not
certify it. What the deployed artifact carries instead is a MEASUREMENT: report() includes the
empirical coverage of the current interval on the SELECTION rows, a slice the calibration quantile
never touches. Both the guarantee and the measurement assume exchangeability and fail silently under
distribution shift – re-measure on drifted traffic.
Two immutable holdout roles, and fresh calibration after every harvest. The held-out rows are
split, deterministically at solve time, into CALIBRATION rows (they set the initial qhat and are
never read by a promotion decision) and SELECTION rows (they decide every improve() promotion and
produce the reported error/coverage measurements). Without the split, improve() chose the student
with the same rows that then set its interval – expected coverage fell from 0.90 to 0.75 after twenty
candidate selections in the reviewer’s exact construction (STAT-RR11-1). The split alone is NOT enough:
the solve-time calibration rows also decide, through the deployment gate, whether requests are
harvested at all, so the candidate’s training data is a function of that draw and the same rows cannot
certify the candidate they helped construct – reusing them gave exactly 0.8857 coverage against the
claimed 0.90 (STAT-RR12-1). Every promotion therefore recalibrates on FRESH rows that postdate the
harvest (reserved from the harvest itself, or a caller-supplied evidence_inputs batch);
calibration_evidence in report() names the regime that certified the current qhat.
selection_uses counts how many promotion decisions the selection rows have made: after the first,
the selection-side numbers are selection scores, not fresh held-out estimates (the same honesty rule
as classification solve).
def price(item): … # the rigid pricing routine sol = solve_regression(price, items, tol=5.0) # dataset <- price(i); train; calibrate sol(item) # a float: local (width <= tol) or teacher sol.interval(item) # (yhat, lo, hi); marginal 1 - alpha coverage sol.improve(); sol.report() # promote on selection; calibrate on fresh rows
qhat is one global width, as in standard split conformal regression.
- class RecordRegressionFeaturizer(dim=256, seed=0)[source]
Bases:
objectRecord featurizer for regression tasks.
HashedRecord(built for classification) squashes numerics throughtanh, which saturates and erases the magnitude signal a regressor needs. Here numeric keys (learned from the fit sample) map to dedicated standardized columns; everything else uses hashing.- fit(records)[source]
Learn numeric-key normalization statistics from sample records.
- transform(records)[source]
Transform records into standardized numeric columns plus hashed categorical features.
- to_spec()[source]
Serialize numeric-key statistics and hashing settings.
- featurizer_spec(f)[source]
Tagged, artifact-ready spec for the featurizers the solve shapes use.
- featurizer_from_spec(spec)[source]
Reconstruct a task featurizer from a tagged artifact spec.
- class RegressionSolution(net, featurizer, teacher, qhat, alpha, tol, holdout_mae, y_mean, y_scale, train_inputs=<factory>, train_ys=<factory>, cal_inputs=<factory>, cal_ys=<factory>, sel_inputs=<factory>, sel_ys=<factory>, selection_uses=0, calibration_evidence='solve-split', hidden=(64, ), epochs=300, lr=0.01, seed=0, n_requests=0, n_escalated=0, harvested_inputs=<factory>, harvested_ys=<factory>)[source]
Bases:
objectA calibrated numeric student in front of the routine it replaces.
- Parameters:
net (Any)
featurizer (Any)
qhat (float)
alpha (float)
tol (float)
holdout_mae (float)
y_mean (float)
y_scale (float)
train_inputs (list)
train_ys (list)
cal_inputs (list)
cal_ys (list)
sel_inputs (list)
sel_ys (list)
selection_uses (int)
calibration_evidence (str)
hidden (tuple)
epochs (int)
lr (float)
seed (int)
n_requests (int)
n_escalated (int)
harvested_inputs (list)
harvested_ys (list)
- interval(x)[source]
Return
(yhat, lo, hi)with calibrated teacher-answer coverage.
- property answers_locally: bool
Whether the calibrated precision meets the tolerance at all (else everything escalates).
- decide(x)[source]
Return the calibrated point estimate when local precision is sufficient.
If
answers_locallyis false, returnNoneto signal escalation. Unlike__call__, this method never falls through to the teacher itself, so aRoutertier can decide whether to escalate to the next tier.
- selection_coverage()[source]
Measured coverage of the CURRENT interval on the selection rows, with its denominator.
The selection rows never touch the calibration quantile, so for a freshly solved model this is an unbiased per-artifact measurement of the deployed interval’s coverage – the honest substitute for the deployment-conditional guarantee split conformal does not provide (see the module docstring). After
improve()promotions the same rows have also chosen the model;selection_usesrecords that the number is then a selection score. Returns(covered_fraction, n_rows)orNonewhen there are no selection rows.
- report()[source]
Return calibration, precision, measurement, request, and harvest metrics.
- save(path)[source]
Persist the network, featurizer, and calibration metadata.
- classmethod load(path, teacher, *, device='cpu')[source]
Reconstitute a serving RegressionSolution (no training/calibration data; improve() raises).
- improve(evidence_inputs=None)[source]
Re-fit with harvested pairs; promote on SELECTION evidence, calibrate on FRESH evidence.
The promote/reject decision reads only the selection rows (STAT-RR11-1’s repair), and the deployed
qhatis computed on rows that DID NOT EXIST before this round’s harvest began – never on the solve-time calibration rows. Reusing those rows leaks even without any direct comparison: the incumbent’s calibration-derived gate decides whether requests escalate at all, so whether a harvest exists – and therefore the candidate’s training data and whether this method can run – is a function of the old calibration draw, and a slice that shaped the candidate cannot also certify it. In the reviewer’s exact exchangeable construction, reusing the gate-contaminated slice gives 0.8857 coverage against the claimed 0.90, and fresh calibration restores 0.90 (STAT-RR12-1).Fresh evidence comes from one of two places. Passing
evidence_inputsteacher-labels a fresh batch and uses it as the calibration slice. Without it, the LASTmax(ceil(1/alpha) - 1, len(harvest) // 4)harvested pairs are RESERVED as the calibration slice and excluded from candidate training; this is sound for the regression loop specifically because its gate is all-or-none – when the route escalates, EVERY request is harvested, so conditional on the deployed artifact the harvest is the raw serving stream, not a threshold-selected slice (contrast the classification loop, whose per-query-selected escalations cannot serve as calibration evidence). When the harvest cannot yet fund the reserved slice plus at least one training row, this returns False and keeps harvesting. On promotion the reserved slice BECOMES the artifact’s calibration data (calibration_evidencerecords the regime), so the next round reserves from the next harvest and no round ever reuses rows that predate its own harvest. A consequence of honest recalibration: the deployedqhatmay grow across a promotion, because it is not the selection metric.selection_usesrecords each decision the selection rows make.
- solve_regression(teacher, inputs, *, tol, alpha=0.1, holdout=0.25, kind=None, hidden=(64,), epochs=300, lr=1e-2, dim=256, prelabeled=None, seed=0, teacher_mode='auto')[source]
Replace a numeric routine with a conformally-calibrated student (see module docstring).
- Parameters:
teacher (Callable[[...], Any]) – the numeric routine (
teacher(x) -> float); labels the dataset, remains the fallback.inputs (Sequence[Any]) – example inputs (text or dict/tuple records).
tol (float) – the caller’s precision requirement — answer locally only when the calibrated
qhat <= tol. NOTE: the coverage statement is marginal over the calibration draw and the query jointly; conditioning on this deployment gate is selection over calibration draws and is NOT covered by the guarantee — see the module docstring, and readreport()’s measuredselection_coveragefor the deployed artifact.alpha (float) – interval miscoverage level (
1 - alphamarginal coverage of the teacher’s answer).holdout (float) – fraction reserved and split into two IMMUTABLE roles at solve time — conformal CALIBRATION rows (the larger half; set
qhat, never read by promotions) and SELECTION rows (decideimprove()promotions, produce the reported measurements).prelabeled (tuple[Sequence[Any], Sequence[float]] | None) – already-teacher-labeled
(inputs, values)— typically harvested escalations from a serving deployment — folded into the TRAINING split only, never calibration. The finite-sample guarantee of the resultingqhatrequires the BASEinputsto be a genuinely fresh sample: re-solving with the sameinputsandseedreproduces the exact same calibration rows (the split is deterministic, andprelabeleddoes not perturb it), and those rows gated the very serving run that harvestedprelabeled– the STAT-RR12-1 leak in re-solve form. Supply fresh base inputs, or treat the re-solved interval as empirical rather than guaranteed.kind (str | None)
epochs (int)
lr (float)
dim (int)
seed (int)
teacher_mode (str)
- Return type:
RegressionSolution