【问题标题】:How to apply StandardScaler in Pipeline in scikit-learn (sklearn)?如何在 scikit-learn (sklearn) 的 Pipeline 中应用 StandardScaler?
【发布时间】:2018-12-29 18:16:18
【问题描述】:

在下面的例子中,

pipe = Pipeline([
        ('scale', StandardScaler()),
        ('reduce_dims', PCA(n_components=4)),
        ('clf', SVC(kernel = 'linear', C = 1))])

param_grid = dict(reduce_dims__n_components=[4,6,8],
                  clf__C=np.logspace(-4, 1, 6),
                  clf__kernel=['rbf','linear'])

grid = GridSearchCV(pipe, param_grid=param_grid, cv=3, n_jobs=1, verbose=2)
grid.fit(X_train, y_train)
print(grid.score(X_test, y_test))

我正在使用StandardScaler(),这也是将其应用于测试集的正确方法吗?

【问题讨论】:

    标签: python scikit-learn


    【解决方案1】:

    是的,这是正确的方法,但您的代码中有一个小错误。让我为您分解一下。

    当您使用StandardScaler 作为Pipeline 中的一个步骤时,scikit-learn 将在内部为您完成这项工作。


    发生的事情可以描述如下:

    • 步骤0:根据您在GridSearchCV中指定的cv参数将数据拆分为TRAINING data和TEST data。
    • 第 1 步:将scaler 安装在TRAINING data 上
    • 第 2 步:scaler 转换 TRAINING data
    • 第 3 步:使用转换后的TRAINING data 拟合/训练模型
    • 第四步:scaler 用于转换TEST data
    • 第五步:训练模型predict使用transformed TEST data

    注意:您应该使用grid.fit(X, y) 和不 grid.fit(X_train, y_train),因为GridSearchCV 会自动将数据拆分为训练和测试数据(这在内部发生)。


    使用如下内容:

    from sklearn.pipeline import Pipeline
    from sklearn.svm import SVC
    from sklearn.preprocessing import StandardScaler
    from sklearn.model_selection import GridSearchCV
    from sklearn.decomposition import PCA
    
    pipe = Pipeline([
            ('scale', StandardScaler()),
            ('reduce_dims', PCA(n_components=4)),
            ('clf', SVC(kernel = 'linear', C = 1))])
    
    param_grid = dict(reduce_dims__n_components=[4,6,8],
                      clf__C=np.logspace(-4, 1, 6),
                      clf__kernel=['rbf','linear'])
    
    grid = GridSearchCV(pipe, param_grid=param_grid, cv=3, n_jobs=1, verbose=2, scoring= 'accuracy')
    grid.fit(X, y)
    print(grid.best_score_)
    print(grid.cv_results_)
    

    运行此代码后(当您调用grid.fit(X, y) 时),您可以在 grid.fit() 返回的结果对象中访问网格搜索的结果。 best_score_ 成员提供对优化过程中观察到的最佳分数的访问,best_params_ 描述了实现最佳结果的参数组合。


    重要编辑 1:如果您想保留原始数据集的验证数据集,请使用:

    X_for_gridsearch, X_future_validation, y_for_gridsearch, y_future_validation 
        = train_test_split(X, y, test_size=0.15, random_state=1)
    

    然后使用:

    grid = GridSearchCV(pipe, param_grid=param_grid, cv=3, n_jobs=1, verbose=2, scoring= 'accuracy')
    grid.fit(X_for_gridsearch, y_for_gridsearch)
    

    【讨论】:

    • 没有。如果你在整个数据集上GridSearchCV,那么你已经在整个数据集上训练了你的超参数,并且不再有一个测试集来验证你的模型。
    • @seralouk,我的意思是你也可以为.predict() 添加一行吗?如果我执行grid.predict(X_test) 之类的操作,它会在不需要再次指定 StandardScalar 的情况下工作吗?
    • 我认为原始发布者想知道是否在整个交叉验证之后调用 grid.predict(X_test),缩放仍然应用于 X_test?如果是这样,什么类型的缩放,使用来自 X_train 的均值/标准或者是基于 X_Test 计算的新均值/标准。我想知道同样的事情。感谢任何帮助。
    • 正如已经指出的那样,您仍然应该分离一个测试集并将其保存在“保险库中”,只将训练数据传递给GridSearchCV:您不想调整整个数据集的超参数因为这样做你没有真正的测试集来计算实际的经验误差。
    • @serafeim 这确实是一个很好的答案。当我通常使用 StandardScaler 时,我使用 StandardScaler 的两个不同实例来缩放我的数据。我总是使用缩放器来适应 X_train 和一个适应 y_train 然后我使用每个实例分别转换 X_test 和 y_test 以避免任何异常值等被“泄漏”到训练中。有没有办法使用管道来做到这一点,甚至是否需要额外的缩放器?
    【解决方案2】:

    快速回答:您的方法是正确的。


    虽然上面的答案很好,但我还是想指出一些微妙之处:

    best_score_ [1] 是最好的交叉验证指标,而不是模型 [2] 的泛化性能。要评估找到的最佳参数的泛化程度,您应该像之前所做的那样调用测试集上的分数。因此需要先将数据拆分为训练集和测试集,只在X_train, y_train 中拟合网格搜索,然后用X_test, y_test [2] 对其进行评分。


    深入了解:

    将数据分成 训练集、验证集和测试集三部分是防止网格搜索过程中参数过拟合的一种方法.另一方面,GridSearchCV 在训练集中使用交叉验证,而不是同时拥有训练和验证集,但这不会替换测试集。这可以在 [2] 和 [3] 中验证。


    参考资料:

    [1]GridSearchCV

    [2]Introduction to Machine Learning with Python

    [3]3.1 Cross-validation: evaluating estimator performance

    【讨论】:

      猜你喜欢
      • 2019-08-11
      • 2017-10-04
      • 2022-01-12
      • 2018-11-04
      • 2016-12-08
      • 2016-10-07
      • 2021-10-17
      • 2017-07-18
      • 2020-09-25
      相关资源
      最近更新 更多