首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >RFE,管道和交叉验证

RFE,管道和交叉验证
EN

Stack Overflow用户
提问于 2020-12-14 20:40:43
回答 1查看 1.3K关注 0票数 1

我试图找出如何使用RFE来解决回归问题,我正在阅读一些教程。

我找到了一个关于如何使用RFECV自动选择理想数量的特性的示例,其内容如下:

代码语言:javascript
复制
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对象做同样的事情,但是为了包含交叉验证,我只找到了涉及使用管道的解决方案,例如:

代码语言:javascript
复制
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的?它发生了吗,或者代码遗漏了这个部分?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-12-15 19:10:16

首先,让我们指出,RFECV和RFE在脚本中执行两个不同的工作:前者是选择最优的特性数,而后者是选择最重要的五个特性(或者说,考虑到它们对DecisionTreeRegressor的重要性,五个特性的最佳组合)。

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

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

代码语言:javascript
复制
""" 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)

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

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

代码语言:javascript
复制
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
"""

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

  1. 按照80%-20%的拆分规则创建一个培训和测试集。
  2. 使用RFE对它们进行转换(即,如前代码段所指定的那样,选择最佳的2个特性)。在RFE上调用fit_transform时,它运行递归功能消除,而则在其对象状态中保存有关所选特性的信息。要知道哪些是所选的特性,请调用rfe.support_注意:测试集上的只执行转换,因此使用rfe.support_中的特性从测试集中筛选出其他特性。
  3. 符合模型并返回元组(y_test,y_pred)。

y_testy_pred可以用来分析模型的性能,如精度。精度保存在一个数组中,程序重复了3次。最后,我们打印出平均精度。

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

代码语言:javascript
复制
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
"""

甚至还有管道:

代码语言:javascript
复制
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
"""

总之,当原始数据被传递给管道时,管道:

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

在程序结束时,有人可以访问性能结果,并将它们平均在褶皱上。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65296195

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档