【问题标题】:Right way to use RFECV and Permutation Importance - Sklearn使用 RFECV 和排列重要性的正确方法 - Sklearn
【发布时间】:2020-10-13 16:10:39
【问题描述】:

Sklearn#15075 中提出了实现此功能的建议,但与此同时,建议将eli5 作为解决方案。但是,我不确定我是否以正确的方式使用它。这是我的代码:

from sklearn.datasets import make_friedman1
from sklearn.feature_selection import RFECV
from sklearn.svm import SVR
import eli5
X, y = make_friedman1(n_samples=50, n_features=10, random_state=0)
estimator = SVR(kernel="linear")
perm = eli5.sklearn.PermutationImportance(estimator,  scoring='r2', n_iter=10, random_state=42, cv=3)
selector = RFECV(perm, step=1, min_features_to_select=1, scoring='r2', cv=3)
selector = selector.fit(X, y)
selector.ranking_
#eli5.show_weights(perm) # fails: AttributeError: 'PermutationImportance' object has no attribute 'feature_importances_'

有几个问题:

  1. 我不确定我是否以正确的方式使用交叉验证。 PermutationImportance 是使用cv 来验证验证集的重要性,或者交叉验证应该只使用RFECV? (在示例中,我在两种情况下都使用了cv=3,但不确定这样做是否正确)

  2. 如果我取消注释最后一行,我会得到一个AttributeError: 'PermutationImportance' ... 这是因为我适合使用RFECV?我正在做的类似于这里的最后一个 sn-p:https://eli5.readthedocs.io/en/latest/blackbox/permutation_importance.html

  3. 作为一个不太重要的问题,当我在 eli5.sklearn.PermutationImportance 中设置 cv 时,这会给我一个警告:

.../lib/python3.8/site-packages/sklearn/utils/validation.py:68: FutureWarning: Pass classifier=False as keyword args. From version 0.25 passing these as positional arguments will result in an error warnings.warn("Pass {} as keyword args. From version 0.25 "

整个过程有点模糊。 有没有办法直接在 Sklearn 中进行操作? 例如通过添加feature_importances 属性?

【问题讨论】:

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


    【解决方案1】:

    由于目标是选择具有置换重要性和递归特征消除的最佳特征数量,我建议将RFECVPermutationImportanceKFold 之类的CV 拆分器结合使用。代码可能如下所示:

    import warnings
    from eli5 import show_weights
    from eli5.sklearn import PermutationImportance
    from sklearn.datasets import make_friedman1
    from sklearn.feature_selection import RFECV
    from sklearn.model_selection import KFold
    from sklearn.svm import SVR
    
    
    warnings.filterwarnings("ignore", category=FutureWarning)
    
    X, y = make_friedman1(n_samples=50, n_features=10, random_state=0)
    
    splitter = KFold(n_splits=3) # 3 folds as in the example
    
    estimator = SVR(kernel="linear")
    selector = RFECV(
        PermutationImportance(estimator,  scoring='r2', n_iter=10, random_state=42, cv=splitter),
        cv=splitter,
        scoring='r2',
        step=1
    )
    selector = selector.fit(X, y)
    selector.ranking_
    
    show_weights(selector.estimator_)
    

    关于您的问题:

    1. PermutationImportance 会根据KFold 提供的分割,以相同的策略计算特征重要性和RFECV r2 评分。

    2. 您在不合适的 PermutationImportance 对象上调用了 show_weights。这就是你出错的原因。您应该改为使用 estimator_ 属性访问拟合对象。

    3. 可以忽略。

    【讨论】:

    • 感谢您的完整回答!我使用RFECV 的原因是因为我最后需要grid_scores 来找到最优的特征数量,即每一步使用最重要特征的分数。现在我有两种方法:I)使用您的方法,然后:cross_val_score(selector.estimator_, X,y, scoring='r2', cv=3) 在每一步或 II)使用我的初始尝试:selector = RFECV(PermutationImportance(estimator, scoring='r2', n_iter=2, random_state=42, cv=4),step=1, scoring='r2', cv=3) 然后selector.grid_scores_ 这有意义吗?或者你能想出更好的方法吗?
    • 好的,我明白了。在这种情况下,我认为坚持使用RFECV 是更简洁的方法。然后,我建议为 RFECVPermutationImportance 提供一个 CV 拆分器对象,以确保所有指标都是在相同的拆分上计算的。我会相应地更新答案。
    • 谢谢!这正是我不确定的部分。我认为RFECV 的每个折叠在使用cv=k 时被分成更小的k 折叠PermutationImportance,然后在折叠训练和测试数据上计算特征重要性。不是这样吗?
    • 据我了解,答案是肯定的和否定的。 RFECV 基本上分两个步骤工作:首先,它通过拟合整个火车折叠并选择在所有折叠中给出最小平均误差的特征数量来确定最佳特征数量。在这一步中,您是对的:PermutationImportance 将使用较小的折叠来计算其值。但在那之后,具有先前找到的最佳特征数量的传统RFE 模型适合整个数据集以找到实际特征。现在,PermutationImportance 将使用与上一步相同的拆分。
    • 这是我通过查看源代码所理解的。我看不出有一种方法可以确保第一步中的拆分也相同。除非您定义自己的方法,否则这可能是您可以获得的最佳折衷方案。但是您肯定也希望对PermutationImportance 进行交叉验证。因为否则,特征重要性是根据训练估计器的数据计算的,因此不能反映特征对泛化的重要性。
    猜你喜欢
    • 2021-11-24
    • 2017-05-01
    • 2017-10-20
    • 2017-07-18
    • 2019-06-04
    • 1970-01-01
    • 2019-09-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多