Skip to content

Thread sample weights through RandomForest Python API - #8306

Merged
rapids-bot[bot] merged 8 commits into
NVIDIA:mainfrom
RAMitchell:codex/enh-rf-sample-weight-python-next
Jul 3, 2026
Merged

Thread sample weights through RandomForest Python API#8306
rapids-bot[bot] merged 8 commits into
NVIDIA:mainfrom
RAMitchell:codex/enh-rf-sample-weight-python-next

Conversation

@RAMitchell

Copy link
Copy Markdown
Contributor

Summary

  • Add sample_weight support to cuML RandomForest classifier/regressor fit
  • Pass optional sample weights through the Python/Cython RF fit path into C++ training
  • Support weighted classifier/regressor score
  • Add class_weight support for RF classification, including "balanced" and explicit class-weight dictionaries
  • Reject class_weight="balanced_subsample" for now
  • Add sklearn comparison tests for zero-weight samples, weighted scoring, min_samples_leaf, and class-weight equivalence

Notes

This relies on the C++ weighted RF training support already merged in the prep work. The current PR keeps cuML's existing max_samples=1.0 behavior and works around sklearn's max_samples=None default only in tests where sklearn parameter conversion is needed.

Follow-up issue for the max_samples default/semantics discrepancy: #8305

Testing

  • pre-commit run --files python/cuml/tests/test_random_forest.py
  • python -m compileall -q python/cuml/tests/test_random_forest.py
  • pytest -q python/cuml/tests/test_random_forest.py -k 'sample_weight or class_weight'

@copy-pr-bot

copy-pr-bot Bot commented Jul 1, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@RAMitchell
RAMitchell requested a review from Copilot July 1, 2026 20:11
@RAMitchell
RAMitchell marked this pull request as ready for review July 1, 2026 20:11
@RAMitchell
RAMitchell requested a review from a team as a code owner July 1, 2026 20:11
@RAMitchell
RAMitchell requested a review from jcrist July 1, 2026 20:11
@RAMitchell RAMitchell added improvement Improvement / enhancement to an existing function non-breaking Non-breaking change labels Jul 1, 2026
@github-actions github-actions Bot added the Cython / Python Cython or Python issue label Jul 1, 2026
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

RandomForest training and scoring now accept sample weights through the accelerator override, Cython bindings, C++ row sampling, and Python estimator APIs. Class-weight handling is added for the classifier, and tests plus sklearn compatibility expectations are updated.

Changes

RandomForest weighted training and scoring

Layer / File(s) Summary
Accelerator override validation and GPU forwarding
python/cuml/cuml/accel/_overrides/sklearn/ensemble.py
sample_weight is no longer rejected on GPU, and GPU fit/score calls now forward it.
fit_treelite sample_weight plumbing
python/cuml/cuml/ensemble/randomforest_common.pyx
sample_weight is added to the Cython training binding and passed through _fit_forest into all training branches.
RandomForestClassifier weighting support
python/cuml/cuml/ensemble/randomforestclassifier.py, python/cuml/cuml_accel_tests/integration/test_rf_classifier.py, python/cuml/tests/test_random_forest.py
RandomForestClassifier adds class_weight and sample_weight handling in fit and score, with new integration and unit coverage for weighted behavior.
RandomForestRegressor sample_weight support
python/cuml/cuml/ensemble/randomforestregressor.py, python/cuml/cuml_accel_tests/integration/test_rf_regressor.py, python/cuml/tests/test_random_forest.py
RandomForestRegressor accepts sample_weight in fit and score, and tests cover weighted predictions and scoring.
RowSampler weighted selection
cpp/src/randomforest/randomforest.cuh, cpp/tests/sg/rf_test.cu
Zero-weight rows are filtered from non-bootstrap sampling, bootstrap mask sizing follows the retained rows, and weighted RF expectations are updated.
Dask fit signature formatting
python/cuml/cuml/dask/ensemble/randomforestclassifier.py, python/cuml/cuml/dask/ensemble/randomforestregressor.py
The Dask RandomForest fit signatures are reformatted without behavioral changes.
Classifier tests and sklearn compatibility
python/cuml/tests/test_sklearn_compatibility.py
RandomForest classifier and regressor sample-weight equivalence checks are marked as expected failures.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

  • rapidsai/cuml#7895: Also changes the RandomForest Cython training path in python/cuml/cuml/ensemble/randomforest_common.pyx.
  • rapidsai/cuml#8023: Directly overlaps on _RandomForestMixin GPU sample_weight handling.
  • rapidsai/cuml#8247: Related C++ weighted RandomForest row-sampling and test updates.

Suggested labels: cuml-accel, sklearn-api-compat

Suggested reviewers: hcho3, csadorf, viclafargue

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main objective: threading sample weights through the RandomForest Python API, which is the central focus of all changes across multiple files.
Description check ✅ Passed The description is directly related to the changeset, providing a clear summary of sample_weight and class_weight support additions, testing strategy, and relevant notes about implementation details and follow-up work.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@python/cuml/cuml/ensemble/randomforestclassifier.py`:
- Around line 262-294: The unsupported class_weight validation in
RandomForestClassifier.fit should run before check_inputs(...), since the
current order can mutate fit-time state via reset=True before raising. Move the
balanced_subsample NotImplementedError check to the start of fit() in
RandomForestClassifier, ahead of input validation and process_class_weight, and
add a test covering the error path to ensure the estimator is not partially
updated on failure.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 2fe3ddbe-5dab-403a-a252-72fdb7ddcd22

📥 Commits

Reviewing files that changed from the base of the PR and between 0b19540 and 1293fb3.

📒 Files selected for processing (11)
  • python/cuml/cuml/accel/_overrides/sklearn/ensemble.py
  • python/cuml/cuml/dask/ensemble/randomforestclassifier.py
  • python/cuml/cuml/dask/ensemble/randomforestregressor.py
  • python/cuml/cuml/ensemble/randomforest_common.pyx
  • python/cuml/cuml/ensemble/randomforestclassifier.py
  • python/cuml/cuml/ensemble/randomforestregressor.py
  • python/cuml/cuml_accel_tests/integration/test_rf_classifier.py
  • python/cuml/cuml_accel_tests/integration/test_rf_regressor.py
  • python/cuml/tests/dask/test_dask_random_forest.py
  • python/cuml/tests/test_random_forest.py
  • python/cuml/tests/test_sklearn_compatibility.py

Comment thread python/cuml/cuml/ensemble/randomforestclassifier.py

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.

Pull request overview

Adds sample-weighted training and scoring support to cuML’s single-GPU RandomForest Python API, threads weights through the Cython/C++ training path, and introduces class_weight for classification (with tests to validate behavior vs scikit-learn). It also updates sklearn-accelerated and Dask-distributed RF entry points to reflect the new API surface (with Dask explicitly rejecting sample_weight).

Changes:

  • Add sample_weight to RandomForestClassifier/Regressor.fit and thread it through randomforest_common.pyx into the C++ training call.
  • Support weighted score() for classifier (accuracy) and regressor (R²), plus class_weight for RF classification ('balanced' and dict).
  • Add/adjust tests for zero-weight samples, weighted scoring, min_samples_leaf interactions, and sklearn compatibility check exclusions.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
python/cuml/tests/test_sklearn_compatibility.py Skips sklearn estimator checks where RF’s binning makes sample-weight equivalence checks invalid.
python/cuml/tests/test_random_forest.py Adds sklearn comparison tests for sample_weight, weighted scoring, min_samples_leaf, and class_weight equivalence.
python/cuml/tests/dask/test_dask_random_forest.py Adds coverage that distributed RF raises for unsupported sample_weight.
python/cuml/cuml/ensemble/randomforestregressor.py Adds sample_weight to fit and weighted R² support in score.
python/cuml/cuml/ensemble/randomforestclassifier.py Adds sample_weight to fit, introduces class_weight support, and weighted accuracy in score.
python/cuml/cuml/ensemble/randomforest_common.pyx Threads sample_weight pointer into the Cython → C++ RF training calls.
python/cuml/cuml/dask/ensemble/randomforestregressor.py Extends distributed regressor fit signature and rejects sample_weight with NotImplementedError.
python/cuml/cuml/dask/ensemble/randomforestclassifier.py Extends distributed classifier fit signature and rejects sample_weight with NotImplementedError.
python/cuml/cuml/accel/_overrides/sklearn/ensemble.py Enables sklearn-accelerated RF proxy to forward sample_weight to the GPU implementation.
python/cuml/cuml_accel_tests/integration/test_rf_regressor.py Adds integration coverage for weighted RF regressor behavior through the accel path.
python/cuml/cuml_accel_tests/integration/test_rf_classifier.py Adds integration coverage for weighted RF classifier behavior through the accel path.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread python/cuml/cuml/ensemble/randomforestclassifier.py Outdated

@jcrist jcrist 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.

A few nits, but overall this is looking good (assuming tests pass)!

Comment thread python/cuml/cuml/ensemble/randomforestclassifier.py Outdated
Comment thread python/cuml/cuml/dask/ensemble/randomforestclassifier.py Outdated
@RAMitchell
RAMitchell force-pushed the codex/enh-rf-sample-weight-python-next branch from 1293fb3 to f7d280b Compare July 1, 2026 21:01
RandomForestClassifier: {
"check_sample_weight_equivalence_on_dense_data": (
"RandomForest uses quantile-binned splits, so sample weighting is "
"not equivalent to duplicating rows"

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.

Can you comment on this a bit more? The statistical semantics of sample_weight matters, and this is the one sklearn is attempting to standardize (they also have some work to do to get here across all estimators).

Are we approximately equal to this, but off by some amount due to the method used? Or are these weights conceptually different?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good that you pointed this out. Sklearn itself xfails this because of boostrapping randomness. However, we should be able to show equivalence to sklearn when bootstrapping=false and we can't. This is because sklearn was not counting zero weight instances towards min_samples and we were. So I will keep the xfail here, but fix this and add another test that checks this specific case.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We still cannot pass the test because quantisation is not aware of zero weight rows leading to slight differences with sklearn. I think this is not worth dealing with in this PR. In the future we could make quantisation weight aware ideally.

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.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Comment thread python/cuml/cuml/ensemble/randomforestclassifier.py
Comment thread python/cuml/cuml/ensemble/randomforestregressor.py
Comment thread cpp/src/randomforest/randomforest.cuh

@jcrist jcrist 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.

Two small python nits, but otherwise this LGTM! Thanks for your work here.

Approving on my end, I'll leave it up to you if/how you want to address these.

Comment thread python/cuml/cuml/ensemble/randomforestclassifier.py
Comment thread python/cuml/cuml/ensemble/randomforestclassifier.py Outdated
Comment thread python/cuml/cuml/ensemble/randomforestclassifier.py Outdated
@RAMitchell

Copy link
Copy Markdown
Contributor Author

/merge

@rapids-bot
rapids-bot Bot merged commit 857cc5a into NVIDIA:main Jul 3, 2026
102 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CUDA/C++ Cython / Python Cython or Python issue improvement Improvement / enhancement to an existing function non-breaking Non-breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants