numpy数组执行欠采样触发ValueError报错的修复咨询
报错修复方案
报错根因
两个报错的核心问题是对imblearn采样器的输入要求理解有误,同时代码存在逻辑错误:
- 第一个
y should be a 1d array报错:imblearn内置的SMOTE、RandomUnderSampler等采样方法原生仅支持单标签分类场景,要求传入的标签y是形状为(n_samples,)的一维数组,每个元素对应一个样本的类别。传入的y形状为(1000, 180),是二维结构,不符合输入规范。 - 第二个
inconsistent numbers of samples报错:调用y.ravel()会把(1000,180)的二维数组直接展平成长度为180000的一维数组,而特征X的样本数只有1000,两者样本数量完全不匹配,自然触发报错。 - 额外逻辑错误:注释说明要使用SMOTE做采样,但实际初始化的是随机欠采样器
RandomUnderSampler,和预期目标不符;且采样完成后拆分数据集时传入的还是原始未采样的X,y,等于采样操作完全没有生效。
修复方法
根据实际任务场景二选一即可:
场景1:做多标签分类任务(每个样本对应180个标签)
这种场景下不要手动展平标签,使用imblearn提供的多标签采样封装器MultiLabelSampler即可直接支持二维标签输入,参考代码:
from imblearn.over_sampling import SMOTE from imblearn.under_sampling import RandomUnderSampler from imblearn.multioutput import MultiLabelSampler from sklearn.model_selection import train_test_split # 初始化需要的基础采样器,这里用原本要使用的SMOTE过采样 base_sampler = SMOTE(random_state=1) # 如果确实要做随机欠采样,替换成下面这行即可 # base_sampler = RandomUnderSampler(sampling_strategy='majority', random_state=1) # 封装为支持多标签的采样器 sampler = MultiLabelSampler(sampler=base_sampler, random_state=1) # 执行采样,输出的X_resampled、y_resampled会自动保持样本和标签的对应关系 X_resampled, y_resampled = sampler.fit_resample(X, y) # 采样完成后再拆分数据集,注意传入采样后的数据 x_train, x_test, y_train, y_test = train_test_split(X_resampled, y_resampled, test_size=0.01, random_state=1)
场景2:实际做单标签分类任务,y的形状是误生成的
如果任务里每个样本只对应1个类别标签,(1000,180)的y形状是处理失误导致的,先把y修正为长度1000的一维数组,再执行采样即可,参考代码:
from imblearn.over_sampling import SMOTE from sklearn.model_selection import train_test_split # 先把y修正为形状(1000,)的一维数组,下面这行是示例,根据实际标签逻辑调整 # 比如如果y每一行都是重复的同一个标签,取第一列即可 y_correct = y[:, 0] # 执行SMOTE采样 smote = SMOTE(random_state=1) X_resampled, y_resampled = smote.fit_resample(X, y_correct) # 拆分数据集 x_train, x_test, y_train, y_test = train_test_split(X_resampled, y_resampled, test_size=0.01, random_state=1)
注意事项
- 不要对二维标签直接调用
ravel()展平,该操作会彻底打乱样本和标签的对应关系,无法用于采样。 - 采样操作需要在数据集拆分之前执行,或者仅对训练集做采样,禁止在拆分前对全量数据采样后再拆分(会引入数据泄露),更不要采样后还用原始数据做拆分。
内容的提问来源于stack exchange,提问作者tanmay
相关产品推荐
相关产品推荐

