问题背景
在使用Python的imbalanced-learn库(简称imblearn)进行数据不平衡处理时,sample_check_neighbors方法可能会抛出ValueError: Found array with 0 sample(s)错误。该问题通常发生在以下场景:
- 输入数据包含全为同一类别的样本
- 采样策略(如SMOTE、ADASYN)尝试从空邻域中生成样本
- 数据预处理阶段误删了有效样本
错误原因分析
该错误的根本原因是样本分布不满足算法要求。例如:
- 当使用KNN-based过采样方法时,如果少数类样本数小于
k_neighbors参数,无法计算有效邻域 - 数据经过过滤后,某个类别的样本数归零
- 数据分区(如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)