这是一个非常小的sklearn代码片段:
logistic = linear_model.LogisticRegression()
pipe = Pipeline(steps=[
('scaler_2', MinMaxScaler()),
('pca', decomposition.NMF(6)),
('logistic', logistic),
])
from sklearn.cross_validation import train_test_split
Xtrain, Xtest, ytrain, ytest = train_test_split(X, y, test_size=0.2)
pipe.fit(Xtrain, ytrain)
ypred = pipe.predict(Xtest)
我将得到这个错误:
raise ValueError("Negative values in data passed to %s" % whom)
ValueError: Negative values in data passed to NMF (input X)
根据这个问题:使用MinMaxScaler
将测试数据缩放到0和1我知道这是因为
这是因为我的测试数据中的最低值是低于列车数据,其中最小最大标量拟合
但我想知道,这是一个bug吗?MinMaxScaler(所有标量)似乎应该在我做预测之前应用,它不应该依赖于以前拟合的训练数据,我对吗?
或者我如何正确地使用预处理标量与管道?
谢谢。
这不是一个bug。将缩放器添加到管道的主要原因是防止将测试集的信息泄漏到模型中。当你将管道拟合到训练数据时,MinMaxScaler
保持训练数据的最小值和最大值。它将使用这些值来缩放它可能看到的用于预测的任何其他数据。正如您所强调的,这个最小值和最大值不一定是测试数据集的最小值和最大值!因此,当你的测试集的最小值小于训练集的最小值时,你的训练集中可能会有一些负值。你需要一个不给你负值的标量。例如,您可以使用sklearn.preprocessing.StandardScaler
。请确保设置了with_mean = False
参数。这样,它就不会在缩放之前将数据居中,而是将数据缩放到单位方差。
如果你的数据是平稳的,并且采样做得很好,你可以假设你的测试集在很大程度上类似于你的训练集。
因此,除了少数"异常值"之外,您可以期望测试集上的min/max接近训练集上的min/max。
为了减少在测试集上使用MinMaxScaler产生负值的机会,只需将数据缩放到(0,1)范围,但要确保为您的变压器允许一些"安全空间",如下所示:
MinMaxScaler(feature_range=(1,2))