如何解决imbalanced-learn库中sample_check_neighbors方法的"ValueError: Found array with 0 sample(s)"错

问题背景

在使用Python的imbalanced-learn库(简称imblearn)进行数据不平衡处理时,sample_check_neighbors方法可能会抛出ValueError: Found array with 0 sample(s)错误。该问题通常发生在以下场景:
  • 输入数据包含全为同一类别的样本
  • 采样策略(如SMOTE、ADASYN)尝试从空邻域中生成样本
  • 数据预处理阶段误删了有效样本

错误原因分析

该错误的根本原因是样本分布不满足算法要求。例如:

  1. 当使用KNN-based过采样方法时,如果少数类样本数小于k_neighbors参数,无法计算有效邻域
  2. 数据经过过滤后,某个类别的样本数归零
  3. 数据分区(如train_test_split)导致某些类别在子集中消失

解决方案

方法1:验证数据分布

from collections import Counter  
print(Counter(y))  # y为目标变量

确保每个类别至少有k_neighbors+1个样本(SMOTE默认k=5)。

方法2:调整采样参数

from imblearn.over_sampling import SMOTE  
sm = SMOTE(k_neighbors=min(5, minority_count-1))  # 动态设置k值

方法3:使用替代采样器

对于极端不平衡数据(如1:1000),改用RandomOverSampler或组合采样:

from imblearn.combine import SMOTETomek  
sampler = SMOTETomek(smote=SMOTE(sampling_strategy=0.1))

预防措施

措施实现方式
数据预检查assert len(np.unique(y)) > 1
参数校验k_neighbors ≤ min_class_count - 1
分层抽样train_test_split(stratify=y)

完整代码示例

from imblearn.over_sampling import SMOTE  
from sklearn.datasets import make_classification  

X, y = make_classification(n_classes=2, weights=[0.99, 0.01])  
try:  
    sm = SMOTE()  
    X_res, y_res = sm.fit_resample(X, y)  
except ValueError as e:  
    print(f"Error: {e}")  
    # 动态调整k_neighbors  
    min_class = min(Counter(y).values())  
    sm = SMOTE(k_neighbors=min(5, min_class-1))  
    X_res, y_res = sm.fit_resample(X, y)