Skip to content

Cleanup LabelBinarizer - #8101

Merged
rapids-bot[bot] merged 7 commits into
NVIDIA:release/26.06from
jcrist:cleanup-label-binarizer
May 19, 2026
Merged

Cleanup LabelBinarizer#8101
rapids-bot[bot] merged 7 commits into
NVIDIA:release/26.06from
jcrist:cleanup-label-binarizer

Conversation

@jcrist

@jcrist jcrist commented May 13, 2026

Copy link
Copy Markdown
Member
  • Updates LabelBinarizer to follow standard cuml and sklearn conventions (simple __init__, no mutation, type reflection, ...)
  • Applies new validation
  • Adds sparse_input_ and y_type_ attributes
  • Improves validation and error messages
  • Improves resilience and sklearn compatibility
  • Improves test coverage
  • Adds support for sklearn interop
  • Adds support for cuml.accel
  • Improves docstrings

This required one change to cuml.internals.validation around handling of unsupported dtypes for cupyx.scipy.sparse. This is split out into a separate commit with a new test case.

Part of #7317.
Fixes #8087.

@jcrist jcrist self-assigned this May 13, 2026
@jcrist jcrist added improvement Improvement / enhancement to an existing function non-breaking Non-breaking change cuml-accel Issues related to cuml.accel sklearn-api-compat Issues around cuml matching sklearn API conventions/standards labels May 13, 2026
@copy-pr-bot

copy-pr-bot Bot commented May 13, 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.

@jcrist

jcrist commented May 13, 2026

Copy link
Copy Markdown
Member Author

/ok to test e395005

@github-actions github-actions Bot added the Cython / Python Cython or Python issue label May 13, 2026
@jcrist
jcrist force-pushed the cleanup-label-binarizer branch from e395005 to ed0a53b Compare May 14, 2026 17:59
@jcrist
jcrist marked this pull request as ready for review May 14, 2026 18:00
@jcrist
jcrist requested a review from a team as a code owner May 14, 2026 18:00
@jcrist
jcrist requested a review from csadorf May 14, 2026 18:00
@coderabbitai

coderabbitai Bot commented May 14, 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

Refactors label binarization for dense/sparse/multilabel inputs with GPU support, updates sparse dtype/memory coercion in check_array, exposes a cuml.accel LabelBinarizer proxy, updates docs, and adds unit/integration/import-export/validation tests.

Changes

LabelBinarizer GPU acceleration and sklearn integration

Layer / File(s) Summary
Sparse dtype normalization and coercion in check_array
python/cuml/cuml/internals/validation.py
check_array now normalizes dtype early to a list of np.dtype, detects sparse inputs upfront, filters device-memory sparse dtypes to floating types supported by cupyx.scipy.sparse, selects appropriate float fallbacks when needed, and reorders host/device coercion for sparse inputs.
Core _label_binarize helper and label_binarize wrapper
python/cuml/cuml/preprocessing/label.py
New internal _label_binarize helper supports dense/sparse inputs (including multilabel-indicator), validates parameters and classes, handles binary/multiclass/multilabel-indicator outputs (sparse or dense), applies neg_label/pos_label remapping, and returns encoded output plus metadata; label_binarize is a thin wrapper.
LabelBinarizer class refactoring with sklearn interoperability
python/cuml/cuml/preprocessing/label.py
Refactored LabelBinarizer to include InteropMixin and _cpu_class_path, added sklearn-fit helpers and CPU/GPU param/attr transfer hooks, store classes_, y_type_, sparse_input_, and rewrote fit/transform/inverse_transform to use the new core and robust validation.
Sklearn acceleration proxy for LabelBinarizer
python/cuml/cuml/accel/_overrides/sklearn/preprocessing.py
Exported LabelBinarizer proxy mapped to cuml.preprocessing.LabelBinarizer and added _gpu_inverse_transform that forwards to GPU inverse transform accepting an optional threshold.
Documentation: FAQ and limitations
docs/source/cuml-accel/faq.rst, docs/source/cuml-accel/limitations.rst
Added LabelBinarizer to the cuml.accel FAQ accelerated estimators list and documented full support with no CPU fallback in limitations.
Integration tests for LabelBinarizer
python/cuml/cuml_accel_tests/integration/test_preprocessing.py, python/cuml/tests/test_sklearn_import_export.py
Added multiclass and multilabel-indicator integration tests covering fit/transform/inverse behavior, sparse/dense inputs, and a cuML↔scikit-learn roundtrip import-export test validating attributes and transform outputs.
Unit tests for LabelBinarizer and label_binarize
python/cuml/tests/test_label_binarizer.py
Added comprehensive unit tests for not-fitted errors, invalid parameters and y types, label mismatch errors, and parametrized binary/multiclass/multilabel-indicator cases (sparse/dense and pos/neg label permutations).
Validation tests for sparse dtype coercion
python/cuml/tests/test_validation.py
Updated test_check_array_sparse_input to expect sparse device outputs coerced to float dtypes instead of raising, and added test_check_array_sparse_input_unsupported_dtype covering integral sparse dtype coercion semantics and error cases.
Naive Bayes sparse integral dtype test update
python/cuml/tests/test_naive_bayes.py
Replaced failing expectation with a parametrized test asserting integral sparse dtypes work and that MultinomialNB.predict returns the expected integer dtype.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • rapidsai/cuml#8105: Also modifies check_array dtype/coercion logic related to device/cuDF conversions.

Suggested reviewers

  • csadorf
  • dantegd
  • divyegala
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 29.73% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title 'Cleanup LabelBinarizer' concisely and clearly summarizes the primary change (refactoring and improving LabelBinarizer), which aligns with the main objective and content of the changeset across multiple files.
Description check ✅ Passed The description is directly related to the changeset, detailing specific improvements to LabelBinarizer including validation updates, new attributes, sklearn compatibility, cuml.accel support, and validation changes.
Linked Issues check ✅ Passed The pull request addresses the linked issue #8087 by adding cuml.accel support for LabelBinarizer through new override classes, documentation updates, and sklearn interoperability enhancements.
Out of Scope Changes check ✅ Passed The changes to validation.py for sparse dtype handling and updates to test_naive_bayes.py are justified as necessary for supporting sparse integral dtypes in LabelBinarizer and related operations, staying within scope.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@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/accel/_overrides/sklearn/preprocessing.py`:
- Around line 62-67: The _gpu_inverse_transform in class LabelBinarizer is
ignoring the passed threshold by calling self._gpu.inverse_transform(Y,
threshold=None); change the call to forward the threshold parameter (e.g.,
self._gpu.inverse_transform(Y, threshold=threshold)) so the user-supplied
threshold is respected; update LabelBinarizer._gpu_inverse_transform accordingly
and preserve the existing signature to keep default behavior when threshold is
None.
🪄 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: 5049aa88-9de5-472d-aa7f-d7e1b8407e27

📥 Commits

Reviewing files that changed from the base of the PR and between f9d55b1 and ed0a53b.

📒 Files selected for processing (8)
  • docs/source/cuml-accel/faq.rst
  • docs/source/cuml-accel/limitations.rst
  • python/cuml/cuml/accel/_overrides/sklearn/preprocessing.py
  • python/cuml/cuml/internals/validation.py
  • python/cuml/cuml/preprocessing/label.py
  • python/cuml/cuml_accel_tests/integration/test_preprocessing.py
  • python/cuml/tests/test_label_binarizer.py
  • python/cuml/tests/test_validation.py

Comment thread python/cuml/cuml/accel/_overrides/sklearn/preprocessing.py

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

🧹 Nitpick comments (1)
python/cuml/tests/test_sklearn_import_export.py (1)

1051-1060: ⚡ Quick win

Assert imported fitted attributes on cu_model2 directly.

cu_model2 (from sklearn on Line 1051) isn’t directly validated for y_type_ / sparse_input_. Current assertions only cover the cuML→sklearn→cuML path through roundtrip.

Suggested patch
     cu_model2 = cuml.preprocessing.LabelBinarizer.from_sklearn(sk_model)
     sk_model2 = cu_model.as_sklearn()
 
     roundtrip = cuml.preprocessing.LabelBinarizer.from_sklearn(sk_model2)
     assert_roundtrip_consistency(cu_model, roundtrip)
@@
     np.testing.assert_array_equal(cu_model.classes_, sk_model2.classes_)
     np.testing.assert_array_equal(cu_model.classes_, roundtrip.classes_)
+    assert cu_model2.y_type_ == sk_model.y_type_
+    assert cu_model2.sparse_input_ == sk_model.sparse_input_
     assert roundtrip.y_type_ == cu_model.y_type_
     assert roundtrip.sparse_input_ == cu_model.sparse_input_
🤖 Prompt for 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.

In `@python/cuml/tests/test_sklearn_import_export.py` around lines 1051 - 1060,
Add direct assertions to validate that the cuML model produced by importing the
fitted sklearn model (cu_model2 from
cuml.preprocessing.LabelBinarizer.from_sklearn(sk_model)) preserved fitted
attributes; specifically, assert that cu_model2.classes_ equals
cu_model.classes_ (or sk_model2.classes_), and assert cu_model2.y_type_ ==
cu_model.y_type_ and cu_model2.sparse_input_ == cu_model.sparse_input_. Keep the
existing roundtrip checks (roundtrip and sk_model2) but add these direct
assertions on cu_model2 to cover the sklearn→cuML import path.
🤖 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.

Nitpick comments:
In `@python/cuml/tests/test_sklearn_import_export.py`:
- Around line 1051-1060: Add direct assertions to validate that the cuML model
produced by importing the fitted sklearn model (cu_model2 from
cuml.preprocessing.LabelBinarizer.from_sklearn(sk_model)) preserved fitted
attributes; specifically, assert that cu_model2.classes_ equals
cu_model.classes_ (or sk_model2.classes_), and assert cu_model2.y_type_ ==
cu_model.y_type_ and cu_model2.sparse_input_ == cu_model.sparse_input_. Keep the
existing roundtrip checks (roundtrip and sk_model2) but add these direct
assertions on cu_model2 to cover the sklearn→cuML import path.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 55416ea7-1fc2-40e8-9314-9395e4d92b7e

📥 Commits

Reviewing files that changed from the base of the PR and between ed0a53b and 732a47c.

📒 Files selected for processing (1)
  • python/cuml/tests/test_sklearn_import_export.py

@jcrist
jcrist changed the base branch from main to release/26.06 May 14, 2026 23:39

@csadorf csadorf left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One minor behavioral divergence we should fix, otherwise LGTM. Fantastic work!

LabelBinarizer
^^^^^^^^^^^^^^

``LabelBinarizer`` supports all cases and will never fall back to CPU.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔥

Comment on lines +118 to +119
# XXX: cudf's to_numpy doesn't support conversions for all
# dtypes. Roundtrip through object dtype when necessary.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

(suggestion not directly related to this pr) I think it would be worthwhile to catalog those and similar limitations and ensure that they are reported upstream.

Comment thread python/cuml/cuml/preprocessing/label.py
@jcrist
jcrist force-pushed the cleanup-label-binarizer branch from a085d15 to b4e3eca Compare May 18, 2026 17:09

@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/tests/test_validation.py`:
- Around line 1005-1012: The pytest.raises match strings contain unescaped regex
metacharacters (the dots in "cupyx.scipy.sparse"), making the regex too
permissive; update the three pytest.raises calls that wrap check_array (those
passing host_i4, device_f4, and device_f4 with mem_type=None) to escape the dots
(e.g., "cupyx\\.scipy\\.sparse") or construct the pattern with re.escape so the
literal module path is matched precisely.
🪄 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: 46980743-efaa-428f-b1d5-4ca50dc319bd

📥 Commits

Reviewing files that changed from the base of the PR and between 67806a1 and b4e3eca.

📒 Files selected for processing (10)
  • docs/source/cuml-accel/faq.rst
  • docs/source/cuml-accel/limitations.rst
  • python/cuml/cuml/accel/_overrides/sklearn/preprocessing.py
  • python/cuml/cuml/internals/validation.py
  • python/cuml/cuml/preprocessing/label.py
  • python/cuml/cuml_accel_tests/integration/test_preprocessing.py
  • python/cuml/tests/test_label_binarizer.py
  • python/cuml/tests/test_naive_bayes.py
  • python/cuml/tests/test_sklearn_import_export.py
  • python/cuml/tests/test_validation.py
✅ Files skipped from review due to trivial changes (1)
  • docs/source/cuml-accel/faq.rst
🚧 Files skipped from review as they are similar to previous changes (7)
  • docs/source/cuml-accel/limitations.rst
  • python/cuml/cuml/accel/_overrides/sklearn/preprocessing.py
  • python/cuml/tests/test_naive_bayes.py
  • python/cuml/cuml_accel_tests/integration/test_preprocessing.py
  • python/cuml/tests/test_sklearn_import_export.py
  • python/cuml/tests/test_label_binarizer.py
  • python/cuml/cuml/preprocessing/label.py

Comment thread python/cuml/tests/test_validation.py
jcrist added 6 commits May 18, 2026 16:27
- Updates `LabelBinarizer` to follow standard cuml and sklearn
  conventions (simple __init__, no mutation, type reflection, ...)
- Applies new validation
- Adds `sparse_input_` and `y_type_` attributes
- Improves validation and error messages
- Improves resilience and sklearn compatibility
- Adds support for sklearn interop
- Adds support for cuml.accel
- Improves docstrings
@jcrist
jcrist force-pushed the cleanup-label-binarizer branch from fb92192 to 3333b51 Compare May 18, 2026 21:27
@jcrist

jcrist commented May 19, 2026

Copy link
Copy Markdown
Member Author

/merge

@rapids-bot
rapids-bot Bot merged commit ac61931 into NVIDIA:release/26.06 May 19, 2026
94 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cuml-accel Issues related to cuml.accel Cython / Python Cython or Python issue improvement Improvement / enhancement to an existing function non-breaking Non-breaking change sklearn-api-compat Issues around cuml matching sklearn API conventions/standards

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add cuml.accel support for LabelBinarizer

4 participants