【问题标题】:Sklearn RFE, pipeline and cross validationSklearn RFE、管道和交叉验证
【发布时间】:2021-03-25 12:23:22
【问题描述】:

我正在尝试弄清楚如何使用 RFE 解决回归问题,并且我正在阅读一些教程。

我找到了一个关于如何使用 RFECV 自动选择理想数量的特征的示例,它类似于:

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import StratifiedKFold
from sklearn.feature_selection import RFECV


rfecv = RFECV(estimator=RandomForestClassifier(random_state=101), step=1, cv=StratifiedKFold(10), scoring='accuracy')
rfecv.fit(X, target)
print(np.where(rfecv.support_ == False)[0])

我觉得这很简单。

但是,我正在检查如何使用 RFE 对象做同样的事情,但为了包括交叉验证,我只找到了涉及使用管道的解决方案,例如:

X, y = make_regression(n_samples=1000, n_features=10, n_informative=5, random_state=1)
# create pipeline
rfe = RFE(estimator=DecisionTreeRegressor(), n_features_to_select=5)
model = DecisionTreeRegressor()
pipeline = Pipeline(steps=[('s',rfe),('m',model)])
# evaluate model
cv = RepeatedKFold(n_splits=10, n_repeats=3, random_state=1)
n_scores = cross_val_score(pipeline, X, y, scoring='neg_mean_absolute_error', cv=cv, n_jobs=-1, error_score='raise')

# report performance
print(f'MAE: {mean(n_scores):.3f}')

我不确定这里到底发生了什么。 该管道用于对 RFE 算法和第二个 DecisionTreeRegressor(模型)进行排队。 如果我没记错的话,这个想法是,对于交叉验证中的每次迭代,都会执行 RFE,选择所需数量的最佳特征,然后仅使用这些特征运行第二个模型。 但是 RFE 如何/何时将有关已选择哪些特征的信息传递给 DecisionTreeRegressor?它甚至发生过,还是代码缺少这部分?

【问题讨论】:

    标签: python scikit-learn rfe


    【解决方案1】:

    好吧,首先,让我们指出 RFECV 和 RFE 在您的脚本中做两个独立的工作:前者是选择最佳数量的特征,而后者是选择最重要的五个特征(或者,最佳组合5 个特征,考虑到它们对决策树回归器的重要性)。

    回到您的问题:“RFE 何时将有关已选择哪些特征的信息传递给决策树?”值得注意的是,RFE 确实没有明确告诉决策树选择了哪些特征。简单地说,它将一个矩阵作为输入(训练集)并根据n_features_to_select=N 参数将其转换为 N 列的矩阵。 该矩阵(即转换后的训练集)与目标变量一起作为输入传递给决策树,目标变量返回可用于预测未见实例的拟合模型。

    让我们深入研究一个分类示例:

    """ Import dependencies and load data """
    import numpy as np
    import pandas as pd
    
    from sklearn.datasets import load_breast_cancer
    from sklearn.feature_selection import RFE
    from sklearn.metrics import precision_score
    from sklearn.tree import DecisionTreeClassifier
    
    X, y = load_breast_cancer(return_X_y=True)
    rfe = RFE(estimator=DecisionTreeClassifier(), n_features_to_select=2)
    

    我们现在已经加载了breast_cancer 数据集并实例化了一个RFE 对象(我使用了DecisionTreeClassifier,但也可以使用其他算法)。

    要了解如何在管道中处理训练数据,让我们从一个手动示例开始,该示例显示管道在其“基本步骤”中分解后的工作方式:

    from sklearn.model_selection import train_test_split
    
    def test_and_train(X, y, random_state):
        # For simplicity, let's use 80%-20% splitting
        X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=random_state)
    
        # Fit and transform the training data by applying Recursive Feature Elimination
        X_train_transformed = rfe.fit_transform(X_train, y_train)
        # Transform the testing data to select the same features
        X_test_transformed = rfe.transform(X_test)  
    
        print(X_train[0:3])
        print(X_train_transformed[0:3])
        print(X_test_transformed[0:3])
    
        # Train on the transformed trained data
        fitted_model = DecisionTreeClassifier().fit(X_train_transformed, y_train)
    
        # Predict on the transformed testing data
        y_pred = fitted_model.predict(X_test_transformed)
    
        print('True labels: ', y_test)
        print('Predicted labels:', y_pred)
    
        return y_test, y_pred
    
    precisions = list() # to store the precision scores (can be replaced by any other evaluation measure)
    
    y_test, y_pred = test_and_train(X, y, 42)
    precisions.append(precision_score(y_test, y_pred))
    
    y_test, y_pred = test_and_train(X, y, 84)
    precisions.append(precision_score(y_test, y_pred))
    
    y_test, y_pred = test_and_train(X, y, 168)
    precisions.append(precision_score(y_test, y_pred))
    
    print('Average precision:', np.mean(precisions))
    """
    Average precision: 0.92
    """
    

    在上面的脚本中,我们创建了一个函数,给定一个数据集X 和一个目标变量y

    1. 按照 80%-20% 拆分规则创建训练和测试集。
    2. 使用 RFE 转换它们(即,选择最好的 2 个特征,如前代码 sn-p 中所指定)。在 RFE 上调用 fit_transform 时,它会运行递归特征消除,并且它将有关选定特征的信息保存在其对象状态中。要了解哪些是选定的功能,请致电rfe.support_注意:在测试集上只执行transform,以便rfe.support_中的特征用于过滤掉测试集中的其他特征。
    3. 拟合模型并返回元组 (y_test, y_pred)。

    y_testy_pred 可用于分析模型的性能,例如其精度。 将精度保存在一个数组中,该过程重复 3 次。 最后,我们打印平均精度。

    我们模拟了一个交叉验证程序,通过在各自的训练和测试集中将原始数据拆分 3 次,拟合模型,计算并平均其三个折叠的性能(即精度)。 这个过程可以使用 RepeatedKFold 验证来简化:

    from sklearn.model_selection import RepeatedKFold
    
    precisions = list()
    rkf = RepeatedKFold(n_splits=2, n_repeats=3, random_state=1)
    
    for train_index, test_index in rkf.split(X, y):
        # print("TRAIN:", train_index, "TEST:", test_index)
        X_train, X_test = X[train_index], X[test_index]
        y_train, y_test = y[train_index], y[test_index]
        
        X_train_transformed = rfe.fit_transform(X_train, y_train)
        X_test_transformed = rfe.transform(X_test)
        
        fitted_model = DecisionTreeClassifier().fit(X_train_transformed, y_train)
        y_pred = fitted_model.predict(X_test_transformed)
    
        precisions.append(precision_score(y_test, y_pred))
    
    print('Average precision:', np.mean(precisions))
    """
    Average precision: 0.93
    """
    

    使用 Pipeline 更进一步:

    from sklearn.pipeline import Pipeline
    from sklearn.model_selection import cross_val_score
    
    rkf = RepeatedKFold(n_splits=2, n_repeats=3, random_state=1)
    pipeline = Pipeline(steps=[('s',rfe),('m',DecisionTreeClassifier())])
    precisions = cross_val_score(pipeline, X, y, scoring='precision', cv=rkf)
    
    print('Average precision:', np.mean(precisions))
    """
    Average precision: 0.93
    """
    
    

    综上所述,当原始数据传递给Pipeline时,后者:

    1. 将其拆分为训练和测试数据;
    2. 在训练数据上调用RFE.fit_transform()
    3. 对测试数据应用RFE.transform(),使其包含相同的特征;
    4. 在训练数据上调用 estimator.fit() 以拟合(即训练)模型;
    5. 调用estimator.predict() 对测试数据进行预测。
    6. 将预测值与实际值进行比较,并在内部保存性能结果(您传递给scoring 参数的结果)。
    7. 对交叉验证过程中的每个拆分重复步骤 1-6

    在程序结束时,有人可以访问性能结果并在各折中取平均值。

    【讨论】:

    • 哇,非常感谢,你真的不能比这更详尽了!我完全错过了管道在训练数据上使用 fit_transform 的部分……既然你解释了那部分,一切都说得通了。感恩千里!
    猜你喜欢
    • 2020-09-16
    • 2012-12-31
    • 2022-01-25
    • 2017-12-22
    • 2018-08-16
    • 2015-06-22
    • 2018-04-26
    • 2018-05-17
    • 2021-02-10
    相关资源
    最近更新 更多