SMOTE过采样、GridSearchCV与10折交叉验证组合使用的正确方法
二分类任务SMOTE+网格搜索+交叉验证流程实现解答
1 全量数据集跑GridSearch的正确性说明
你当前的代码已经避免了SMOTE过采样的数据泄露问题:把SMOTE放在Pipeline里执行,GridSearch每折交叉验证时,只会对当前折叠的训练子集做过采样,不会用到测试子集的信息,这部分逻辑是正确的。
是否需要提前划分70/30留出集,分两种场景判断:
- 如果你的目标仅为调参得到最优超参数,最终要在全量数据集上训练最终模型部署,不需要额外划分留出集,直接用全量数据跑GridSearch即可。
- 如果你的目标是得到无偏的模型泛化性能评估,必须提前做分层留出集划分,GridSearch仅在训练子集上执行,最终用完全未参与调参的测试子集评估性能。如果直接用GridSearch内部交叉验证的结果作为最终性能,会因为调参过程已经用到了所有折叠的测试信息,导致性能评估偏高,出现数据泄露。
2 获取accuracy、f1等评估指标的实现方法
可以直接通过GridSearch的scoring参数配置多指标评估,实现方式如下:
配置多指标网格搜索
给GridSearch传入scoring参数指定需要统计的指标列表,多指标场景下需要通过refit参数指定以哪个指标为标准选择最优超参数。
指标获取方式
- 10折交叉验证的指标可以从
grid_search.cv_results_属性中获取,对应字段为mean_test_accuracy、mean_test_f1等,找到最优参数对应的索引即可拿到对应平均指标。 - 留出测试集的指标可以通过
sklearn.metrics下的对应函数直接计算。
完整代码示例
from sklearn.model_selection import train_test_split, GridSearchCV, StratifiedKFold from sklearn.pipeline import Pipeline from sklearn.neighbors import KNeighborsClassifier from imblearn.over_sampling import SMOTE from sklearn.metrics import accuracy_score, f1_score # 如需无偏泛化性能评估,先划分分层留出集 X_train, X_test, y_train, y_test = train_test_split( X_all, y_all, test_size=0.3, stratify=y_all, random_state=42 ) # 构建包含SMOTE的Pipeline pipe = Pipeline([ ('resample', SMOTE(sampling_strategy=1)), ('model', KNeighborsClassifier()) ]) # 10折分层交叉验证 cv = StratifiedKFold(n_splits=10, shuffle=True, random_state=42) # 超参数搜索空间 params = [{ 'model__n_neighbors': [1,3,5,15,25,45], 'model__weights': ['uniform','distance'], 'model__leaf_size': [3,5,7,9,15,25] }] # 配置多指标网格搜索 grid_search = GridSearchCV( estimator=pipe, param_grid=params, cv=cv, refit='f1', # 以F1为标准选择最优参数 scoring=['accuracy', 'f1'], # 指定要统计的评估指标 n_jobs=-1 # 多进程加速搜索 ) # 仅用训练集执行网格搜索(无需无偏评估可替换为X_all、y_all) grid_search.fit(X_train, y_train) # 输出最优参数 print("最优超参数:", grid_search.best_params_) # 获取10折交叉验证的平均指标 best_idx = grid_search.best_index_ print("10折交叉验证平均准确率:", round(grid_search.cv_results_['mean_test_accuracy'][best_idx], 4)) print("10折交叉验证平均F1值:", round(grid_search.cv_results_['mean_test_f1'][best_idx], 4)) # (划分留出集的场景)在独立测试集上评估泛化性能 y_pred = grid_search.predict(X_test) print("独立测试集准确率:", round(accuracy_score(y_test, y_pred), 4)) print("独立测试集F1值:", round(f1_score(y_test, y_pred), 4))
内容的提问来源于stack exchange,提问作者Vasu Mistry
相关产品推荐
相关产品推荐

