【问题标题】:Feature selection: after or during nested cross-validation?特征选择:嵌套交叉验证之后还是期间?
【发布时间】:2023-03-26 00:22:01
【问题描述】:

我已经设法编写了一些代码,使用 lightGBM 作为我的回归器进行嵌套交叉验证,并使用 sklearn.pipeline 包装所有内容。

最终,我现在想要进行特征选择(或者实际上只是了解特征对最终模型的重要性),但我想知道从这里采取的最佳路径是什么。我想有两种可能:

1# 使用此方法来使用最佳超参数构建模型(使用 .fit 和 .predict)。然后检查该模型的特征的重要性。

2# 在嵌套 cv 的内部折叠中进行特征选择,但我不确定如何准确执行此操作。

我猜#1 会是最简单的,但我不确定如何为每个外层获得最佳超参数。

这个线程涉及到它: Putting together sklearn pipeline+nested cross-validation for KNN regression

但是选择的答案完全放弃了 cross_val_score,这意味着它不再是嵌套的交叉验证(我仍然想在内折叠上获得最佳超参数后在外折叠上执行 CV)。

所以我的问题如下:

  1. 我能否获取外部 CV 每一折的特征重要性(我是 意识到如果我有 5 折,我将获得 5 组不同的功能 重要性)?如果是,怎么做?
  2. 或者,我是否应该为每个获得最佳超参数 折叠(如何?)并在整个数据集上构建一个没有 CV 的新模型, 基于这些超参数?

这是我目前的代码:

import numpy as np
import pandas as pd
import lightgbm as lgb
from sklearn.model_selection import cross_val_score, RandomizedSearchCV, KFold
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
import scipy.stats as st

#Parameters for model building an reproducibility
X = X_age
y = y_age
RNGesus = 42 
state = 13
outer_scoring = 'neg_mean_absolute_error'
inner_scoring = 'neg_mean_absolute_error'

#### Nested CV with Random gridsearch ####

# Pipeline with standard scaling and the regressor    
regressors = [lgb.LGBMRegressor(random_state = state)]
continuous_transformer = Pipeline([('scaler', StandardScaler())])
preprocessor = ColumnTransformer([('cont',continuous_transformer, continuous_variables)], remainder = 'passthrough')

for reg in regressors:
    steps=[('preprocessor', preprocessor), ('regressor', reg)]
    pipeline = Pipeline(steps)

#inner and outer fold to be used
inner_cv = KFold(n_splits=5, shuffle=True, random_state=RNGesus)
outer_cv = KFold(n_splits=5, shuffle=True, random_state=RNGesus)

#Hyperparameters of the regressor to be optimized using randomized search
params = {
'regressor__max_depth': (3, 5, 7, 10),
'regressor__lambda_l1': st.uniform(0, 5),
 'regressor__lambda_l2': st.uniform(0, 3)
}

#Pass the RandomizedSearchCV to cross_val_score

regression = RandomizedSearchCV(estimator = pipeline, param_distributions = params, scoring=inner_scoring, cv=inner_cv, n_iter=200, verbose= 3, n_jobs= -1)
nested_score = cross_val_score(regression, X= X, y= y, cv = outer_cv, scoring=outer_scoring)

print('\n MAE for lightGBM model predicting age: %.3f' % (abs(nested_score.mean())))

print('\n'str(nested_score) + '<- outer CV')

编辑:清楚地说明问题。

【问题讨论】:

  • 有什么问题?
  • 特征选择过程是您管道中的一个阶段吗?
  • @serafeim:我添加了一个更清晰(我希望)的问题表述。 @ShaharA:目前没有。我现在只有一个StandardScaler()LGBMRegressor

标签: python scikit-learn cross-validation feature-selection hyperparameters


【解决方案1】:

我在导入lightGBM 模块时遇到了问题,所以我无法运行您的代码。但这里a post 解释了您如何无法从cross_val_score 的嵌套交叉验证中获得“获胜”或最佳超参数(以及feature_importance_)。简单来说,原因是cross_val_score只返回测量值。

  1. 我能否获得外部 CV 每一折的特征重要性(我知道如果我有 5 折,我将获得 5 组不同的特征重要性)?如果是,怎么做?

cross_val_score 的答案是否定的。但是,如果您按照该帖子中的代码进行操作,您将能够通过 GSCV.best_estimator_.feature_importance_GSCV.fit() 之后的 for 循环下获得 feature_importance_

  1. 或者,我是否应该只为每个折叠获取最佳超参数(如何?)并基于这些超参数在整个数据集上构建一个没有 CV 的新模型?

这正是那篇文章所说的:通过嵌套 cv 为您提供“最佳”超参数。理想情况下,您将观察到一种始终获胜的超参数组合,这就是您将用于最终模型(具有整个训练集)的超参数。但是当 cv 过程中出现不同的“最佳”超参数组合时,据我所知并没有标准的处理方法。

【讨论】:

    猜你喜欢
    • 2013-11-08
    • 2015-11-13
    • 2020-07-10
    • 2021-08-27
    • 1970-01-01
    • 2013-12-19
    • 1970-01-01
    • 2020-03-03
    • 2021-12-21
    相关资源
    最近更新 更多