为什么只在 x_train 上使用 Scaler.fit 而不是在 x_test 上使用 MinMaxScaler 来规范化值?

数据挖掘 scikit-学习 特征工程 正常化 特征缩放
2022-02-26 15:54:07

虽然对数据进行规范化是说我们只需要适应 x_train 而不是 x_test ?为什么我们不应该适合 x_test ?

如果我们不应该在 x_test 上安装缩放器,那么为什么我们需要在 x_test 上单独应用转换?

from sklearn.preprocessing import MinMaxScaler
Scaler=MinMaxScaler()
Scaler.fit(X_train)
x_train=Scaler.transform(x_train)
x_test=Scaler.transform(x_test)
3个回答

如果您适合使用缩放器,x_test那么您将使用来自测试集的信息并且会泄漏数据。如果您的模型在生产中,您将不会拥有这些信息,因此在拟合您的模型时无法使用。

除了Oxbowerce发表的评论之外,您还可以进行如下推理:在实际情况下,您希望 X_train 数据的分布类似于 X_test 数据,因此将 MinMaxScaler 转换器应用于拟合的 X_test 数据“仅“在 X_train 上意味着(或应该意味着)与使用 X_test 拟合它相比没有实际差异;毕竟,这个缩放器所做的是找到这种分布的最小值和最大值,并用这些值重新缩放。

不过,如果您使用所有可用的新数据获得越来越多的数据,您可以不时在生产场景中改装您的变压器......

scikit-learn MinMaxScaler 的工作方式是:

  • 拟合操作:查找特征列的最小值和最大值(请注意,此缩放分别应用于每个数据框属性/列)
  • 变换:应用最小最大缩放操作,在“适合”操作中找到值

工作示例:

假设我们有一个具有以下值的特征: [285, 543, 511, 359, 338, 678, 519, 760, 792, 395, 320, 952, 653, 129, 306, 91, 284, 359, 595, 167, 112, 802, 740, 977, 753, 74, 908, 353, 168, 622, 613, 602, 786, 396, 957, 600, 457, 74, 825, 547, 983, 825, 978, 823, 503, 782, 41, 574, 42, 851, 532, 225, 71, 827, 215, 25, 857, 682, 93, 218, 526, 776, 425, 688, 557, 61, 218, 984, 339, 92, 623, 762, 147, 634, 159, 24, 634, 365, 772, 283, 954, 805, 736, 678, 445, 677, 175, 484, 508, 341, 719, 599, 118, 401, 405, 349, 268, 133, 902, 804]

我们需要的是通过应用最小最大缩放定义来重新缩放每个值:

rescaled_X_value = (X_value - feature_values_min) / (feature_values_max - feature_values_min)

关键是,我们的最小值和最大值是多少?这就是 scikit-learn MinMaxScaler 对您的火车数据进行的“拟合”操作;关键是,一旦你在火车数据上使用这个“拟合”操作来找到最小值和最大值,你不必在测试数据上重复它,你只需要应用“变换”操作来重新调整测试数据。让我们看看它是如何工作的:

如果我们手动应用它:

min_max_scaled_train_data = (train_feature_data - train_feature_data.min())/(train_feature_data.max()-train_feature_data.min())
min_max_scaled_train_data[:10]

前 10 个元素的结果是:

array([0.27111575, 0.54014599, 0.50677789, 0.34827946, 0.32638165,
       0.68091762, 0.51511992, 0.76642336, 0.79979145, 0.38581856])

使用 scikit 学习定标器:

from sklearn.preprocessing import MinMaxScaler

min_max_scaler = MinMaxScaler()
min_max_scaler.fit(train_feature_data.reshape(-1, 1))

min_max_scaler 已经拥有要应用于您的新数据(假设您的测试数据)的信息(即最小值和最大值),而无需再次拟合。我们还可以看到,结果和上面手动做的一样:

min_max_scaler.transform(train_feature_data.reshape(-1, 1))[:10]
array([[0.27111575],
       [0.54014599],
       [0.50677789],
       [0.34827946],
       [0.32638165],
       [0.68091762],
       [0.51511992],
       [0.76642336],
       [0.79979145],
       [0.38581856]])

作为附加检查,您可以看到在找到最小值和最大值时 train_data 与所有数据(即训练 + 测试)之间的差异并不大,因为两者来自相同的分布。您可以在此处找到示例完整代码