Keras回归使用Scikit了解StandardScaler与管道和无管道

Fra*_*ank 3 python pipeline scikit-learn keras

我正在比较两个关于KerasRegressor使用Scikit-Learn的程序的性能StandardScaler:一个程序与Scikit-Learn Pipeline和一个程序没有Pipeline.

计划1:

estimators = []
estimators.append(('standardise', StandardScaler()))
estimators.append(('multiLayerPerceptron', KerasRegressor(build_fn=build_nn, nb_epoch=num_epochs, batch_size=10, verbose=0)))
pipeline = Pipeline(estimators)
log = pipeline.fit(X_train, Y_train)
Y_deep = pipeline.predict(X_test)
Run Code Online (Sandbox Code Playgroud)

计划2:

scale = StandardScaler()
X_train = scale.fit_transform(X_train)
X_test = scale.fit_transform(X_test)
model_np = KerasRegressor(build_fn=build_nn, nb_epoch=num_epochs, batch_size=10, verbose=0)
log = model_np.fit(X_train, Y_train)
Y_deep = model_np.predict(X_test)
Run Code Online (Sandbox Code Playgroud)

我的问题是,程序1可以使R2得分为0.98(平均3次试验),而程序2只能达到R2得分为0.84(平均3次试验).有谁可以解释这两个程序之间的区别?

Viv*_*mar 6

在第二种情况下,你正在呼唤StandardScaler.fit_transform()两者X_trainX_test.它的错误用法.

你应该叫fit_transform()X_train,然后只调用transform()X_test.因为那是Pipeline做什么的.在Pipeline作为文档状态,将:

fit():

一个接一个地拟合所有变换并转换数据,然后使用最终估算器拟合变换后的数据

预测():

将变换应用于数据,并使用最终估算器进行预测

所以你看,它只适用transform()于测试数据,而不是fit_transform().

所以详细说明我的观点,你的代码应该是:

scale = StandardScaler()
X_train = scale.fit_transform(X_train)

#This is the change
X_test = scale.transform(X_test)

model_np = KerasRegressor(build_fn=build_nn, nb_epoch=num_epochs, batch_size=10, verbose=0)
log = model_np.fit(X_train, Y_train)
Y_deep = model_np.predict(X_test)
Run Code Online (Sandbox Code Playgroud)

调用fit()fit_transform()测试数据错误地将其缩放到与列车数据上使用的不同的比例.并且是预测变化的来源.

编辑:回答评论中的问题:

看,fit_transform()只是一个快捷功能fit(),然后做transform().因为StandardScaler,fit()不返回任何东西,只是学习数据的均值和标准差.然后transform()应用数据学习来返回新的缩放数据.

所以你所说的导致以下两种情况:

场景1:错了

1) X_scaled = scaler.fit_transform(X)
2) Divide the X_scaled into X_scaled_train, X_scaled_test and run your model. 
   No need to scale again.
Run Code Online (Sandbox Code Playgroud)

场景2:错误(基本上等于场景1,反转缩放和随地吐痰操作)

1) Divide the X into X_train, X_test
2) scale.fit_transform(X) [# You are not using the returned value, only fitting the data, so equivalent to scale.fit(X)]
3.a) X_train_scaled = scale.transform(X_train) #[Equals X_scaled_train in scenario 1]
3.b) X_test_scaled = scale.transform(X_test) #[Equals X_scaled_test in scenario 1]
Run Code Online (Sandbox Code Playgroud)

您可以尝试任何方案,也许它会提高模型的性能.

但是有一件非常重要的事情在他们身上缺失.当你对整个数据进行缩放然后将它们分成训练和测试时,假设你知道测试(看不见的)数据,这在现实世界的情况下是不正确的.并会给你不符合现实世界结果的结果.因为在现实世界中,整个数据将是我们的训练数据.它也可能导致过度拟合,因为模型已经有一些关于测试数据的信息.

因此,在评估机器学习模型的性能时,建议您在对其执行任何操作之前保留测试数据.因为这是我们看不见的数据,所以我们对它一无所知.理想的操作路径就是我回答的那个,即:

1) Divide X into X_train and X_test (same for y)
2) X_train_scaled = scale.fit_transform(X_train) [#Learn the mean and SD of train data]
3) X_test_scaled = scale.transform(X_test) [#Use the mean and SD learned in step2 to convert test data]
4) Use the X_train_scaled for training the model and X_test_scaled in evaluation.
Run Code Online (Sandbox Code Playgroud)

希望对你有意义.