You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何复现scikit-learn RFECV类cv_results_中的交叉验证分数?

对递归特征消除交叉验证(RFECV)的理解

sklearn.feature_selection.RFECV的核心逻辑:

  • 传入带有coef_或feature_importances_属性的算法,先在全特征数据集上训练,生成特征重要性排名
  • 通过交叉验证评估当前特征集下的模型性能
  • 移除排名最低的特征,重新训练模型生成新的重要性排名,再次交叉验证评估
  • 重复上述过程,直到剩余特征数达到min_features_to_select指定值(默认1个)
  • 最终选择交叉验证分数最高的特征数量
问题

我能从rfecv.cv_results_["mean_test_score"]获取不同特征数量对应的交叉验证分数,但手动复现n-1个特征对应的分数时,结果和内置方法不一致。

手动复现代码:

from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import StratifiedKFold
from sklearn.model_selection import cross_validate
from sklearn.feature_selection import RFECV

alg = DecisionTreeClassifier(random_state = 0)
cv_split = StratifiedKFold(5)
# train是pandas数据框,x_var和y_var均为包含变量名的列表
X = train[x_var]
y = np.ravel(train[y_var])

alg.fit(X, y)
lowest_ranked_feature = np.argmin(alg.feature_importances_)
x_var.pop(lowest_ranked_feature)

one_removed_feature = train[x_var]
alg.fit(one_removed_feature, y)
cv_score = cross_validate(alg, one_removed_feature, y, cv=cv_split, scoring="accuracy")
np.mean(cv_score["test_score"])

内置方法获取分数的代码:

rfecv = RFECV(
    estimator=alg,
    step=1,
    cv=cv_split,
    scoring="accuracy",
)

rfecv.fit(X, y)
rfecv.cv_results_["mean_test_score"][-2]

注:全特征(n个)对应的分数,手动复现和内置方法结果一致。

解决方法

你手动复现的逻辑和RFECV的核心差异在于:RFECV是在每个交叉验证的训练子集内独立完成特征选择,而非用整个数据集的特征重要性决定移除哪个特征。

正确的手动复现步骤及代码:

  1. 遍历StratifiedKFold的每个训练/测试折
  2. 在每个训练折上训练模型,得到特征重要性并移除排名最低的特征
  3. 用筛选后的训练折特征重新训练模型,在对应测试折上评估分数
  4. 取所有测试折分数的平均值
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import StratifiedKFold
import numpy as np

alg = DecisionTreeClassifier(random_state=0)
cv_split = StratifiedKFold(5)
X = train[x_var]
y = np.ravel(train[y_var])

scores = []
for train_idx, test_idx in cv_split.split(X, y):
    # 拆分当前折的训练和测试数据
    X_train, X_test = X.iloc[train_idx], X.iloc[test_idx]
    y_train, y_test = y[train_idx], y[test_idx]
    
    # 在训练折上训练模型,确定要移除的特征
    temp_alg = DecisionTreeClassifier(random_state=0)
    temp_alg.fit(X_train, y_train)
    lowest_rank_idx = np.argmin(temp_alg.feature_importances_)
    
    # 同步移除训练和测试折中的目标特征
    X_train_selected = X_train.drop(X_train.columns[lowest_rank_idx], axis=1)
    X_test_selected = X_test.drop(X_test.columns[lowest_rank_idx], axis=1)
    
    # 用筛选后的特征训练模型并评估
    temp_alg.fit(X_train_selected, y_train)
    scores.append(temp_alg.score(X_test_selected, y_test))

# 计算平均分数,与rfecv.cv_results_["mean_test_score"][-2]结果一致
np.mean(scores)

关键注意点:

  • 必须在每个交叉验证的训练折内单独做特征选择,避免用全数据集的特征重要性导致数据泄露
  • 每次循环重新初始化模型,避免之前的训练状态干扰结果
  • 测试折要同步移除对应特征,保证与训练折的特征集一致

内容的提问来源于stack exchange,提问作者AvanishM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 18:43:09