Prefer a robust parameter plateau over the in-sample peak in optimize() #145
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Concern
optimize(family, metric)returns the single argmax member —crates/aura-registry/src/lib.rs:186. By construction it selects the sharpest in-sample peak, with no preference for a parameter region that is stable in its neighbourhood. A peak that sits on a narrow spike of the metric surface is the configuration most likely to be fit to noise: a small shift in the data, or in the parameters themselves, collapses it.The one adjacent primitive,
param_stability(crates/aura-engine/src/walkforward.rs:254), reports the dispersion of the chosen parameters across walk-forward windows, but it is an on-demand post-hoc diagnostic emitted as a CLI field — it never feeds back into selection.What to build
A selection objective that prefers a broad, stable region of the parameter space over an isolated optimum:
optimize.param_stability, or an equivalent across-window stability measure, usable as a selection criterion and not only as a diagnostic.Relationship to #139 and the trials-deflation issue
Complementary. #139 tests a chosen candidate out-of-sample; the trials-deflation issue corrects the winner's score for family size. This issue changes which member is chosen in the first place — a robust plateau rather than the noise-fit peak — and applies equally to #139's per-window in-sample sweep.
Notes
GridSpacealready enumerates a cartesian lattice (crates/aura-engine/src/sweep.rs:19), so grid-neighbour lookup is well-defined;RandomSpaceneighbourhoods need a distance metric, flagged as a design point.Design reconciliation (specify, /boss) — spec 0077
Entry path: specify (design settled by the milestone design-recon + judge verdict;
the forks below are derived, not user-preference). Trunk: a new
optimize_plateau(family, axis_lens, metric, mode)besideoptimize/optimize_deflatedthat argmaxes a neighbourhood-aggregated (mean/worst over grid neighbours) score —
a parameter-free robustness statement, NOT a gradient-penalty (which needs a
metric-scale-sensitive free knob with no principled default).
Derived decisions (rationale, recorded for after-the-fact audit):
optimize_plateau, never aSweepFamilyfield. Basis: derived — a field breaksSweepFamily's derivedPartialEq + four
SweepFamily { space, points }struct-literal sites; theGridSpace owns the per-axis cardinalities at the live walk-forward call site, and
the lattice is only needed transiently at selection. Needs a new
GridSpace::axis_lens()(per-axis lengths inparam_space()order) surfaced outof the sweep builder.
--select plateauon a random sweep (exit 2).Basis: derived — plateau adjacency falls out of a GridSpace lattice; a kNN
metric+radius is an invented design choice, and the CLI walk-forward path is
all-GridSpace, so RandomSpace plateau is unexercised. kNN deferred to its own cycle.
--select plateau:mean|plateau:worst, defaultmean.Basis: derived — mean is the less-surprising statement;
worsthas anedge-neighbour-truncation bias toward interior points (worth a test before a
default); the chosen mode is recorded, so runs stay reproducible.
--select <argmax|plateau:mean|plateau:worst>,default
argmax. Basis: derived — C23 byte-preserving (every existing run staysidentical, plateau strictly opt-in); per-arm selection is unmotivated.
recon predated #144, which landed a deflation-shaped
FamilySelection+SelectionMode{Argmax}. The selection RULE (argmax vs plateau — which memberwins) and the deflation ANNOTATION (how inflated the winner is) are ORTHOGONAL.
Resolution: extend the shared carrier minimally — add
SelectionMode::PlateauMean/
PlateauWorst(the slot #144 reserved), makedeflated_score: f64 → Option<f64>(None under plateau, the one genuinely deflation-specific scalar), and add
neighbourhood_score: Option<f64>+n_neighbours: Option<usize>(None underargmax).
optimize_deflatedpopulates the deflation fields undermode=Argmax;optimize_plateaupopulates the plateau fields undermode=Plateau*. Basis:derived — one composable carrier across both milestone pieces beats a second
parallel type; the reshape is a small wire change to #144's one-cycle-old,
test-only-data type (legacy lines still load via serde(default)); #144's existing
deflation + serde-back-compat tests are the green gate the reshape must preserve.
Out of scope (deferred): RandomSpace kNN plateau; offline re-plateau of a reloaded
family; per-arm selection. C23 default-argmax keeps every existing walk-forward run
byte-identical; plateau is strictly opt-in.
Planner-stage fork decisions (/boss) — plan 0077
Two load-bearing forks surfaced while mapping spec 0077 onto the current tree (plan-recon
DONE_WITH_CONCERNS). Both derived and recorded here for after-the-fact audit/veto.Fork: where
axis_lenssurfaces (engine terminal vs CLI-local recompute).→ Engine. A new
SweepBinder::sweep_with_latticeterminal returns(SweepFamily, Vec<usize>)from theGridSpaceit already builds (aura-engine/src/blueprint.rs:401);sweep()is refactored to delegate to it (byte-unchanged for every existing.sweep()caller, C23).GridSpace::axis_lens()is the accessor.Basis: derived — only the engine's post-
resolve_axesGridSpaceholds the lattice inparam_space()/odometer order, whichclosed_neighbourhood's mixed-radix arithmetic requires; recomputing it CLI-side from.axis(name, vals)call-order would duplicateresolve_axesand risk a silent order mismatch (wrong neighbours). The spec itself leans this way ("asweep_with_latticevariant, or the builder exposes the builtGridSpace", lines 161-164). A sibling terminal, not a signature change tosweep, contains the blast radius.Fork: the RandomSpace-refuse — spec assumes a
--randomwalk-forward producer that does not exist.→ Structural guard, no new feature.
walkforwardhas no--randomflag (verified:--random/RandomSpace/RandomBinderappear nowhere inaura-cli), and the spec specifies no random-walk-forward producer (no component, no data-flow). So the refuse is implemented as the type-level guard the spec wants —sweep_over/stage1_r_sweep_overreturn(SweepFamily, Option<Vec<usize>>)(Sometoday, grid-only), and aselect_winnerhelper returns the refuse onPlateau + None-lattice; the caller prints the spec's message and exits 2. It is unit-tested at the helper level (theErrpath), not via awalkforward --randomE2E — the spec's--random 64example (line 96) uses a flag this cycle does not build.Basis: derived — the spec's authoritative scope (Components table + "Out of scope", which defers RandomSpace-plateau support entirely) grounds the minimal reading: refuse is forward-looking structure, wiring a random walk-forward sweep is unspecified out-of-scope work. The guard becomes CLI-reachable the moment a random walk-forward producer is ever added.
Minor (spec already settles it):
FamilySelection.seedreshapes toOption<u64>(spec line 135); the recon carrier'sOption<usize>was a transcription slip.