Skip to content

Preserve numeric labels when adapting single-class classifiers - #680

Open
Linxiushen wants to merge 4 commits into
interpretml:mainfrom
Linxiushen:fix/preserve-single-class-labels
Open

Linxiushen wants to merge 4 commits into
interpretml:mainfrom
Linxiushen:fix/preserve-single-class-labels

Conversation

@Linxiushen

@Linxiushen Linxiushen commented Sep 27, 2026 •

Copy link
Copy Markdown

The single-class adapter adds a synthetic string class using NumPy's inferred dtype. For integer or boolean classes, this also converts the original label to a string. PR(model).explain_perf(X, y) and ROC(model).explain_perf(X, y) then raise KeyError while looking up the original labels; explanation records can instead mark the observed class as unknown with probability zero.

Preserve the original label in an object array alongside the synthetic class. The regression tests fit real sklearn classifiers and cover public PR/ROC calls, explanation label/probability mapping, single-sample inputs, strings, and the ordinary binary path.

Validation on Windows / Python 3.12:

  • New regressions: 12 failed / 9 passed before the fix.
  • New tests plus related cleaning/explanation tests: 26 passed / 1 skipped after the fix.
  • All applicable configured pre-commit hooks pass.
  • Advisory mypy is blocked by NumPy 2.5 stubs using Python 3.12 syntax with the repository's Python 3.10 target; identical failure reproduced on unchanged main.

Single-class ROC metrics remain undefined as reported by sklearn. Full EBM/native and browser suites were not run.

Hosted CI follow-up: all 21 new regression cases pass in both failed Python jobs. Their APLR MRO errors also occur in a scheduled run on the same unchanged base; Powerlift's SQLAlchemy 2.1.1 / sqlalchemy-utils 0.42.1 import failure likewise reproduces there. Docs additionally fails when the fork token tries to create its warning check (403). The workflow has 30 successful, 4 failed and 31 cancelled jobs, so the full matrix remains incomplete. DCO is a separate owner-attestation gate. Same-base comparison run.

@codecov

codecov Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 67.88%. Comparing base (4a492be) to head (40d196d).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #680      +/-   ##
==========================================
+ Coverage   67.80%   67.88%   +0.08%     
==========================================
  Files          77       77              
  Lines       11893    11893              
==========================================
+ Hits         8064     8074      +10     
+ Misses       3829     3819      -10     
Flag Coverage Δ
bdist_linux_311_python ?
bdist_linux_312_python ?
bdist_linux_313_python ?
bdist_linux_314_python ?
bdist_linuxarm_311_python 67.68% <100.00%> (+0.12%) ⬆️
bdist_linuxarm_312_python ?
bdist_linuxarm_313_python ?
bdist_linuxarm_314_python 65.93% <100.00%> (-1.54%) ⬇️
bdist_mac_311_python ?
bdist_mac_312_python ?
bdist_mac_313_python ?
bdist_mac_314_python 66.72% <100.00%> (-0.87%) ⬇️
bdist_win_311_python 64.20% <100.00%> (-3.52%) ⬇️
bdist_win_312_python ?
bdist_win_313_python ?
bdist_win_314_python 64.08% <100.00%> (-3.54%) ⬇️
sdist_linux_311_python ?
sdist_linux_312_python ?
sdist_linux_313_python ?
sdist_linux_314_python ?
sdist_linuxarm_311_python ?
sdist_linuxarm_312_python ?
sdist_linuxarm_313_python ?
sdist_linuxarm_314_python ?
sdist_mac_311_python ?
sdist_mac_312_python ?
sdist_mac_313_python ?
sdist_mac_314_python ?
sdist_win_311_python ?
sdist_win_312_python ?
sdist_win_313_python ?
sdist_win_314_python ?

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Signed-off-by: 林SO <142557582+Linxiushen@users.noreply.github.com>
@Linxiushen
Linxiushen force-pushed the fix/preserve-single-class-labels branch from a36fe00 to 50e96b4 Compare September 28, 2026 09:45

Copilot AI 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.

🟢 Approval recommended

The narrowly scoped dtype fix addresses label coercion without changing prediction logic, and the regression tests cover the affected behavior.

No open issues 🎉

What changed in this PR

This PR fixes single-class classifier adaptation so numeric and boolean labels remain intact when a synthetic string class is added, preserving label lookup in performance explainers.

Changes:

  • Uses an object array to retain the original class label without string coercion.
  • Adds 21 regression cases covering PR/ROC calls, explanation mappings, single-sample inputs, string labels, and unchanged binary behavior.
File Description
python/​interpret-core/​tests/​utils/​test_unify_predict.py Adds regression coverage for label preservation and prediction behavior.
python/​interpret-core/​interpret/​utils/​_unify_predict.py Preserves the original label by explicitly setting dtype=object.

Review effort: Balanced

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants