具有多个转换和估计器的 Sklearn 管道

Sklearn Pipeline with multiple transforms and estimators

我正在尝试使用 Pipeline 构建 GridSearchCV,我想同时测试转换器和估算器。 有没有更简洁的方法呢?

pipeline = Pipeline([
    ('imputer', SimpleImputer()),
    ('scaler', StandardScaler()),
    ('pca',  PCA()), 
    ('clf', KNeighborsClassifier())
])

parameters = [{
        'imputer': (SimpleImputer(), ), 
        'imputer__strategy': ('median', 'mean'),
        'pca__n_components': (10, 20), 
        'clf': (LogisticRegression(),),
        'clf__C': (1,10)
    }, {
        'imputer': (SimpleImputer(), ), 
        'imputer__strategy': ('median', 'mean'),
        'pca__n_components': (10, 20), 
        'clf': (KNeighborsClassifier(),),
        'clf__n_neighbors': (10, 25),
    }, {
        'imputer': (KNNImputer(), ), 
        'imputer__n_neighbors': (5, 10),
        'pca__n_components': (10, 20), 
        'clf': (LogisticRegression(),),
        'clf__C': (1,10)
    }, {
        'imputer': (KNNImputer(), ), 
        'imputer__n_neighbors': (5, 10),
        'pca__n_components': (10, 20), 
        'clf': (KNeighborsClassifier(),),
        'clf__n_neighbors': (10, 25),
    }]
grid_search = GridSearchCV(estimator=pipeline, param_grid=parameters)

除了有 4 个参数块,我想声明我想使用相应参数和 2 个分类器测试的 2 个插补方法。并且不给 pca__n_components 贴花 4 次。

当您获得相互依赖的超参数时,参数网格方法会变得很麻烦。有几种方法可以获得您需要的东西。

嵌套网格搜索

GridSearchCV(
    estimator=GridSearchCV(estimator=pipeline, param_grid=imputer_grid),
    param_grid=estimator_grid,
)

对于每个估计器候选者,这对输入者候选者运行网格搜索;最好的 imputer 用于估计器,然后比较 estimators-with-best-imputers。

这里的主要缺点是内部搜索被克隆到每个估计器候选者,因此您无法访问 non-winning 估计器的输入器的 cv_results_

python 生成(部分)网格

ParameterGrid,由 GridSearchCV 内部使用,主要是 itertools.product 的包装。所以我们可以使用 itertools 自己来创建(块)网格。例如。我们可以创建您编写的列表,但重复代码较少:

import itertools

imputers = [{
    'imputer': (SimpleImputer(), ), 
    'imputer__strategy': ('median', 'mean'),
},
{
    'imputer': (KNNImputer(), ), 
    'imputer__n_neighbors': (5, 10),
}]
models = [{
    'clf': (LogisticRegression(),),
    'clf__C': (1,10),
},
{
    'clf': (KNeighborsClassifier(),),
    'clf__n_neighbors': (10, 25),
}]
pcas = [{'pca__n_components': (10, 20),}]
parameters = [
    {**imp, **pca, **model}  # in py3.9 the slicker notation imp | pca | model works
    for imp, pca, model in itertools.product(imputers, pca, models)
]  # this should give the same as your hard-coded list-of-dicts