【问题标题】:Using SMOTE with NaN values使用具有 NaN 值的 SMOTE
【发布时间】:2019-08-12 06:22:27
【问题描述】:

有没有一种方法可以将 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').

【问题讨论】:

    标签: missing-data smote imbalanced-data


    【解决方案1】:

    您已经包含了答案。请注意,使用 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()))
    

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

    【讨论】:

    • 是的,但是通过使用 SimpleImputer(),您基本上可以取消 NaN,然后​​应用重采样。我想知道是否有办法在使用 NaN 时重新采样
    • 没有。 SMOTE 使用线性插值来生成新样本。在缺失值和非缺失值之间进行插值是没有意义的。
    【解决方案2】:

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

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

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

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

    更新 1:

    另一种方法是先估算缺失值,这样您实际上可以通过三个步骤来拟合模型:

    1. 插补缺失值(使用 MICE 或类似方法)
    2. SMOTE 平衡训练集
    3. 拟合算法/模型

    【讨论】:

      猜你喜欢
      • 2021-03-05
      • 2019-02-24
      • 2011-08-23
      • 2022-01-11
      • 2017-03-21
      • 2022-09-28
      • 2020-08-29
      • 2017-04-17
      • 2022-11-25
      相关资源
      最近更新 更多