5

我目前正在使用 cross_val_score 和 KFold 来评估在数据预处理中的不同点使用 StandardScaler 的影响,特别是在执行交叉验证之前缩放整个训练数据集是否会引入数据泄漏以及与缩放相比的影响管道内的数据(因此仅将其应用于训练折叠)。

我目前的流程如下:

实验A

  • 从 sklearn.datasets 导入波士顿住房数据集并拆分为数据 (X) 和目标 (y)
  • 创建一个管道 (sklearn.pipeline),在应用线性回归之前应用 StandardScaler
  • 将交叉验证方法指定为 5 折的 KFold
  • 使用上述 Pipeline 和 KFold 方法进行交叉验证(cross_val_score)并观察分数

实验 B

  • 使用与上述相同的波士顿住房数据
  • 整个数据集上的 fit_transform StandardScaler
  • 使用 cross_val_Score 再次对 5 折执行交叉验证,但这次直接输入 LinearRegression 而不是管道
  • 将此处的分数与实验 A 进行比较

获得的分数是相同的(大约小数点后 13 位),我质疑实验 B 在交叉验证期间肯定会引入数据泄漏。

我看过帖子说在交叉验证之前是否对整个训练集进行缩放并不重要,如果这是真的,我想知道为什么,如果这不是真的,我想了解为什么分数尽管数据泄漏,仍然可以如此相似?

请参阅下面的测试代码:

import numpy as np
import pandas as pd
from sklearn.pipeline import Pipeline
from sklearn import datasets

from sklearn.preprocessing import StandardScaler
from sklearn.svm import LinearSVC
from sklearn.model_selection import KFold, StratifiedKFold

from sklearn.model_selection import cross_val_score, cross_val_predict

from sklearn.linear_model import LinearRegression

np.set_printoptions(15)

boston = datasets.load_boston()
X = boston["data"]
y = boston["target"]
scalar = StandardScaler()
clf = LinearRegression()

class StScaler(StandardScaler):
    def fit_transform(self,X,y=None):
        print('Length of Data on which scaler is fit on =', len(X))
        output = super().fit(X,y)
#         print('mean of scalar =',output.mean_)
        output = super().transform(X)
        return output


pipeline = Pipeline([('sc', StScaler()), ('estimator', clf)])

cv = KFold(n_splits=5, random_state=42)

cross_val_score(pipeline, X, y, cv = cv)

# Now fitting Scaler on whole train data
scaler_2 = StandardScaler()
clf_2 = LinearRegression()

X_ss = scaler_2.fit_transform(X)
cross_val_score(clf_2, X_ss, y, cv=cv)

谢谢!

4

0 回答 0