Fresh R NNS 13.0 parity regeneration and corrective Python fixes - #3
Merged
Conversation
- scripts/regenerate_r_cache.py --fresh refuses to run in CI, verifies a live local R NNS 13.0 install, moves the existing tests/_r_cache.json to tests/_r_cache.json.bak, and regenerates every entry from an empty cache so no existing entries can be reused. - Clear NNS_R_CACHE_ONLY and NNS_OFFLINE toggles (in addition to the PYNNS variants and CI) before invoking pytest. - Start docs/r13_cache_regeneration.md provenance record for the fresh live R NNS 13.0 regeneration (final counts to be filled in when the in-progress fresh regeneration completes). - Ignore vendored NNS local-install build artifacts and the fresh-mode cache backup. https://claude.ai/code/session_015pEPxpJWbiHizgcFEm1AWf
A from-empty cache regeneration against live vendored R NNS 13.0 surfaced 216 failing parity tests. All traced to four deterministic divergences; Python is fixed to match fresh R 13.0 in each case: - LPM.VaR/UPM.VaR integer degrees 1-4: port R's exact polynomial root-finding inversion (.NNS_LPM_VaR_integer) replacing the old optimize() search. Fixes regression/M.reg confidence intervals and stack/boost prediction intervals built on these helpers. - Distance kernels: add nns_distance_path_single_bulk mirroring R's bulk path kernel, which uses the population sd of ranks sqrt((k^2-1)/12) in the lognormal weight; the single-point NNS.distance kernel keeps the sample sd. Use the bulk kernel for n.best>1 fitted values and multi-point estimates as R does. - NNS.M.reg out-of-hull multi-point extrapolation: mirror R 13.0's vectorized outsider path (bulk kernel estimates, pmax(d, 1e-10) gradient guards) and drop the old dims-dropping single-outsider quirk R no longer has. - NNS.ARMA numeric multi-lag seasonal weighting: weight each seasonal factor by its position in the vector (R's seq(n, 1, -i)), not its lag value. Removes the two formerly-xfailed Sunspots ARMA and macro VAR practical examples, which now pass against live R. Structural updates justified by fresh R output: NNS.boost no longer returns n.best, so the Python return and stale test assertions were updated, and final-estimate NaN handling now matches R. The remaining balanced-Iris boost xfail is documented as a stochastic RNG sampling gap. https://claude.ai/code/session_015pEPxpJWbiHizgcFEm1AWf
…pty cache)
Freshly regenerated from an empty cache against live vendored R NNS 13.0
(packageVersion('NNS') == 13.0), installed from tools/NNS only. No prior
cache entries were reused: scripts/regenerate_r_cache.py --fresh moved the
old cache aside and every entry was produced by a live R call.
- 2385 entries (was 2406): an instrumented cache-only replay confirmed the
21 dropped keys are stale and not computed by any current parity test.
- 456 of the 2384 shared keys changed value vs the prior committed cache;
the fresh live R 13.0 values are authoritative. See
docs/r13_cache_regeneration.md for the per-function breakdown.
- Two independent from-empty regenerations agree on 2384/2385 entries; the
sole difference is the stochastic bootstrap CI block of one NNS.ANOVA
entry (deterministic core identical), covered by a @pytest.mark.stochastic
range check.
Cache-only parity replay, smoke, and invariants all pass against this cache.
https://claude.ai/code/session_015pEPxpJWbiHizgcFEm1AWf
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.
Summary
This PR freshly regenerated
tests/_r_cache.jsonfrom vendored live R NNS 13.0 after starting from an empty cache, and fixes the deterministic Python parity gaps that the fresh run revealed.What was done
Made regeneration truly fresh. Added a
--freshmode toscripts/regenerate_r_cache.pythat refuses to run in CI, verifies a live local R NNS 13.0 install, moves the existingtests/_r_cache.jsontotests/_r_cache.json.bak, and repopulates every entry from a live R call. No existing entries were reused.Installed live vendored R NNS 13.0. Installed via
scripts/install_local_r_nns.py(R CMD INSTALL tools/NNS), never from CRAN. Verified independently:R dependencies needed to load NNS came from Ubuntu binaries;
Rfast(+zigg) was built from upstream GitHub releasev2.1.5.1-apollobecause CRAN was unreachable. NNS itself came only fromtools/NNS.Regenerated the full cache from live R.
python scripts/regenerate_r_cache.py --fresh -- -n 0 tests/parity. Result:nns_version: 13.0,schema_version: 1, 2385 entries (was 2406). The 21 dropped keys are stale — an instrumented cache-only replay confirmed no current parity test computes them. 456 of the 2384 shared keys changed value; fresh live R 13.0 values are authoritative.Fixed Python to match fresh R 13.0 (the fresh run surfaced 216 failing tests, all from four deterministic divergences):
LPM.VaR/UPM.VaRinteger degrees 1–4 (var.py): ported R 13.0's exact polynomial root-finding inversion (.NNS_LPM_VaR_integer) replacing the oldoptimize()search. Also fixed dependent regression/M.reg CIs and stack/boost prediction intervals.distance.py): addednns_distance_path_single_bulkusing the population sd of rankssqrt((k²−1)/12)in the lognormal weight (the single-point kernel keeps sample sd), and used it forn.best>1fitted values and multi-point estimates, as R does.NNS.M.regout-of-hull multi-point extrapolation (multivariate_regression.py): mirrored R 13.0's vectorized outsider path and dropped the obsolete single-outsider dims-dropping quirk.NNS.ARMAnumeric multi-lag seasonal weighting (arma.py): weight each seasonal factor by its position in the vector (R'sseq(n,1,-i)), not its lag value. This resolved the two previouslyxfail-ed Sunspots ARMA and macro VAR practical examples, which now pass against live R; theirxfailmarkers were removed.Structural test/return updates justified by fresh R output: R 13.0's
NNS.boostno longer returnsn.best, so the Python return dict and stale assertions were updated, and final-estimate NaN handling now matches R.ARMA nonseasonal nonlinear reconciliation. Live R 13.0 returns
[128.5, 113.5, 155.5, 213.667]; Python returns the same. The previously reported[125.25, 107.75, 158.75, …]Python values do not reproduce with the current implementation. Smoke expectations were verified against this live run and needed no change.Manual diagnostic scripts. No
scripts/compare_nns*.pyexist in this repo, so there was no$RPM-based univariateNNS.regextraction to fix. The univariate regression-point diagnostic intest_r13_smoke.pyalready usesNNS.reg(..., multivariate.call = TRUE)$y.Verification (all run after fresh regeneration)
If
--freshwere not used, the equivalent manual step is:Two independent from-empty regenerations agree on 2384/2385 entries; the only difference is the stochastic bootstrap CI block of one
NNS.ANOVAentry (deterministic core identical), covered by a@pytest.mark.stochasticrange check. The sole remainingxfailis the balanced-IrisNNS.boostdiagnostic, documented as a stochastic RNG sampling gap. No deterministic parity gap is excluded from the suite.Full provenance:
docs/r13_cache_regeneration.md.https://claude.ai/code/session_015pEPxpJWbiHizgcFEm1AWf
Generated by Claude Code