Repository navigation
feat(eval): the mismatch sweep as an ensemble over seeds - #177
Merged
Merged
Conversation
Run each (case, factor) of the mismatch sweep for seeds 25 to 49 through the sweep's own run_case path and score the per-epoch NEES with ensemble_nees. Adds navkit sweep mismatch --ensemble-csv/--ensemble-page/--ensemble-compare, docs/data/mismatch_ensemble.csv and a generated section of docs/mismatch.md. The existing sweep output is unchanged. The page no longer says the ensemble is the tool that can resolve a mild mismatch: the CSV shows it resolves some and not others. Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #112.
Since ADR-0029 a single run's verdict uses the effective sample size, so the mismatch sweep (5 seeds per cell, single-run verdicts) cannot resolve a mild mismatch from one run. This adds the ensemble version, the way
docs/calibration.mddoes for the benchmark cases.What changed
navkit sweep mismatch --ensemble-csv PATH [--ensemble-page PATH] [--ensemble-compare PATH] [--ensemble-seeds N]. It extends the existing command. The existing outputs are unchanged:--compare docs/data/mismatch_sweep.csvstill matches, and a test checks the single-run CSV and JSON are identical with and without the new flags.src/navkit/mismatch_ensemble.py: each (case, factor) is run for seeds 25 to 49 through the sweep's ownrun_casepath, the per-epoch NEES is kept, andensemble_neesscores it (band for 25 runs and 3 dof). Only the statisticsdocs/calibration.mdalready defines: grand mean and the shares inside, below and above the band, for the full run and, foroutage_control, the outage scope.docs/data/mismatch_ensemble.csv(deterministic; a fresh run is byte-identical).docs/mismatch.md: a new section "The ensemble over seeds". The table and the sentences are generated from the two CSVs and a test rebuilds them.CHANGELOG.md, the documentation-test list inci.yml, and the generated test-count markers (metrics.py --write; PR chore(metrics): quote the test count rounded down to a hundred, so PRs stop conflicting #174 is not merged).Result
Band for the ensemble mean over N = 25 runs with 3 degrees of freedom: 2.118 to 4.034. Shares are of the scored epochs.
My rule for resolved, which is a choice and not a test: the mild factors are 0.8, 0.9 and 1.25. The ensemble resolves one when its mean is outside the band, on the side the mismatch predicts, for more than 50.0% of the scored epochs and for a larger share than at the true noise. One run resolves it when its bulk test reads the predicted way in at least 4 of 5 seeds.
Sentences changed
docs/mismatch.md, statement 6: "The ensemble over seeds is the tool that can resolve a mild mismatch" is replaced. The CSV does not support it as written. The ensemble resolvesgnss_onlyat 0.8 and 1.25 (1.25 is one the single run could not), andoutage_controlat 1.25 on the full run. It does not resolve 0.9 in either case,outage_controlat 0.8, or any mild factor in the outage scope. One run resolvesoutage_controlat 0.8 where the ensemble does not. "Resolved" is my rule, stated on the page.docs/calibration.mdmakes that claim, so it is not edited.outage_controlat factor 1 is inside the band for all outage epochs on seeds 0 to 24 (benchmark ensemble) and below it for all of them on seeds 25 to 49. I checked my path reproduces the committed benchmark ensemble exactly on seeds 0 to 24, so this is a seed-set effect. I have not explained it.Runtime and CI
navkit sweep mismatchwith the ensemble, full grid (2 cases, 9 factors, 25 seeds each, plus the 5-seed single-run sweep): 8 min 22 s on a laptop, about 7.4 min of it the ensemble. The new tests add about 45 s to the test jobs.test (py3.13)) took 40 min, the repo states no budget for it, and I cannot time a runner from here. The extra 7 to 15 min would put it level with the longest job. The CSV is checked against the page by test, not against a fresh run. Reproduce withnavkit sweep mismatch --ensemble-csv /tmp/e.csv --ensemble-compare docs/data/mismatch_ensemble.csv. Say if you want it in the job.Mutation checks
test_a_known_input_is_scored_against_the_band...,..._agrees_with_ensemble_nees...,..._half_open_window_only).test_a_known_input_is_scored_against_the_band_for_n_runs_and_three_doffails.test_the_factor_reaches_the_filter_so_two_factors_give_two_resultsandtest_a_cell_is_the_sweeps_own_run_case_path_on_seeds_25_to_27fail.Checks
ruff, ruff format, mypy,
check_doc_tables.py(benchmark JSON in a scratch path),metrics.py --check,check_links.py,mkdocs build --strict,test_framing.py,test_quoted_numbers.py, the golden test (unchanged), and the full suite once. The full suite hadtests/test_doc_tables.py::test_the_real_documents_match_the_committed_benchmarkfailing; it fails the same on main because the localresults/benchmark.jsonis stale, andcheck_doc_tables.pypasses against a fresh one. Three other failures were mine (an import cycle, a quoted word, a page expectation); each is fixed and its test rerun.🤖 Generated with Claude Code