1

有没有一种方法可以将 SMOTE 与 NaN 一起使用?

这是一个在存在 NaN 值的情况下尝试使用 SMOTE 的虚拟程序

# Imports
from collections import Counter
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.preprocessing import Imputer
from imblearn.over_sampling import SMOTE
from imblearn.pipeline import make_pipeline
from imblearn.combine import SMOTEENN

# Load data
bc = load_breast_cancer()
X, y = bc.data, bc.target

# Initial number of samples per class
print('Number of samples for both classes: {} and {}.'.format(*Counter(y).values()))

# SMOTEd class distribution
print('Dataset has %s missing values.' % np.isnan(X).sum())
_, y_resampled = SMOTE().fit_sample(X, y)
print('Number of samples for both classes: {} and {}.'.format(*Counter(y_resampled).values()))

# Generate artificial missing values
X[X > 1.0] = np.nan
print('Dataset has %s missing values.' % np.isnan(X).sum())
#_, y_resampled = make_pipeline(Imputer(), SMOTE()).fit_sample(X, y)


sm = SMOTE(ratio = 'auto',k_neighbors = 5, n_jobs = -1)
smote_enn = SMOTEENN(smote = sm)

x_train_res, y_train_res = smote_enn.fit_sample(X, y)

print('Number of samples for both classes: {} and {}.'.format(*Counter(y_resampled).values()))

我得到以下输出/错误:

Number of samples for both classes: 212 and 357.
Dataset has 0 missing values.
Number of samples for both classes: 357 and 357.
Dataset has 6051 missing values.

ValueError: Input contains NaN, infinity or a value too large for dtype('float64').
4

2 回答 2

3

你已经包含了答案。请注意,fit_resample使用 代替fit_sample。你应该使用make_pipeline如下:

# Imports
import numpy as np
from collections import Counter
from sklearn.datasets import load_breast_cancer
from sklearn.impute import SimpleImputer
from imblearn.over_sampling import SMOTE
from imblearn.pipeline import make_pipeline
from imblearn.combine import SMOTEENN

# Load data
bc = load_breast_cancer()
X, y = bc.data, bc.target
X[X > 1.0] = np.nan

# Over-sampling 
smote = SMOTE(ratio='auto',k_neighbors=5, n_jobs=-1)
smote_enn = make_pipeline(SimpleImputer(), SMOTEENN(smote=smote))
_, y_res = smote_enn.fit_resample(X, y)

# Class distribution
print('Number of samples for both classes: {} and {}.'.format(*Counter(y_res).values()))

还要检查你的不平衡学习版本。

于 2019-08-12T10:35:08.757 回答
0

通常不会,SMOTE 正在为进一步的模型拟合准备数据集。

通常的模型(如随机森林等)不适NA用于标签变量,因为您在这里实际预测的是什么?预测变量也是如此NA,大多数算法要么不起作用,要么只是忽略NA.

因此,该错误几乎是设计使然,因为您不能也不应该在算法的训练数据集中存在缺失值,并且从逻辑上讲,您不想“平衡”具有缺失值的案例,您只想使用有效标签对案例进行 SMOTE。

如果您觉得缺失的标签仍然代表应该平衡的有效信息(例如,您实际上想要对NA类进行过度采样,因为您认为它的代表性不足),那么它不应该是缺失值,而是一个称为“未知”或其他东西的定义值否则,表示具有“NA”特征的已知类,但我真的没有看到任何有意义的研究问题。

更新1:

另一种方法是首先估算缺失值,以便您实际上有三个步骤来拟合模型:

  1. 估算缺失值(使用 MICE 或类似方法)
  2. SMOTE 平衡训练集
  3. 拟合算法/模型
于 2019-08-12T08:33:07.417 回答