Skip to content

stack: add nns_stack_fit / nns_stack_predict (fit-once, reuse CV/RPM)#134

Merged
OVVO-Financial merged 1 commit into
mainfrom
claude/nns-stack-fit-predict
Jul 18, 2026
Merged

stack: add nns_stack_fit / nns_stack_predict (fit-once, reuse CV/RPM)#134
OVVO-Financial merged 1 commit into
mainfrom
claude/nns-stack-fit-predict

Conversation

@OVVO-Financial

Copy link
Copy Markdown
Owner

Summary

Implements the RPM/CV caching item from the performance discussion (#3) as a real fit/predict split for NNS.stack. The cross-validated model selection — the dominant cost — now runs once and is reused across predictions, instead of re-running the full out-of-fold CV on every call.

API

fit  = nns_stack_fit(x, y, method=(1, 2), dim_red_method="equal", order="max", folds=5)
pred = nns_stack_predict(fit, new_x)["stack"]   # no CV re-run

How it works

  • nns_stack gains an opt-in fitted bypass. When supplied, the three CV fold-loops (dimension count, n.best, ensemble weight) are skipped and the stored hyperparameters are used; only the cheap, test-dependent final production fit + X* projection runs. The default fitted=None leaves behavior byte-identical.
  • return_fit=True attaches the selected hyperparameters as a private _fit state. The default public result dict is unchanged (no new key — the existing key-set contract holds).
  • nns_stack_fit runs the selection once and returns a lightweight fit object (training data + call args + _fit); nns_stack_predict scores new data reusing it.

Since the CV selection is test-independent, fitting with no test set yields exactly the hyperparameters a full nns_stack(x, y, new_x) would select — so predictions are identical, not approximate.

Validation

  • Parity (byte-identical): nns_stack_predict(fit, new_x)["stack"] == nns_stack(x, y, new_x)["stack"] across method ∈ {(1,2),(1,),(2,)} × dim_red_method ∈ {cor, equal, NNS.dep} (atol=1e-9).
  • Speed: fit-once + 5 predictions ≈ 5.4× faster than 5 full stacks (2000×4, order="max", folds=5).
  • No regression: full invariant suite (346 tests) passes unchanged; new tests cover export, parity, and the unchanged default key-set. ruff clean.

Notes

  • Additive and backward-compatible — no change to the default nns_stack result or behavior.
  • This is the Python side. The R NNS.stack (OVVO-Financial/NNS) could take the same additive fitted/return_fit split; happy to follow up there if wanted.

🤖 Generated with Claude Code


Generated by Claude Code

Adds a real fit/predict split to NNS.stack so the cross-validated model
selection - the dominant cost - runs once and is reused across predictions,
instead of re-running the full out-of-fold CV on every call.

  * nns_stack gains an opt-in "fitted" bypass: when supplied, the three CV
    fold-loops (dimension count, n.best, ensemble weight) are skipped and the
    stored hyperparameters are used; only the (cheap, test-dependent) final
    production fit + projection runs. The default (fitted=None) leaves behavior
    byte-identical.
  * return_fit=True attaches the selected hyperparameters as the "_fit" state;
    the default public result dict is unchanged (no new key).
  * nns_stack_fit(x, y, ...) runs the selection once and returns a fit object;
    nns_stack_predict(fit, newdata) scores new data reusing it.

Verified: nns_stack_predict(fit, newdata) is byte-identical to a full
nns_stack(x, y, newdata) call across method in {(1,2),(1,),(2,)} times
dim_red_method in {cor, equal, NNS.dep} (the selection is test-independent).
Fit-once + 5 predictions runs ~5.4x faster than 5 full stacks (2000x4,
order='max', folds=5). Full invariant suite (346) passes unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@OVVO-Financial
OVVO-Financial merged commit f917049 into main Jul 18, 2026
1 of 9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants