【问题标题】:How to properly do feature selection with SelectFromModel from scikit-learn?如何使用 scikit-learn 中的 SelectFromModel 正确进行特征选择?
【发布时间】:2021-02-11 07:37:54
【问题描述】:

我使用very simple kaggle dataset 来了解带有逻辑回归的 SelectFromModel 的工作原理。这个想法是创建一个非常简单的管道,其中包含一些基本的数据处理(删除列 + 缩放),将其传递给特征选择(logreg),然后拟合 xgboost 模型(未包含在代码中)。通过阅读documentation,我的理解是,给定我的 X_train 和 y_train 拟合 logreg 模型,并选择系数高于或等于阈值的那些特征。就我而言,我将阈值设置为 mean*1.25。

我不明白为什么输出 selector.threshold_ 与我期望得到相同值的 selector.estimator_.coef_.mean()*1.25. 不同,为什么不是这样?

展望未来,我想做 GridSearchCV 来微调我的管道参数。我通常这样做:

from sklearn.model_selection import GridSearchCV

params = {}
params['gradientboostingclassifier__learning_rate'] = [0.05, 0.1, 0.2]
params['selectfrommodel__estimator__C'] = [0.1, 1, 10]
params['selectfrommodel__estimator__penalty']= ['l1', 'l2']
params['selectfrommodel__estimator__threshold']=['median', 'mean', '1.25*mean', '0.75*mean']

grid = GridSearchCV(pipe, params, cv=5, scoring='recall')
%time grid.fit(X_train, y_train);

不幸的是,阈值似乎不在参数列表中 (pipe.named_steps.selectfrommodel.estimator.get_params().keys()),因此要使 GridSearchCV 正常工作,需要对此行进行注释。

params['selectfrommodel__estimator__threshold']=['median', 'mean', '1.25*mean', '0.75*mean']

有没有办法微调阈值?

【问题讨论】:

    标签: python machine-learning scikit-learn logistic-regression gridsearchcv


    【解决方案1】:

    因为重要性是基于系数的绝对值的平均值。如果你对相对值做平均,平均重要性会更低

    我已经构建了一个示例来演示该行为:

    from sklearn.feature_selection import SelectFromModel
    from sklearn.linear_model import LogisticRegression
    X = [[ 0.87, -1.34,  0.31 ],
         [-2.79, -0.02, -0.85 ],
         [-1.34, -0.48, -2.55 ],
         [ 1.92,  1.48,  0.65 ]]
    y = [0, 1, 0, 1]
    selector = SelectFromModel(estimator=LogisticRegression(), threshold="1.25*mean").fit(X, y)
    print(selector.estimator_.coef_)
    print(selector.threshold_) # 0.6905659148858644
    # note here the absolute transformation before the mean
    print(abs(selector.estimator_.coef_).mean()*1.25) # 0.6905659148858644
    

    另请注意,特征重要性是模型训练的结果,而不是您可以先验定义的东西。这就是原因,因为您无法满足阈值,该阈值仅在您的训练后获得

    【讨论】:

    • 清除第一部分!你是什​​么意思“你的模型训练的结果”,你的意思是 logreg 模型,对吧?能否进一步说明?
    • @G.Macia 模型系数是在训练后获得的,只有在此之后才能详细说明阈值。您不能在训练之前选择一组阈值,因为它不是模型的超参数。不要忘记接受最佳答案:)
    • 超参数通常在训练之前定义,而不是之后。
    • @G.Macia 更清楚地说,系数是给定一组超参数(例如估计器惩罚)的训练结果。你不会在训练期间选择你的特征
    【解决方案2】:

    @Nikaido 问题对于第一部分是完全正确的,abs() 丢失了。这意味着abs(selector.estimator_.coef_).mean()*1.25 等于selector.threshold_

    对于第二部分,确实有可能,正确的做法是改变这一行:

    params['selectfrommodel__estimator__threshold']=['median', 'mean', '1.25*mean', '0.75*mean']
    

    到另一行:

    params['selectfrommodel__threshold']=['median', 'mean', '1.25*mean', '0.75*mean']
    

    因为threshold 是来自selectfrommodel 而不是来自estimator 的参数,请参阅下文如何获取这两种情况的完整列表以进一步调整超参数使用这些:

    pipe.named_steps.selectfrommodel.get_params().keys() 
    pipe.named_steps.selectfrommodel.estimator.get_params().keys() 
    

    【讨论】:

      猜你喜欢
      • 2014-11-05
      • 2021-03-26
      • 2018-02-24
      • 2018-06-01
      • 2015-05-20
      • 2018-08-26
      • 2018-09-25
      • 2019-10-22
      相关资源
      最近更新 更多