Repository navigation
fix(ensemble): take exactly the requested fraction when subsampling - #1352
aniruddhaadak80 wants to merge 2 commits into
Conversation
The float branch resolved to int(frac * n_samples) + 1, contradicting its docstring and the sibling int branch's min(k, n). A 0.5 fraction of 1000 rows subsampled 501 rows instead of 500, and 0.01 of 100 rows resolved to 2, which tripped the guard requiring at least one row per class - reachable without any opt-in because stratified is the resolved default for classifiers.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit be7753d. Configure here.
| @@ -0,0 +1 @@ | |||
| Take exactly the requested fraction when SUBSAMPLE_SAMPLES is a float, instead of one row more, which also stopped small valid fractions from failing the class-count guard. No newline at end of file | |||
There was a problem hiding this comment.
Changelog retells internal incident
Low Severity
The towncrier fragment narrates the old one-row overshoot and names the internal class-count guard. It also claims small valid fractions no longer fail that guard, but dropping the +1 makes more of those requests fail it.
Triggered by learned rule: Towncrier fragments: user-facing change only; keep concise
Reviewed by Cursor Bugbot for commit be7753d. Configure here.
| documents, and the equivalent int spelling (500) produced a different | ||
| context for the model. The float spelling must agree with the int spelling, | ||
| truncate rather than round up, and never resolve to an empty subsample. | ||
| """ |
There was a problem hiding this comment.
Test docstring narrates prior behavior
Low Severity
The new test docstring recounts the previous int(frac * n_samples) + 1 arithmetic and why it was wrong, rather than stating only the current size contract.
Triggered by learned rule: Docstrings describe current behavior only — no call sites or code history
Reviewed by Cursor Bugbot for commit be7753d. Configure here.


Issue
Fixes #1347
Motivation and Context
In preprocessing/ensemble.py the two branches that resolve subsample_samples disagree with each other and with the parameter's own docstring:
python if isinstance(subsample_samples, int): ... size = min(subsample_samples, n_samples) # exactly what was asked else: ... size = int(subsample_samples * n_samples) + 1 # one row moreThe docstring says "If float, subsample that fraction of samples", so the +1 is simply wrong. Two observable defects follow:
No opt-in is needed to hit this: "stratified" is the resolved default for classifiers.
The fix takes the fraction exactly, truncating rather than rounding up, and keeps the floor at one row via max(1, ...) so a tiny fraction of a tiny dataset cannot resolve to an empty subsample.
Two existing tests encoded the old +1 arithmetic in their assertions and comments, and have been updated to the documented contract - one changes rac=0.2 to rac=0.25 to keep the same size=5 that its balanced-coverage assertion depends on.
Public API Changes
No signature changes. A float SUBSAMPLE_SAMPLES now yields exactly int(frac * n_samples) rows, matching its documentation and the int spelling.
How Has This Been Tested?
New tests in ests/test_preprocessing/test_ensemble.py:
The first fails on the unfixed source and passes with the fix:
`
unfixed source
FAILED ...::test__get_subsample_indices_for_estimators__float_fraction_exact_size
1 failed, 1 passed
with the fix
12 passed, 89 deselected
`
The full file gives 5 failed / 96 passed with the fix and 5 failed / 94 passed on a pristine ensemble.py - the same five failures either way, all differentiable_input and majority_downsample tests that fail without model weights, and the +2 difference is the new tests.
Worth noting: the second new test passes both before and after. It is kept as a guard on the crash rather than as a regression test for the fix.
uff check and
uff format --check are clean.
Checklist