Skip to content

FIX KMeansSMOTE: uniform weights for degenerate clusters (#1186)#1187

Open
chaoz23 wants to merge 1 commit into
scikit-learn-contrib:masterfrom
chaoz23:fix/kmeans-smote-degenerate-clusters
Open

FIX KMeansSMOTE: uniform weights for degenerate clusters (#1186)#1187
chaoz23 wants to merge 1 commit into
scikit-learn-contrib:masterfrom
chaoz23:fix/kmeans-smote-degenerate-clusters

Conversation

@chaoz23

@chaoz23 chaoz23 commented Jul 18, 2026

Copy link
Copy Markdown

Toward #1186 — fixes the crash (issue 1). The exact-count allocation (issue 2) is intentionally left as a follow-up, so this does not auto-close the issue.

What

When every sample within each valid cluster is identical, all cluster sparsities are 0, so cluster_sparsities / cluster_sparsities.sum() divides by zero and yields NaN weights. The subsequent math.ceil(...) then raises ValueError: cannot convert float NaN to integer.

This can happen with duplicated rows or discrete/one-hot features where a whole cluster collapses to a single point.

Change

  • Weight such degenerate clusters uniformly when the total sparsity is 0, instead of dividing by zero.
  • Move the existing empty-valid_clusters RuntimeError guard ahead of the weight computation (previously it ran an unnecessary division on an empty array first).
  • Add a non-regression test reproducing the reported case.

Reproducer (from the issue)

import numpy as np
from imblearn.over_sampling import KMeansSMOTE
from sklearn.cluster import KMeans

X = np.array([[1., 1.]]*4 + [[2., 2.]]*4 + [[3., 3.]]*4)
y = np.array([1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0])
KMeansSMOTE(
    kmeans_estimator=KMeans(n_clusters=2, random_state=42),
    random_state=42, cluster_balance_threshold=0.1,
).fit_resample(X, y)   # was: ValueError; now: resamples cleanly

Scope

Limited to issue 1 (the crash). Issue 2 (making the total number of generated samples exactly match the requested count) is a separate behavioral change — happy to follow up on it in its own PR.

@chaoz23
chaoz23 force-pushed the fix/kmeans-smote-degenerate-clusters branch from e295a4e to a5f6f4d Compare July 18, 2026 04:30
When every sample within each valid cluster is identical, all cluster
sparsities are 0, so dividing by their (zero) sum produced NaN weights
and crashed with 'ValueError: cannot convert float NaN to integer' in
math.ceil. Fall back to uniform weighting across the valid clusters.

Toward scikit-learn-contrib#1186: fixes the crash (issue 1). The exact-count allocation
(issue 2) is left as a follow-up, so this does not auto-close the issue.
@chaoz23
chaoz23 force-pushed the fix/kmeans-smote-degenerate-clusters branch from a5f6f4d to 829f723 Compare July 18, 2026 05:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant