machine-learning - 如果我们在管道中包含 Transformer,scikit-learn 的 `cross_val_score` 和 `GridsearchCV` 的 k 倍交叉验证分数是否有偏差?

标签 machine-learning scikit-learn pipeline cross-validation grid-search

应使用 StandardScaler 等数据预处理器来拟合变换训练集,而仅变换(不拟合)测试集。我希望相同的拟合/转换过程适用于用于调整模型的交叉验证。但是,我发现 cross_val_scoreGridSearchCV 使用预处理器来 fit_transform 整个训练集(而不是 fit_transform inside_train 集,并转换 inside_validation 集)。我相信这人为地消除了 inner_validation 集中的方差,这使得 cv 分数(用于通过 GridSearch 选择最佳模型的指标)产生偏差。这是一个问题还是我实际上错过了什么?

为了演示上述问题,我使用 Kaggle 的威斯康星州乳腺癌(诊断)数据集尝试了以下三个简单的测试用例。

  1. 我特意使用 StandardScaler() 来拟合和变换整个 X
X_sc = StandardScaler().fit_transform(X)
lr = LogisticRegression(penalty='l2', random_state=42)
cross_val_score(lr, X_sc, y, cv=5)
  • 我将 SC 和 LR 包含在 Pipeline 中并运行 cross_val_score
  • pipe = Pipeline([
        ('sc', StandardScaler()),
        ('lr', LogisticRegression(penalty='l2', random_state=42))
    ])
    cross_val_score(pipe, X, y, cv=5)
    
  • 与 2 相同,但使用 GridSearchCV
  • pipe = Pipeline([
        ('sc', StandardScaler()),
        ('lr', LogisticRegression(random_state=42))
    ])
    params = {
        'lr__penalty': ['l2']
    }
    gs=GridSearchCV(pipe,
    param_grid=params, cv=5).fit(X, y)
    gs.cv_results_
    

    它们都产生相同的验证分数。 [0.9826087、0.97391304、0.97345133、0.97345133、0.99115044]

    最佳答案

    不,sklearn 不会对整个数据集执行 fit_transform

    为了检查这一点,我对 StandardScaler 进行了子类化,以打印发送给它的数据集的大小。

    class StScaler(StandardScaler):
        def fit_transform(self,X,y=None):
            print(len(X))
            return super().fit_transform(X,y)
    

    如果您现在替换代码中的 StandardScaler,您会发现第一种情况下传递的数据集大小实际上更大。

    但是为什么准确度保持完全相同呢?我认为这是因为 LogisticRegression 对特征尺度不是很敏感。如果我们使用对规模非常敏感的分类器(例如 KNeighborsClassifier),您会发现两种情况之间的准确性开始变化。

    X,y = load_breast_cancer(return_X_y=True)
    X_sc = StScaler().fit_transform(X)
    lr = KNeighborsClassifier(n_neighbors=1)
    cross_val_score(lr, X_sc,y, cv=5)
    

    输出:

    569
    [0.94782609 0.96521739 0.97345133 0.92920354 0.9380531 ]
    

    还有第二种情况,

    pipe = Pipeline([
        ('sc', StScaler()),
        ('lr', KNeighborsClassifier(n_neighbors=1))
    ])
    print(cross_val_score(pipe, X, y, cv=5))
    

    输出:

    454
    454
    456
    456
    456
    [0.95652174 0.97391304 0.97345133 0.92920354 0.9380531 ]
    

    准确性方面变化不大,但仍然发生了变化。

    关于machine-learning - 如果我们在管道中包含 Transformer,scikit-learn 的 `cross_val_score` 和 `GridsearchCV` 的 k 倍交叉验证分数是否有偏差?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57651455/

    相关文章:

    machine-learning - "learning rate warm-up"是什么意思?

    amazon-web-services - 如何将输入传递到 CloudFormation 中 Step Function 目标的事件规则?

    MIPS流水线时序图

    python - Scikit-learn 管道中的 Keras 模型与早期停止

    python - 处理 sklearn.tree.DecisionTreeClassifier 中的连续变量

    r - 机器学习中的评估指标

    python - 从 OpenCV 将数据加载到 CNN

    python - 导入错误 : cannot import name 'StratifiedGroupKFold' from 'sklearn.model_selection'

    python - 堆叠两个不同维度的稀疏矩阵

    python - 尝试导入 autosklearn 时 Colab 出错