CV-ing数据集时如何实现基于比率的SMOTE过采样

时间:2018-07-23 14:06:56

标签: python scikit-learn cross-validation

我正在处理二进制分类问题中非常不平衡的数据集(约5%)。我正在使用SMOTE和随机森林分类器来使我的过采样发生在GridSearch CV循环内(如建议here)。您可以在下面看到我的实现:

from imblearn.over_sampling import SMOTE
from sklearn.ensemble import RandomForestClassifier
from imblearn.pipeline import Pipeline
from sklearn.model_selection import RandomizedSearchCV, StratifiedKFold

sm = SMOTE()
rf = RandomForestClassifier()

pipeline = Pipeline([('sm', sm), ('rf', rf)])

kf = StratifiedKFold(n_splits = 5)

params = {'rf__max_depth' : list(range(2,5)),
    'rf__max_features' : ['auto','sqrt'],
    'rf__bootstrap' : [True, False]
}

grid = RandomizedSearchCV(pipeline, param_distributions = params, scoring = 'f1', cv = kf)

grid.fit(X, y)

但是,this paper(请参阅第7页的表4)建议测试不同的重采样率,以找出哪个可以提供更好的性能。现在,使用我的 sm = SMOTE(),我正在生成50-50%的数据集,但我想遍历一系列潜在比率(例如5-95、10-90,等等。)。但是,SMOTE中的 ratio 参数不能接受所需的百分比率,而是一个带有样本数量的特定整数,由于kfold,我认为我无法做到这一点CV(每折可能具有稍微不同的样本量)。如何实现?

1 个答案:

答案 0 :(得分:1)

尽管在文档中未提及,但我认为您可以将float设置为ratio。但是您应该知道它已被弃用,并将在将来的版本中删除(因为我认为这仅适用于二进制情况,不适用于多类)。

params = {'sm__ratio' : [0.05, 0.10, 0.15],
          'rf__max_depth' : list(range(2,5)),
          'rf__max_features' : ['auto','sqrt'],
          'rf__bootstrap' : [True, False]
         }

grid = RandomizedSearchCV(pipeline, param_distributions = params, scoring = 'f1', cv = kf)

还请注意,您在此处提到的比率将是在对少数族裔进行上采样之后的各类比率。

因此,假设您具有以下原始类:

  1:  75
  0:  25  

然后将比率指定为0.5。在这里,多数类别不会被触及,但是将生成12个类别0的另外12个合成样本,因此最终数字为:

  1:  75
  0:  37  (25 + 12) 

最终比率是37/75 = 0.5(如您所述)。