【问题标题】:Up Sampling imbalanced dataset's minor classes对不平衡数据集的次要类进行上采样
【发布时间】:2021-02-20 03:21:19
【问题描述】:

我正在使用 scikit-learn 对我的数据进行分类,目前我正在运行一个简单的决策树分类器。 我有三个班级存在很大的不平衡问题。类是 0,1 和 2。次要类是 1 和 2。

让您了解类的样本数量:

0 = 25.000 samples
1 = 15/20 less or more
2 = 15/20 less or more

所以小类大约占数据集的 0.06%。 我遵循的解决不平衡问题的方法是次要类的 UPSAMPLING。代码:

from sklearn.utils import resample,
resample(data, replace=True, n_samples=len_major_class, random_state=1234)

现在问题来了。我做了两个测试:

  1. 如果我对次要类进行上采样,然后将我的数据集分为两组,一组用于训练,一组用于测试...准确度为:
             precision    recall  f1-score   support

          0       1.00      1.00      1.00     20570
          1       1.00      1.00      1.00     20533
          2       1.00      1.00      1.00     20439

avg / total       1.00      1.00      1.00     61542

非常好的结果。

  1. 如果我只对 training 数据进行上采样并保留原始数据进行测试,则结果是:
             precision    recall  f1-score   support

          0       1.00      1.00      1.00     20570
          1       0.00      0.00      0.00        15
          2       0.00      0.00      0.00        16

avg / total       1.00      1.00      1.00     20601

如您所见,全局准确率很高,但第 1 类和第 2 类的准确率是零。

我是这样创建分类器的:

DecisionTreeClassifier(max_depth=20, max_features=0.4, random_state=1234, criterion='entropy')

我也尝试将class_weight 与 balanced 值相加,但没有任何区别。

我应该只对训练数据进行上采样,为什么会出现这个奇怪的问题?

【问题讨论】:

    标签: python machine-learning scikit-learn


    【解决方案1】:

    在拆分之前进行重新采样时,您获得这种行为是很正常的;你在你的数据中引入了偏见。

    如果您对数据进行过采样然后拆分,则测试中的少数样本将不再独立于训练集中的样本,因为它们是一起生成的。在您的情况下,它们是训练集中样本的精确副本。您的准确率是 100%,因为分类器正在对训练中已经看到的样本进行分类。

    由于您的问题非常不平衡,我建议使用分类器集合来处理它。 1)将数据集拆分为训练集和测试集。给定数据集的大小,您可以从少数类中抽取 1-2 个样本进行测试,而将其他样本留作训练。 2)从训练中,您生成 N 个数据集,其中包含少数类的所有剩余样本和多数类的欠样本(我会说 2*少数类中的样本数)。 3)对于获得的每个数据集,您都训练了一个模型。 4)使用测试集得到预测;最终的预测将是分类器所有预测的多数票的结果。

    要让稳健的指标通过不同的初始拆分测试/训练执行不同的迭代。

    【讨论】:

      【解决方案2】:

      上采样后不应拆分数据集。您可以在训练数据中进行上采样。

      基本上,您将测试数据泄漏到训练数据中。

      【讨论】:

        【解决方案3】:

        我有一个函数可以对每个类的数据集重新采样以具有相同数量的实例。

        from sklearn.utils import resample
        import pandas as pd
        
        def make_resample(_df, column):
        
          dfs_r = {}
          dfs_c = {}
          bigger = 0
          ignore = ""
          for c in _df[column].unique():
            dfs_c[c] = _df[df[column] == c]
            if dfs_c[c].shape[0] > bigger:
              bigger = dfs_c[c].shape[0]
              ignore = c
        
          for c in dfs_c:
            if c == ignore:
              continue
            dfs_r[c] = resample(dfs_c[c], 
                                replace=True,
                                n_samples=bigger - dfs_c[c].shape[0],
                                random_state=0)
          return pd.concat([dfs_r[c] for c in dfs_r] + [_df])
        

        【讨论】:

          猜你喜欢
          • 2018-09-18
          • 2020-08-30
          • 2020-09-06
          • 2022-11-15
          • 2018-05-17
          • 2018-12-06
          • 1970-01-01
          • 2023-03-03
          • 2014-01-09
          相关资源
          最近更新 更多