Skip to content

Apply new validation to metrics.confusion_matrix - #8049

Merged
rapids-bot[bot] merged 5 commits into
NVIDIA:mainfrom
csadorf:issue-7998-apply-new-validation-to-metrics-confusion-matrix
May 6, 2026
Merged

Apply new validation to metrics.confusion_matrix#8049
rapids-bot[bot] merged 5 commits into
NVIDIA:mainfrom
csadorf:issue-7998-apply-new-validation-to-metrics-confusion-matrix

Conversation

@csadorf

@csadorf csadorf commented May 5, 2026

Copy link
Copy Markdown
Contributor

Convert metrics.confusion_matrix to new input validation system.

Part of #7998

Replace legacy input_to_cuml_array / input_to_cupy_array calls in
cuml.metrics.confusion_matrix with the new cuml.internals.validation
helpers (check_array, check_consistent_length, check_sample_weight),
matching the pattern established by the _classification, _ranking,
and regression metrics migrations (xref NVIDIA#7998).
@csadorf
csadorf requested a review from a team as a code owner May 5, 2026 16:02
@csadorf
csadorf requested a review from viclafargue May 5, 2026 16:02
@github-actions github-actions Bot added the Cython / Python Cython or Python issue label May 5, 2026
@csadorf csadorf added improvement Improvement / enhancement to an existing function non-breaking Non-breaking change labels May 5, 2026
@coderabbitai

coderabbitai Bot commented May 5, 2026

Copy link
Copy Markdown
📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Optional automatic label dtype conversion to enforce integer label types.
  • Bug Fixes

    • Stricter validation with clear errors for input shapes (now documented as 1D), label dtypes, sample-weight length, and normalization options.
  • Tests

    • Added unit tests covering error cases and dtype-conversion behavior to ensure compatibility with reference implementations.

Walkthrough

Refactors confusion_matrix to use standardized validation helpers (check_array, check_consistent_length, check_sample_weight), enforces 1D integer label dtypes, validates/constructs sample_weight, validates normalize, removes using_output_type("cupy"), updates return type to cp.ndarray, and adds unit tests for error cases and dtype coercion. (≤50 words)

Changes

Confusion Matrix Input Validation & Tests

Layer / File(s) Summary
Imports & DTypes
python/cuml/cuml/metrics/confusion_matrix.py
Replaced input_to_cuml_array/input_to_cupy_array/using_output_type imports with check_array, check_consistent_length, check_sample_weight; introduced _LABEL_DTYPES and _WEIGHT_DTYPES.
Function Signature & Return Type
python/cuml/cuml/metrics/confusion_matrix.py
Docstring and annotation updated to 1D-only inputs; return type changed from CumlArray to cp.ndarray.
Primary Input Validation
python/cuml/cuml/metrics/confusion_matrix.py
y_true and y_pred validated via check_array (dtype restricted to _LABEL_DTYPES, ensure_2d=False), enforce 1D shape, then check_consistent_length.
Labels Handling
python/cuml/cuml/metrics/confusion_matrix.py
If labels is None compute with sorted_unique_labels from validated arrays; otherwise validate labels with check_array and enforce 1D.
Sample Weight & Normalize
python/cuml/cuml/metrics/confusion_matrix.py
sample_weight validated via check_sample_weight (length checked) or created as cp.ones(n_rows, dtype=y_true.dtype) when None. normalize validated early with explicit ValueError for invalid values.
Relabeling & Core Logic
python/cuml/cuml/metrics/confusion_matrix.py
Removed using_output_type("cupy"); call make_monotonic directly on validated arrays and construct/normalize confusion matrix using the validated inputs.
Documentation Update (dask variant)
python/cuml/cuml/dask/metrics/confusion_matrix.py
Docstring adjusted to document 1D-only y_true/y_pred shapes; SPDX year bumped.
Tests
python/cuml/tests/test_metrics.py
Added test_confusion_matrix_errors (invalid lengths, non-integer label dtypes without conversion, 2D inputs for y_true/labels, bad sample_weight length, invalid normalize) and test_confusion_matrix_convert_dtype (verifies convert_dtype=True coerces floats to int32 and matches sklearn).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • rapidsai/cuml#8012: Similar migration of metric functions to the new validation helpers (check_array, etc.).
  • rapidsai/cuml#8050: Another PR applying the same input-validation migration across modules.

Suggested reviewers

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

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% 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 title 'Apply new validation to metrics.confusion_matrix' clearly and concisely describes the main change: replacing legacy input validation with the new validation system in the confusion_matrix function.
Description check ✅ Passed The description 'Convert metrics.confusion_matrix to new input validation system. Part of #7998' directly relates to the changeset, explaining the migration to the new validation system and referencing the related issue.
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.

✏️ 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
python/cuml/cuml/metrics/confusion_matrix.py (1)

110-138: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Incorrect return type annotation.

The function declares -> CumlArray but returns a raw cp.ndarray. Update the annotation to cp.ndarray or remove it if not strictly required.

🤖 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/cuml/metrics/confusion_matrix.py` around lines 110 - 138, The
function's declared return type (-> CumlArray) doesn't match the actual return
(a cupy ndarray); update the function signature to return cp.ndarray (or remove
the explicit annotation) where the function is defined (confusion_matrix in
confusion_matrix.py), and ensure any related type hints/exports referencing
CumlArray are adjusted accordingly so the annotation matches the actual return
type.
🤖 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.

Outside diff comments:
In `@python/cuml/cuml/metrics/confusion_matrix.py`:
- Around line 110-138: The function's declared return type (-> CumlArray)
doesn't match the actual return (a cupy ndarray); update the function signature
to return cp.ndarray (or remove the explicit annotation) where the function is
defined (confusion_matrix in confusion_matrix.py), and ensure any related type
hints/exports referencing CumlArray are adjusted accordingly so the annotation
matches the actual return type.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 95d03e3e-b3f4-4dad-bbd8-fd3d647404cd

📥 Commits

Reviewing files that changed from the base of the PR and between f39dde1 and 3c27601.

📒 Files selected for processing (2)
  • python/cuml/cuml/metrics/confusion_matrix.py
  • python/cuml/tests/test_metrics.py

The confusion_matrix function creates a cupy ndarray via .toarray()
and operates on it with cp.divide / cp.nan_to_num throughout. Declaring
-> CumlArray was therefore incorrect.

- Change return annotation from -> CumlArray to -> cp.ndarray
- Remove unused CumlArray import

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
python/cuml/cuml/metrics/confusion_matrix.py (1)

28-54: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Align the return docstring with the new concrete return type.

Line 28 now annotates cp.ndarray, but the Returns section still describes a generic “array-like (device or host)”. Tightening this avoids API ambiguity for callers.

📝 Suggested doc update
-    C : array-like (device or host) shape = (n_classes, n_classes)
-        Confusion matrix.
+    C : cupy.ndarray of shape (n_classes, n_classes)
+        Confusion matrix on device.
🤖 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/cuml/metrics/confusion_matrix.py` around lines 28 - 54, Update
the Returns docstring for the confusion_matrix function to match the concrete
return type cp.ndarray: replace "array-like (device or host) shape = (n_classes,
n_classes)" with "cp.ndarray shape = (n_classes, n_classes)" and keep the
descriptive text "Confusion matrix" (and mention device/host behavior if
desired). Edit the Returns section for the confusion_matrix function so the
documented type aligns with the annotated return cp.ndarray.
🤖 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.

Outside diff comments:
In `@python/cuml/cuml/metrics/confusion_matrix.py`:
- Around line 28-54: Update the Returns docstring for the confusion_matrix
function to match the concrete return type cp.ndarray: replace "array-like
(device or host) shape = (n_classes, n_classes)" with "cp.ndarray shape =
(n_classes, n_classes)" and keep the descriptive text "Confusion matrix" (and
mention device/host behavior if desired). Edit the Returns section for the
confusion_matrix function so the documented type aligns with the annotated
return cp.ndarray.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 016a8c9f-15d0-41e4-9aa5-da5533b351fe

📥 Commits

Reviewing files that changed from the base of the PR and between 3c27601 and 5bc8f06.

📒 Files selected for processing (1)
  • python/cuml/cuml/metrics/confusion_matrix.py

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

Thanks for working on this! LGTM

Comment thread python/cuml/cuml/metrics/confusion_matrix.py
Comment thread python/cuml/cuml/metrics/confusion_matrix.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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
python/cuml/cuml/metrics/confusion_matrix.py (1)

47-50: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update convert_dtype docs to reflect sample-weight conversion path.

The docstring currently describes coercion for labels/targets only, but Line 95-97 also applies convert_dtype to sample_weight.

Proposed doc tweak
     convert_dtype : bool, optional (default=False)
         When set to True, the confusion matrix method will automatically
-        convert the predictions, ground truth, and labels arrays to np.int32.
+        convert the predictions, ground truth, and labels arrays to np.int32,
+        and coerce sample_weight to a supported numeric dtype when needed.

As per coding guidelines: "Missing docstrings for public methods, undocumented hyperparameters, or missing scikit-learn compatibility notes in documentation must be addressed."

🤖 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/cuml/metrics/confusion_matrix.py` around lines 47 - 50, Update
the confusion_matrix docstring to state that convert_dtype not only coerces
predictions, ground truth, and labels to np.int32 but also coerces sample_weight
to np.int32 (see the conversion logic at the lines applying convert_dtype around
sample_weight). Modify the parameter description for convert_dtype in the
confusion_matrix function/class docstring to explicitly mention sample_weight
conversion and any related behavior or caveats so the docs match the
implementation.
python/cuml/cuml/dask/metrics/confusion_matrix.py (1)

63-66: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Document that normalize=None is supported.

Line 63 currently documents only string values, but Line 82 explicitly accepts None. Please align the parameter docs with runtime behavior.

Proposed doc tweak
-    normalize : string in ['true', 'pred', 'all']
+    normalize : {'true', 'pred', 'all'} or None, default=None

As per coding guidelines: "Missing docstrings for public methods, undocumented hyperparameters, or missing scikit-learn compatibility notes in documentation must be addressed."

🤖 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/cuml/dask/metrics/confusion_matrix.py` around lines 63 - 66,
Update the docstring for the normalize parameter in the confusion_matrix
function to state that normalize may be one of the strings 'true', 'pred', or
'all' or None (default), and describe that None means no normalization will be
applied; ensure the normalize description in the parameter block matches the
runtime behavior checked in the function where normalize is compared to None.
🤖 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.

Outside diff comments:
In `@python/cuml/cuml/dask/metrics/confusion_matrix.py`:
- Around line 63-66: Update the docstring for the normalize parameter in the
confusion_matrix function to state that normalize may be one of the strings
'true', 'pred', or 'all' or None (default), and describe that None means no
normalization will be applied; ensure the normalize description in the parameter
block matches the runtime behavior checked in the function where normalize is
compared to None.

In `@python/cuml/cuml/metrics/confusion_matrix.py`:
- Around line 47-50: Update the confusion_matrix docstring to state that
convert_dtype not only coerces predictions, ground truth, and labels to np.int32
but also coerces sample_weight to np.int32 (see the conversion logic at the
lines applying convert_dtype around sample_weight). Modify the parameter
description for convert_dtype in the confusion_matrix function/class docstring
to explicitly mention sample_weight conversion and any related behavior or
caveats so the docs match the implementation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: cd97eb4d-aacc-4869-9896-d4fafcb9facb

📥 Commits

Reviewing files that changed from the base of the PR and between 5bc8f06 and 857ee08.

📒 Files selected for processing (2)
  • python/cuml/cuml/dask/metrics/confusion_matrix.py
  • python/cuml/cuml/metrics/confusion_matrix.py

@jcrist

jcrist commented May 6, 2026

Copy link
Copy Markdown
Member

/merge

@rapids-bot
rapids-bot Bot merged commit 7ba22e6 into NVIDIA:main May 6, 2026
93 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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.

5 participants