Skip to content

Keep the most regularized SVM C within 1% of the best inner-CV count - #69

Merged
brendanx67 merged 1 commit into
mainfrom
feature/svm-c-selection-tolerance
Sep 27, 2026
Merged

brendanx67 merged 1 commit into
mainfrom
feature/svm-c-selection-tolerance

Conversation

@maccoss

@maccoss maccoss commented Sep 24, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • The first-pass grid search kept the strict maximum of the inner-CV passing counts, but neighboring C values usually pass within noise of each other. On 3-file Stellar, C = 0.1, 1 and 10 passed 5,025, 5,037 and 5,002 targets. The pick flips on tiny input changes, and it matters:
    • a weakly regularized C = 1 fit splits weight between correlated spectral features (apex-scan xcorr / median_polish_cosine against the multi-scan sg_weighted_cosine);
    • the first pass scores the same either way, but the second pass, which reuses the frozen first-pass model on reconciled peaks, scores much worse;
    • two Stellar libraries that differed only by 1e-4 GPU/CPU rounding gave 21,176 and 28,309 experiment precursors at the same entrapment FDP.
  • grid_search_c now keeps the smallest C whose count is within PercolatorConfig::c_selection_tolerance (default 0.01) of the best, through a new svm::select_c. Tolerance 0 is the old strict maximum, with the first C in grid order winning a tie.
  • In C# (osprey: Fixed first-pass SVM C selection being decided by noise ProteoWizard/pwiz#4703), the same rule:
    • took those two libraries to 30,316 and 30,485;
    • moved the regression datasets' experiment precursors by +16% (Stellar), +1% (Stellar library decoys), +6% (Stellar generated decoys with entrapment) and 0% (Astral). On the entrapment leg, the measured FDP stayed within one standard error of 1%.
  • Cross-impl: this mirrors C# PercolatorTrainer.SelectC, which shipped the rule first. As with Sample one run per precursor for first-pass SVM training #66, there is no opt-out here; C# keeps OSPREY_SVM_C_TOLERANCE only for A/B work.

Companion to ProteoWizard/pwiz#4703.

Test plan

  • cargo fmt --check, cargo clippy --workspace -- -D warnings, cargo test --workspace
  • test_select_c_tolerance runs the same cases as C# FdrTest.TestSvmCSelectionTolerance, including the real Stellar inner-CV sweep
  • test_grid_search_c_first_tie_wins still pins the strict-maximum tiebreak at tolerance 0
  • End-to-end cross-impl on 3-file Stellar against C# at its default tolerance (Compare-EndToEnd-Crossimpl.ps1 -CsSvmCTolerance '', C# from the pwiz .NET 10 port branch with the matching change):
  • The same on 3-file Astral, with Apply the best-of-runs experiment-q floor before anything reads or persists it #68 merged locally: OVERALL PASS, bit-parity at 1e-9 end to end (precursors 117,236 on both sides, Stage 7 protein FDR, blib, both passes' FDR sidecars)

Co-Authored-By: Claude noreply@anthropic.com

The first-pass grid search kept the strict maximum of the inner-CV passing
counts, but neighboring C values usually pass within noise of each other: on
3-file Stellar, C = 0.1, 1 and 10 passed 5,025, 5,037 and 5,002 targets. The
pick then flips on tiny input changes, and it matters. A weakly regularized
C = 1 fit splits weight between correlated spectral features (apex-scan xcorr
and median_polish_cosine against the multi-scan sg_weighted_cosine) in a way
that scores the first pass alike but the second pass, which reuses the frozen
first-pass model on reconciled peaks, much worse. Two Stellar libraries that
differed only by 1e-4 GPU/CPU rounding gave 21,176 and 28,309 experiment
precursors at the same entrapment FDP.

grid_search_c now keeps the smallest C whose count is within
PercolatorConfig::c_selection_tolerance (default 0.01) of the best, through a
new svm::select_c; 0 keeps the strict maximum with the first C in grid order
winning a tie, as before. In C# the same rule took the two libraries above to
30,316 and 30,485, and moved the regression datasets' experiment precursors
by +16% (Stellar), +1% (Stellar library decoys), +6% (Stellar generated decoys
with entrapment, whose measured FDP stayed within one standard error of 1%)
and 0% (Astral).

Cross-impl: mirrors C# PercolatorTrainer.SelectC, which shipped the rule
first; test_select_c_tolerance runs the same cases as C#
FdrTest.TestSvmCSelectionTolerance. As with #66 there is no opt-out here;
C# keeps OSPREY_SVM_C_TOLERANCE only for A/B work.

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 24, 2026 22:30

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Cache and sidecar validity do not account for the changed C-selection policy, allowing stale artifacts to bypass the new behavior.

Review effort: Lite
Findings: None

What changed in this PR

Updates Percolator’s SVM hyperparameter selection to prefer the strongest regularization within 1% of the best inner-CV result.

Changes:

  • Adds configurable tolerance-based select_c logic.
  • Integrates the 1% default into Percolator.
  • Adds tests and documentation.
File Summary
docs/​11-testing.md Documents the new regression test.
docs/​07-fdr-control.md Documents C-selection behavior and configuration.
crates/​osprey-ml/​src/​svm.rs Implements tolerant C selection and tests.
crates/​osprey-fdr/​src/​percolator.rs Adds and forwards the selection tolerance.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@brendanx67
brendanx67 merged commit 5807d6f into main Sep 27, 2026
4 checks passed
@brendanx67
brendanx67 deleted the feature/svm-c-selection-tolerance branch September 27, 2026 14:38
brendanx67 added a commit to ProteoWizard/pwiz-ai that referenced this pull request Sep 27, 2026
* Rust main keeps the most regularized C within 1% since maccoss/osprey#69, as C# does (#4703)
* The scripts now clear an inherited OSPREY_SVM_C_TOLERANCE; -CsSvmCTolerance defaults to ''
* Updated the development guide and dataset-runner comments to match

Co-Authored-By: Claude <noreply@anthropic.com>
brendanx67 added a commit to ProteoWizard/pwiz that referenced this pull request Sep 28, 2026
…ction (#4722)

* maccoss/osprey#69 adopted the 1% C-selection rule with no opt-out, so C# and Rust agree
* Resolved the C#-only divergence entry and reworded the docs, error text and comments

See TODO-20260924_osprey_svm_c_selection.md in pwiz-ai/todos

Co-Authored-By: Claude <noreply@anthropic.com>
chambm pushed a commit to ProteoWizard/pwiz that referenced this pull request Oct 5, 2026
…ction (#4722)

* maccoss/osprey#69 adopted the 1% C-selection rule with no opt-out, so C# and Rust agree
* Resolved the C#-only divergence entry and reworded the docs, error text and comments

See TODO-20260924_osprey_svm_c_selection.md in pwiz-ai/todos

Co-Authored-By: Claude <noreply@anthropic.com>
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.

3 participants