好吧,首先,让我们指出 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
- 按照 80%-20% 拆分规则创建训练和测试集。
- 使用 RFE 转换它们(即,选择最好的 2 个特征,如前代码 sn-p 中所指定)。在 RFE 上调用
fit_transform 时,它会运行递归特征消除,并且它将有关选定特征的信息保存在其对象状态中。要了解哪些是选定的功能,请致电rfe.support_。
注意:在测试集上只执行transform,以便rfe.support_中的特征用于过滤掉测试集中的其他特征。
- 拟合模型并返回元组 (y_test, y_pred)。
y_test 和 y_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时,后者:
- 将其拆分为训练和测试数据;
- 在训练数据上调用
RFE.fit_transform();
- 对测试数据应用
RFE.transform(),使其包含相同的特征;
- 在训练数据上调用
estimator.fit() 以拟合(即训练)模型;
- 调用
estimator.predict() 对测试数据进行预测。
- 将预测值与实际值进行比较,并在内部保存性能结果(您传递给
scoring 参数的结果)。
- 对交叉验证过程中的每个拆分重复步骤 1-6
在程序结束时,有人可以访问性能结果并在各折中取平均值。