这算作"data leakage"吗?

Does this count as "data leakage"?

我正在尝试使用网格搜索调整我的 k 最近邻模型。但是因为我的数据集不稳定,我需要先标准化它。

但是,我在教程中看到,在进行 k 折交叉验证之前进行标准化会导致数据泄漏,因为验证集会影响训练集。

我想问一下我下面的代码块中是否存在这个问题。如果是这样,我该如何避免这种情况。谢谢!

#Standardizing my data

scaler = StandardScaler().fit(X_train)
rescaledX = scaler.transform(X_train)

#Using Grid Search and k-fold cross validation

k_values = numpy.array([1,3,5,7,9,11,13,15,17,19,21])
param_grid = dict(n_neighbors=k_values)
model = KNeighborsRegressor()
kfold = KFold(n_splits=num_folds, random_state=seed, shuffle=True)

#Does this step cause data leakage if all folds in k-fold were standardized together in 2nd line?

grid = GridSearchCV(estimator=model, param_grid=param_grid, scoring=scoring, cv=kfold)
grid_result = grid.fit(rescaledX, Y_train)

是的,这是数据泄漏:网格搜索中的得分来自测试折叠,但这些都是与 X_train 的其余部分一起缩放的,所以一些来自测试折叠的信息已被模型“看到”。

您可以使用 sklearn Pipelines 解决这个问题,只对网格搜索的训练折叠进行缩放和模型拟合:

from sklearn.pipeline import Pipeline
pipe = Pipeline(steps=[('scale', StandardScaler()),
                       ('knn', KNeighborsRegressor())])
# the hyperparameter names need a prefix now that the model is in a pipeline:
param_grid = dict(knn__n_neighbors=k_values)
grid = GridSearchCV(estimator=pipe, param_grid=param_grid, scoring=scoring, cv=kfold)
grid_result = grid.fit(rescaledX, Y_train)

(现在,来自缩放的数据泄漏可能是一个相当温和的版本,特别是如果你的训练集实际上是一个很好的代表性样本。并且因为受影响的分数只是用于 select 超参数的分数(注意best_score_ 不是无偏估计!),任何泄漏都必须具有使某些超参数受益于另一个超参数的效果。 但在这种情况下,只需使用管道:它可能不会显着影响计算时间,它在统计上更严格,并且更容易测试和投入生产(构建了缩放步骤-输入看不见的数据)。)