Thanks to visit codestin.com
Credit goes to github.com

Skip to content

DOC HalvingGridSearchCV/HalvingRandomSearchCV: clarify best_estimator_ reflects last halving iteration - #33723

Merged
betatim merged 7 commits into
scikit-learn:mainfrom
RudrenduPaul:doc/halving-search-best-estimator-last-iter
Jun 2, 2026
Merged

DOC HalvingGridSearchCV/HalvingRandomSearchCV: clarify best_estimator_ reflects last halving iteration#33723
betatim merged 7 commits into
scikit-learn:mainfrom
RudrenduPaul:doc/halving-search-best-estimator-last-iter

Conversation

@RudrenduPaul

@RudrenduPaul RudrenduPaul commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

Description

Closes #24901.

HalvingGridSearchCV and HalvingRandomSearchCV use a custom _select_best_index callable (line 194–214 of _search_successive_halving.py) that picks the best candidate from the final halving iteration only — not the globally best-ranked row in cv_results_. However, the existing docstrings for best_estimator_, best_score_, and best_params_ did not mention this, leading users to expect that best_params_ matches the rank_test_score == 1 row in cv_results_ (which may come from an earlier iteration with fewer resources).

Changes

  • best_estimator_: Added "in the last halving iteration" to the description + a .. note:: block explaining why earlier-iteration candidates can outrank the final winner in cv_results_, and showing how to filter cv_results_['iter'] == n_iterations_ - 1 to see only final-iteration results.
  • best_score_: Clarified it is "computed over the candidates from the last halving iteration only."
  • best_params_: Added "in the last halving iteration" to the description.

Both HalvingGridSearchCV and HalvingRandomSearchCV share identical docstrings for these attributes, so both were updated.

Motivation

Discussed in #24901: multiple users were confused because cv_results_['rank_test_score'] == 1 pointed to an early-iteration candidate (with a high but unreliable score from a small sample), while best_params_ pointed to a different set of parameters. The root cause is documented in the code but not in the public API documentation.


AI Assistance Disclosure (required per AGENTS.md)
This pull request includes code written with the assistance of AI (Claude Code).
All changes have been read, understood, and verified by the human contributor (Rudrendu Paul).

…_ reflects last halving iteration

best_estimator_, best_score_, and best_params_ select the winner from the
final halving iteration only (via the _select_best_index callable), not the
globally highest-ranked entry in cv_results_. The global rank_test_score can
show earlier-iteration candidates ranked scikit-learn#1 because ranking spans all iterations,
but those scores come from fewer resources and are less reliable.

Added a .. note:: block to best_estimator_ explaining the distinction and
showing how to filter cv_results_ by the final iteration. Also clarified
best_score_ and best_params_ docstrings to make this explicit.

Closes scikit-learn#24901

Built by Rudrendu Paul, developed with Claude Code

@StefanieSenger StefanieSenger left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for this documentation enhancement, @RudrenduPaul.

best_estimator_ etc. in Halving*Search are indeed only chosen from within the last halving iteration and it is helpful to be clear about it in the docs. I think these changes are clear and understandable.

@StefanieSenger StefanieSenger added the Waiting for Second Reviewer First reviewer is done, need a second one! label Apr 11, 2026

@betatim betatim left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Some small clean up comment and one about shortening the docstring a bit if possible.

Otherwise I like it

on the left out data. Not available if ``refit=False``.
Estimator that was chosen by the search, i.e. estimator which gave
the highest score (or smallest loss if specified) on the left out data
**in the last halving iteration**. Not available if ``refit=False``.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
**in the last halving iteration**. Not available if ``refit=False``.
in the last halving iteration. Not available if ``refit=False``.

Not sure we need this

Estimator that was chosen by the search, i.e. estimator
which gave highest score (or smallest loss if specified)
on the left out data. Not available if ``refit=False``.
Estimator that was chosen by the search, i.e. estimator which gave

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Would it be possible to make the edit so that the unchanged lines are not changed? It helps keep the amount of churn in the git blame history low.

Same comment for the other instances where this happened.

Comment thread sklearn/model_selection/_search_successive_halving.py
RudrenduPaul and others added 2 commits April 14, 2026 01:47
Per @betatim review: restore original line wrapping to minimize git blame
churn, remove bold from 'in the last halving iteration', and shorten the
note by removing parenthetical about global ranking.

Built by Rudrendu Paul, developed with Claude Code
@StefanieSenger

Copy link
Copy Markdown
Member

Hi @RudrenduPaul, can you give us a summary feedback please? Did you integrate everything @betatim had suggested to you?

Combine the two-line ``Not available if refit=False`` sentence back onto
one line in both HalvingGridSearchCV and HalvingRandomSearchCV, exactly
as betatim's inline suggestion shows.

Built by Rudrendu Paul, developed with Claude Code
@RudrenduPaul

Copy link
Copy Markdown
Contributor Author

Hi @StefanieSenger and @betatim — apologies for the delayed follow-up. Summary of what I've integrated:

  1. best_estimator_ line — merged the two lines back into one, per @betatim's inline suggestion (applies to both HalvingGridSearchCV and HalvingRandomSearchCV).
  2. Whitespace churn — the prior commit "restore original wrapping" already addressed this; the current diff touches only the lines with substantive changes.
  3. .. note:: length — the note was shortened to @betatim's compact version in the previous commit and remains as-is.

All three suggestions are now integrated. Happy to make any further adjustments.

@github-actions github-actions Bot added the CI:Linter failure The linter CI is failing on this PR label May 10, 2026
Remove "Not available if ``refit=False``." from best_estimator_ in
both HalvingGridSearchCV and HalvingRandomSearchCV. This was flagged
by betatim as "not sure we need this" and caused E501 lint violations
(94 > 88 chars) introduced by the previous commit.

Built by Rudrendu Paul, developed with Claude Code
@RudrenduPaul

Copy link
Copy Markdown
Contributor Author

Pushed a follow-up commit to fix an E501 linting error introduced in the previous commit.

The merged line on the left out data, in the last halving iteration. Not available if ``refit=False``. was 94 characters — above the 88-char limit — so the CI lint check was failing. I've removed the Not available if ``refit=False``. clause (which @betatim noted as "not sure we need this") so the line is now 60 characters. All other changes remain the same.

@github-actions github-actions Bot removed the CI:Linter failure The linter CI is failing on this PR label May 10, 2026
Comment thread sklearn/model_selection/_search_successive_halving.py
@StefanieSenger

StefanieSenger commented Jun 2, 2026

Copy link
Copy Markdown
Member

I've added the last lacking line. I think this PR is now ready to merge, @betatim. Thanks a lot for your work, @RudrenduPaul!

@betatim betatim left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for improving the documentation and the last little fix

@betatim
betatim merged commit 87518b3 into scikit-learn:main Jun 2, 2026
38 checks passed
prady0t pushed a commit to prady0t/scikit-learn that referenced this pull request Sep 2, 2026
…_ reflects last halving iteration (scikit-learn#33723)

Co-authored-by: Stefanie Senger <[email protected]>
Co-authored-by: Tim Head <[email protected]>
Co-authored-by: Stefanie Senger <[email protected]>
@jeremiedbb jeremiedbb mentioned this pull request Sep 8, 2026
14 tasks
jeremiedbb pushed a commit that referenced this pull request Sep 10, 2026
…_ reflects last halving iteration (#33723)

Co-authored-by: Stefanie Senger <[email protected]>
Co-authored-by: Tim Head <[email protected]>
Co-authored-by: Stefanie Senger <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Inconsistent results with HalvingGridSearchCV

3 participants