为什么Scikit-learn的RFECV在训练数据集上返回的特征差异很大?

我一直在使用波士顿数据集进行RFECV实验。

据我目前所知,为了防止数据泄露,重要的是仅在训练数据上而不是整个数据集上执行此类操作。

我仅在训练数据上进行了RFECV操作,结果显示14个特征中有13个是最优的。然而,当我对整个数据集运行相同的过程时,这次结果显示只有6个特征是最优的——这看起来更合理。

为了说明这一点:

import numpy as npimport pandas as pdfrom sklearn.model_selection import train_test_splitfrom sklearn.feature_selection import RFECVfrom sklearn.linear_model import LinearRegressionfrom sklearn.datasets import load_boston### CONSTANTSTARGET_COLUMN = 'Price'TEST_SIZE = 0.1RANDOM_STATE = 0### LOAD THE DATA AND ASSIGN TO X and ydata_dict = load_boston()data = data_dict.datafeatures = list(data_dict.feature_names)target = data_dict.targetdf = pd.DataFrame(data=data, columns=features)df[TARGET_COLUMN] = targetX = df[features]y = df[TARGET_COLUMN]### PERFORM TRAIN TEST SPLITX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=TEST_SIZE, random_state=RANDOM_STATE)#### DETERMINE THE DATA THAT IS PASSED TO RFECV## Just the Training dataX_input = X_trainy_input = y_train## All the data# X_input = X# y_input = y### IMPLEMENT RFECV AND GET RESULTSrfecv = RFECV(estimator=LinearRegression(), step=1, scoring='neg_mean_squared_error')rfecv.fit(X_input, y_input)rfecv.transform(X_input)print(f'Optimal number of features: {rfecv.n_features_}')imp_feats = X.drop(X.columns[np.where(rfecv.support_ == False)[0]], axis=1)print('Important features:', list(imp_feats.columns))

运行上述代码将得到以下结果:

Optimal number of features: 13Important features: ['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT']

现在,如果我更改代码,让RFECV适应所有数据:

#### DETERMINE THE DATA THAT IS PASSED TO RFECV## Just the Training data# X_input = X_train # NOW COMMENTED OUT# y_input = y_train # NOW COMMENTED OUT## All the dataX_input = X  # NOW UN-COMMENTEDy_input = y  # NOW UN-COMMENTED

并运行它,我得到以下结果:

Optimal number of features: 6Important features: ['CHAS', 'NOX', 'RM', 'DIS', 'PTRATIO', 'LSTAT']

我不明白为什么在整个数据集上的结果与仅在训练集上的结果差异如此明显(而且似乎更准确)。

我尝试通过将TEST_SIZE常量设置为极小值,使训练集的规模接近整个数据集,但仍然得到了这种看似不太可能的差异。

我错过了什么?


回答:

这种行为确实看起来很出乎意料,尤其是当你提到即使将测试集大小减少到10%甚至5%,仍然会发现类似的差异,这似乎非常违反直觉。理解这里发生的事情的关键是认识到,对于这个特定的数据集,每列的值在各行之间不是随机分布的(例如,尝试运行X['CRIM'].plot())。你用来分割数据的train_test_split函数有一个默认值为Trueshuffle参数。所以如果你查看X_train数据集,你会发现索引是打乱的,而在X中索引是顺序的。这意味着当RFECV类在内部进行交叉验证时,它在X的每次分割中得到的是一个有偏见的数据子集,而在X_train的每次分割中得到的是一个更具代表性/随机的数据子集。如果你将shuffle=False传递给train_test_split,你会发现这两个结果更加接近(或者更好的方法,可能是在X上打乱索引)。

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注