Python 在GridSearch CV之后进行预测时,是否遵循管道步骤

Python 在GridSearch CV之后进行预测时,是否遵循管道步骤,python,scikit-learn,pipeline,gridsearchcv,Python,Scikit Learn,Pipeline,Gridsearchcv,我将GridSearchCV与一个管道结合使用,该管道将标准化作为第一步。我发现使用GridSearchCV的.predict方法预测测试数据集时,结果与手动实现管道步骤时不同。我在下面创建了我的脚本的简化版本,以显示发现的错误有所不同。为了简单起见,每个参数的搜索空间仅包含1个值 我知道这里的差别很小。但在我的原始代码中,这种差异要大得多。因此,我试图理解是什么导致这两种方法之间的差异 初始化数据 import random import numpy as np from sklearn.m

我将GridSearchCV与一个管道结合使用,该管道将标准化作为第一步。我发现使用GridSearchCV的.predict方法预测测试数据集时,结果与手动实现管道步骤时不同。我在下面创建了我的脚本的简化版本,以显示发现的错误有所不同。为了简单起见,每个参数的搜索空间仅包含1个值

我知道这里的差别很小。但在我的原始代码中,这种差异要大得多。因此,我试图理解是什么导致这两种方法之间的差异

初始化数据

import random

import numpy as np
from sklearn.metrics import mean_absolute_error
from sklearn.model_selection import GridSearchCV, KFold
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVR

random.seed(5)
np.random.seed(5)

x_train = np.random.rand(1000,4)
y_train = np.random.rand(1000,1)

x_test = np.random.rand(100,4)
y_test = np.random.rand(100,1)

C_space = 1
epsilon_space = 0.04
gamma_space = 0.001
实施管道

cv_folds = KFold(n_splits=5, shuffle=True)

steps = [
    ('scaler', StandardScaler()), 
    ('svr', SVR(kernel='rbf', gamma=gamma_space, C=C_space, epsilon=epsilon_space))
    ]
pipe = Pipeline(steps, verbose=0)

search_space = [{
        'svr__gamma':[gamma_space],
        'svr__C':[C_space], 
        'svr__epsilon':[epsilon_space]
        }]

mod = GridSearchCV(pipe, search_space,
    scoring='neg_mean_absolute_error', cv=5, verbose=0, return_train_score=True, refit=True)
svr = mod.fit(x_train, y_train)
y_pred = svr.predict(x_test)

error = mean_absolute_error(y_pred, y_test)
手动执行这些步骤

scaler = StandardScaler()
x_train_scaled = scaler.fit_transform(x_train)
x_test_scaled = scaler.fit_transform(x_test)

manual_svr = SVR(kernel='rbf', gamma=gamma_space, C=C_space,
    epsilon=epsilon_space).fit(x_train_scaled, y_train)

y_pred_manual = manual_svr.predict(x_test_scaled)

error_manual = mean_absolute_error(y_pred_manual, y_test)
结果是:

Pipeline error is: 0.23495746730222067
Manual error is: 0.23487379770774958

您正在将
GridSearchCV
中的
StandardScaler
拟合到培训数据中,而您正在重新拟合到测试数据中-将您的“手动”
scaler
拟合到测试数据中。与

scaler = StandardScaler()
x_train_scaled = scaler.fit_transform(x_train)
x_test_scaled = scaler.fit_transform(x_test)
您正在覆盖
缩放器
以适应训练数据
这是而不是使用定标器的目的。将定标器与训练数据相匹配,然后使用此定标器标准化测试数据

让我们将您的输出与它的外观进行比较。首先,让我们在
GridSearchCV
中提取scaler fit,并用它标准化测试数据:

gscv_sclr = mod.best_estimator_.named_steps['scaler']
gscv_test_scld = gscv_sclr.transform(x_test)
如您所见,这不等于手动标准化测试数据:

np.allclose(gscv_test_scld, x_test_scaled)
# Out: False
scaler_new = StandardScaler()
x_train_scaled = scaler_new.fit_transform(x_train)
x_test_scaled_new = scaler_new.transform(x_test)

# and compare it to the gridsearchcv scaler:
np.allclose(gscv_test_scld, x_test_scaled_new)
# Out: True
现在,让我们仅将“手动”标准化器与培训数据相匹配,并使用此标准化器转换测试数据:

np.allclose(gscv_test_scld, x_test_scaled)
# Out: False
scaler_new = StandardScaler()
x_train_scaled = scaler_new.fit_transform(x_train)
x_test_scaled_new = scaler_new.transform(x_test)

# and compare it to the gridsearchcv scaler:
np.allclose(gscv_test_scld, x_test_scaled_new)
# Out: True
哪个是相等的
现在使用此正确标准化的测试集进行预测:

# this refitting is actually not needed. it is simply here for having separate models...
manual_svr_new = SVR(kernel='rbf', gamma=gamma_space, C=C_space,
    epsilon=epsilon_space).fit(x_train_scaled, y_train)

y_pred_manual_new = manual_svr_new.predict(x_test_scaled_new)

error_manual_new = mean_absolute_error(y_pred_manual_new, y_test)

# And test it:
error_manual_new == error
# Out: True
现在你已经得到了你的管道的结果