交叉验证之前的过采样,有问题吗?

数据挖掘 机器学习 交叉验证 阶级失衡 采样
2021-09-22 13:08:34

我有一个高度不平衡的多类分类问题要解决。显然我正在做过采样,但我正在对过采样数据集进行交叉验证,因此我应该在火车和验证集中重复数据。我正在使用 lightgbm 算法,但令人惊讶的是,交叉验证分数和未见数据集的分数之间没有太大差异。

但是我只想知道在对数据集进行过采样后进行交叉验证是否可以,如果不是,为什么我在验证集和看不见的测试集上得到如此接近的分数?

此外,如果在交叉验证之前进行过采样不正确,那么将数据拆分为验证和训练然后再次对训练集进行采样以及在最终预测期间再次采样(如果您希望使用所有数据)会变得很长然后你必须附加验证和训练数据,然后再次过采样。有什么捷径可以解决问题吗?

2个回答

对训练数据进行过采样可能有助于分类器更好地预测最初较少代表的类。这并不意味着它应该应用于性能指标,因为它会改变原始目标分布,从而在结果中产生偏差。

想象一下癌症检测的问题,您的原始数据集是不平衡的:10% 的患者患有癌症y=1,其余 90% 没有y=0如果你训练一个在不平衡数据集(例如人工神经网络)上容易出错的分类器,你最终可能总是预测多数类:y=0.

如果你对一个新的分布进行过采样,比如 50/50,你的分类器有望提高性能,特别是在正类上。尽管如此,要衡量本身就存在偏差的真实数据的性能,衡量过采样可能不是最佳选择。

因此,如果您正在优化超参数或从一组分类器中进行选择,则使用过采样数据进行交叉验证可能会为您提供关于分类器预测具有同等重要性的两个类的能力的不同观点。尽管如此,如果您正在估计现实生活中的预测能力,我不建议您对此类验证数据进行过度采样!

我建议阅读这篇文章文章解释说:

在交叉验证之前进行上采样时,您将选择最过采样的模型,因为过采样允许数据从验证折叠泄漏到训练折叠中。

相反,我们应该首先分成训练和验证折叠。然后,在每一折上,我们应该:

  1. 过采样少数类
  2. 在训练折叠上训练分类器
  3. 在剩余折叠上验证分类器

因此,为避免过度拟合,请尝试使用 imblearn make_pipeline 类,以便您可以将上采样作为交叉验证的一部分,如下所示:

kf = KFold(n_splits=5, random_state=42, shuffle=False)

# define parametres for hypertuning
params = {
    'n_estimators': [50, 100, 200],
    'max_depth': [4, 6, 10, 12],
    'random_state': [13]
}

from imblearn.pipeline import Pipeline, make_pipeline
imba_pipeline = make_pipeline(SMOTE(random_state=42), 
                              RandomForestClassifier(n_estimators=100, random_state=13))
cross_val_score(imba_pipeline, X_train, y_train, scoring='recall', cv=kf)
new_params = {'randomforestclassifier__' + key: params[key] for key in params}
grid_imba = GridSearchCV(imba_pipeline, param_grid=new_params, cv=kf, scoring='recall',
                        return_train_score=True)
grid_imba.fit(X_train, y_train);

# check recall on validation set
grid_imba.best_score_

# check recall on test set
y_test_predict = grid_imba.predict(X_test)

这将导致验证集召回是对测试集召回的良好估计。