如何结合SequentialFeatureSelector实现嵌套交叉验证?
嵌套交叉验证中整合SequentialFeatureSelector的问题
我编写了一段嵌套交叉验证循环的代码,但不清楚如何将自带CV语句的SequentialFeatureSelector整合其中。我考虑过参考类似space = dict()的实现方式,或是搭配nested_cv库来实现?代码如下:
# 配置交叉验证流程 outer_k = 10 inner_k = 10 random_st = sample(list(np.arange(0,10,1)),1)[0] #print(random_st) cv_inner = KFold(n_splits=inner_k, shuffle=True, random_state=random_st) cv_outer = KFold(n_splits=outer_k, shuffle=True, random_state=random_st+1) outer_results = [] for outer_train_ix, outer_test_ix in cv_outer.split(X.index): inner_results = [] for inner_train_ix, inner_test_ix in cv_outer.split(outer_train_ix): print("inner_train_ix", inner_train_ix) print("inner_test_ix",inner_test_ix) #inner_results.append(inner_errors) # 从上述循环中选择最佳模型参数 # 用outer_train_ix拟合最佳模型,并用outer_test_ix计算样本外误差 print("outer_train_ix",outer_train_ix) print("outer_test_ix",outer_test_ix) #outer_results.append(outer_errors) # 选择在外部(样本外)预测中表现最佳的模型
方案一:手动整合SequentialFeatureSelector到嵌套循环
SequentialFeatureSelector(SFS)本身支持传入cv参数处理内部交叉验证,无需手动编写内循环的特征选择逻辑,只需在外循环的训练集上初始化SFS,让它自动完成内部特征选择与模型评估。
修改后的代码示例:
from sklearn.feature_selection import SequentialFeatureSelector from sklearn.model_selection import KFold import numpy as np from random import sample from sklearn.linear_model import LinearRegression # 示例基础模型,可替换为你的模型 base_model = LinearRegression() # 配置交叉验证流程 outer_k = 10 inner_k = 10 random_st = sample(list(np.arange(0,10,1)),1)[0] cv_inner = KFold(n_splits=inner_k, shuffle=True, random_state=random_st) cv_outer = KFold(n_splits=outer_k, shuffle=True, random_state=random_st+1) outer_results = [] best_models = [] for outer_train_ix, outer_test_ix in cv_outer.split(X.index): # 划分外部训练/测试集 X_outer_train, X_outer_test = X.iloc[outer_train_ix], X.iloc[outer_test_ix] y_outer_train, y_outer_test = y.iloc[outer_train_ix], y.iloc[outer_test_ix] # 初始化SFS,传入内部CV配置 sfs = SequentialFeatureSelector( base_model, n_features_to_select='best', # 自动选择最优特征数量 cv=cv_inner, scoring='neg_mean_squared_error', # 根据任务替换评分指标(如分类用'accuracy') direction='forward' # 可选'forward'前向或'backward'后向选择 ) # 在外部训练集上拟合SFS,自动完成内部交叉验证选特征 sfs.fit(X_outer_train, y_outer_train) # 获取选中的特征列 selected_features = X_outer_train.columns[sfs.get_support()] print(f"当前外部折选中特征: {selected_features}") # 用选中特征拟合最终模型 best_model = base_model.fit(X_outer_train[selected_features], y_outer_train) # 计算外部测试集误差 y_pred = best_model.predict(X_outer_test[selected_features]) outer_error = np.mean((y_pred - y_outer_test)**2) outer_results.append(outer_error) best_models.append(best_model) print(f"当前外部测试集MSE: {outer_error}") # 选择外部交叉验证中误差最小的模型 best_overall_model = best_models[np.argmin(outer_results)] print(f"所有外部折平均MSE: {np.mean(outer_results)}")
方案二:使用nested_cv库简化流程
如果想用nested_cv库,可以借助NestedCV类直接整合特征选择与嵌套交叉验证,无需手动编写循环:
from nested_cv import NestedCV from sklearn.linear_model import LinearRegression from sklearn.feature_selection import SequentialFeatureSelector # 定义SFS特征选择器 sfs = SequentialFeatureSelector( LinearRegression(), n_features_to_select='best', cv=10, scoring='neg_mean_squared_error' ) # 配置NestedCV ncv = NestedCV( model=LinearRegression(), params_grid={}, # 若模型有超参数,可在此定义网格搜索范围 outer_kfolds=10, inner_kfolds=10, feature_selector=sfs, random_state=random_st, scoring='neg_mean_squared_error' ) # 运行嵌套交叉验证 ncv.fit(X, y) # 获取结果 print(f"外部交叉验证平均得分: {ncv.best_score_}") print(f"最终选中特征: {X.columns[ncv.best_estimator_.named_steps['featureselector'].get_support()]}")
关键注意事项
- 避免重复内循环:SFS的
cv参数已处理内部交叉验证,手动编写内循环会导致逻辑冗余甚至数据泄露。 - 严格隔离数据:外部测试集绝对不能参与任何特征选择或模型训练步骤,所有特征选择操作必须在外部训练集内部完成。
- 匹配任务的评分指标:回归任务用
neg_mean_squared_error、r2等,分类任务用accuracy、f1等。
内容的提问来源于stack exchange,提问作者thistleknot
相关产品推荐
相关产品推荐

