使用 GridSearchCV 进行目标缩放

Posted

技术标签:

【中文标题】使用 GridSearchCV 进行目标缩放【英文标题】:target scaling using GridSearchCV 【发布时间】:2021-07-12 03:44:05 【问题描述】:

对于超参数调整,我使用 Python 包 sklearn 中的函数 GridSearchCV。我测试的一些模型需要特征缩放(例如支持向量回归 - SVR)。最近,在 Udemy 的课程Machine Learning A-Z™: Hands-On Python & R In Data Science中,讲师提到对于 SVR,目标也应该进行缩放(如果它不是二进制的)。考虑到这一点,我想知道目标是否在GridSearchCV 执行的交叉验证过程的每次迭代中也被缩放,或者是否只有特征被缩放。请参阅下面的代码,它说明了我用于对需要缩放训练集的估计器进行超参数调整的正常过程:

from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import GridSearchCV
from sklearn.svm import SVR
    
def SVRegressor(**kwargs):
   '''contruct a pipeline to perform SVR regression'''
   return make_pipeline(StandardScaler(), SVR(**kwargs))

params = 'svr__kernel': ["poly", "rbf"]
grid_search = GridSearchCV(SVRegressor(), params)
grid_search.fit(X, y)

我知道我可以简单地扩展 Xy 先验,然后从管道中删除 StandardScaler。但是,我想在测试多个模型的代码管道中实现这种方法,其中一些需要缩放,而另一些不需要。这就是为什么我想知道GridSearchCV 如何在后台处理缩放。

【问题讨论】:

【参考方案1】:

不,它不会缩放目标,如果您查看 make_pipeline,它只是将 X 和 y 参数传递给您的转换器,而 StandardScaler() 对您的 y 没有任何作用:

def _fit_transform_one(transformer,
                       X,
                       y,
                       weight,
                       message_clsname='',
                       message=None,
                       **fit_params):
    """
    Fits ``transformer`` to ``X`` and ``y``. The transformed result is returned
    with the fitted transformer. If ``weight`` is not ``None``, the result will
    be multiplied by ``weight``.
    """
    with _print_elapsed_time(message_clsname, message):
        if hasattr(transformer, 'fit_transform'):
            res = transformer.fit_transform(X, y, **fit_params)
        else:
            res = transformer.fit(X, y, **fit_params).transform(X)

    if weight is None:
        return res, transformer
    return res * weight, transformer

你可以在 StandardScaler() 上试试这个,你会发现它对 y 没有任何作用:

np.random.seed(111)
X = np.random.normal(5,2,(100,3))
y = np.random.normal(5,2,100)

res = StandardScaler().fit_transform(X=X,y=y)
res.shape
(100, 3)

res.mean(axis=0)
array([1.01030295e-15, 4.39648318e-16, 8.91509089e-16])

res.std(axis=0)
array([1., 1., 1.])

你也可以查看你的 gridsearchcv 的结果:

SVRegressor = make_pipeline(StandardScaler(), SVR())
params = 'svr__kernel': ["poly", "rbf"]
grid_search = GridSearchCV(SVRegressor, params,
scoring='neg_mean_absolute_error')

在未缩放的 y 上,您会看到在未缩放的数据上,您的负平均绝对误差与您的标准差大致相同(我在示例中使用了 2):

grid_search.fit(X, y)

grid_search.cv_results_['mean_test_score']
array([-2.01029707, -1.88779205])

在缩放 y 上,我们的标准差为 1,您可以看到误差在 -1 左右:

y_scaled = StandardScaler().fit_transform(y.reshape(-1,1)).ravel()
grid_search.fit(X, y_scaled)

grid_search.cv_results_['mean_test_score']
array([-1.00585999, -0.88330208])

【讨论】:

以上是关于使用 GridSearchCV 进行目标缩放的主要内容,如果未能解决你的问题,请参考以下文章

GridSearchCV 参数不能改善分类

将目标/标签数据传递给 Scikit-learn GridSearchCV 的 OneClassSVM 拟合方法

如何使用 GridSearchCV 在嵌套管道中测试预处理组合?

自定义 k-means 聚类 GridSearchCV

Groupby 在一列 pandas 数据帧上,并使用 GridsearchCv 使用通用 sklearn 管道训练每个组的特征和目标 (X, y)

带有管道和 GridSearchCV 的 StandardScaler