我有一个不平衡的数据集,我正在尝试不同的方法来解决数据不平衡问题。我发现这篇文章解释了使用 SMOTE 技术对数据进行过采样时交叉验证的正确方法。
我使用 AdaBoost 算法创建了一个模型,并设置了以下要在网格搜索中使用的参数:
ada = AdaBoostClassifier(n_estimators=100, random_state=42)
params = {
'n_estimators': [50, 100, 200],
'random_state': [42]
}
根据文章,这是过采样的错误方法:
X_train_upsample, y_train_upsample = SMOTE(random_state=42).fit_sample(X_train, y_train)
# cross-validate using grid search
grid_naive_up = GridSearchCV(ada, param_grid=params, cv=kf,
scoring='recall').fit(X_train_upsample,
y_train_upsample)
grid_naive_up.best_score_
0.6715940782827282
# test set
recall_score(y_test, grid_naive_up.predict(X_test))
0.2824858757062147
而过采样的正确方法是这样的:
from imblearn.pipeline import Pipeline, make_pipeline
imba_pipeline = make_pipeline(SMOTE(random_state=42),
AdaBoostClassifier(n_estimators=100, random_state=42))
cross_val_score(imba_pipeline, X_train, y_train, scoring='recall', cv=kf)
new_params = {'adaboostclassifier__' + 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);
# How well do we do on our validation set?
grid_imba.best_score_
0.29015614186873506
# compare this to the test set:
y_test_predict = grid_imba.predict(X_test)
0.2824858757062147
因此,根据文章,第一种方法是错误的,因为在交叉验证之前进行上采样时,验证召回不是测试召回的良好衡量标准(28.2%)。然而,当使用 imblearn 管道进行上采样作为交叉验证的一部分时,验证集召回率 (29%) 是对测试集召回率 (28.3%) 的良好估计。根据文章,这样做的原因是:
在交叉验证之前进行上采样时,您将选择最过采样的模型,因为过采样允许数据从验证折叠泄漏到训练折叠中。
谁能简单地向我解释过采样如何使数据泄漏到验证中并导致过拟合?为什么在 imblearn 管道中不会出现这个问题?