Keras Regression using Scikit Learn StandardScaler with Pipeline and without Pipeline
Posted
技术标签:
【中文标题】Keras Regression using Scikit Learn StandardScaler with Pipeline and without Pipeline【英文标题】: 【发布时间】:2017-10-04 15:07:50 【问题描述】:我正在比较使用 Scikit-Learn StandardScaler
的两个关于 KerasRegressor
的程序的性能:一个使用 Scikit-Learn Pipeline
的程序和一个没有 Pipeline
的程序。
方案一:
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)
方案二:
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)
我的问题是程序 1 的 R2 分数可以达到 0.98(平均 3 次试验),而程序 2 的 R2 分数只能达到 0.84(平均 3 次试验)。谁能解释这两个程序之间的区别?
【问题讨论】:
看来你是独立地重新缩放每个数据集,你应该使用X_train = scale.fit_transform(X_train)
和X_test = scale.transform(X_test)
【参考方案1】:
在第二种情况下,您同时在X_train
和X_test
上调用StandardScaler.fit_transform()
。它的错误用法。
您应该在X_train
上致电fit_transform()
,然后在X_test
上仅致电transform()
。因为这就是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)
在测试数据上调用 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.
场景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]
您可以尝试任何场景,也许它会提高模型的性能。
但是其中缺少一件非常重要的事情。当您对整个数据进行缩放然后将它们分成训练和测试时,假设您知道测试(未见过的)数据,这在现实世界的情况下是不正确的。并且会给你结果,这与现实世界的结果不相符。因为在现实世界中,所有的数据都是我们的训练数据。这也可能导致过拟合,因为模型已经有一些关于测试数据的信息。
因此,在评估机器学习模型的性能时,建议您先将测试数据放在一边,然后再对其进行任何操作。因为这是我们看不见的数据,我们对此一无所知。所以理想的操作路径就是我回答的那个,即:
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.
希望对你有意义。
【讨论】:
亲爱的 Vivek:我听从你关于 fit_transform(X_train) 和 transform(X_test) 的建议,分数确实上升了。谢谢。但是,我在这里有两个问题。 (1) 按照datascience.stackexchange.com/questions/13350/… 下的示例,我在 X_train 和 X_test 上都使用了 fit_transform()。看起来那个程序也会有类似的问题,对吧? (2) “fit_transform(X), then transform(X_train) and transform(X_test), where X is equal to X_train plus X_test”效果更好吗? Vivek:感谢您的 cmets。我现在对这些功能有了更好的了解。 @Frank 如果我的回答对您有所帮助并且您的问题得到解决,那么请考虑将其标记为已接受。以上是关于Keras Regression using Scikit Learn StandardScaler with Pipeline and without Pipeline的主要内容,如果未能解决你的问题,请参考以下文章
Linear Regression Using Gradient Descent 代码实现
Logistic Regression Using Gradient Descent -- Binary Classification 代码实现
Theano-Deep Learning Tutorials 笔记:Classifying MNIST digits using Logistic Regression