sklearn - 如何创建顺序管道

数据挖掘 Python scikit-学习 数据插补 管道
2022-02-23 07:27:43

更新:本文中的示例已更新

在之前的 SO 帖子中没有得到明确的答案后,我在这里重新发布了这个问题

我正在寻找帮助使用 sklearn 的 ColumnTransformer 函数构建数据预处理管道的帮助,其中一些功能是按顺序进行的预处理。我很清楚如何为不同的功能子集构建单独的管道。例如,我的管道可能看起来像这样:

from sklearn.compose import ColumnTransformer 
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import Normalizer

ColumnTransformer(remainder='passthrough',
                  transformers=[
                              ('num_impute', SimpleImputer(strategy='median'), ['feat_1', 'feat_2'])
                                ('Std', StandardScaler(), ['feat_3', 'feat_4']),
                                ('Norm', Normalizer(), ['feat_5', 'feat_6']),
                                ])

请注意,每个变压器都提供了一组独特的功能。

我遇到的问题是如何对相同的特征(转换和特征的不同组合)应用顺序处理。例如,

ColumnTransformer(remainder='passthrough',
                  transformers=[
                              ('num_impute', SimpleImputer(strategy='median'), ['feat_1', 'feat_2', , 'feat_5'])
                              ('Std', StandardScaler(), ['feat_1', 'feat_2','feat_3', 'feat_4', 'feat_6']),
                              ('Norm', Normalizer(), ['feat_1', 'feat_6'])

                                ])

请注意,feat_1 被提供给三个转换,feat_2 被提供给两个转换器(impute 和 Std),feat_6 被提供给两个转换器(Std 和 Norm)

像这样的管道将为feat_2 和feat_3 提供两个重复的列,为feat_1 提供三个重复的列。为每个转换/功能组合构建单独的管道是不可扩展的。

2个回答

当您想要进行顺序转换时,您应该使用Pipeline.

imp_std = Pipeline(
    steps=[
        ('impute', SimpleImputer(strategy='median')),
        ('scale', StandardScaler()),
    ]
)

ColumnTransformer(
    remainder='passthrough',
    transformers=[
        ('imp_std', imp_std, ['feat_1', 'feat_2']),
        ('std', StandardScaler(), ['feat_3']),
    ]
)

或者

imp = ColumnTransformer(
    remainder='passthrough',
    transformers=[
        ('imp', SimpleImputer(strategy='median'), ['feat_1', 'feat_2']),
    ]
)

Pipeline(
    steps=[
        ('imp', imp),
        ('std', StandardScaler()),
    ]
)

一种方法是为每种数据类型创建单独的预处理步骤,最常见的情况是您有分类变量和连续变量

from sklearn.pipeline import Pipeline
from sklearn.compose import make_column_transformer
from sklearn.compose import make_column_selector as selector
from sklearn.linear_model import LogisticRegression

cont_prepro = Pipeline([("imputer",SimpleImputer(strategy = "median")),("scaler",StandarScaler())])

cat_prepro = Pipeline([("imputer",SimpleImputer(strategy = "most_frequent")),("encoder",OneHotEncoder(handle_unknown = "ignore"))])

preprocessing = make_column_transformer((cont_prepro,selector(dtype_exclude = "object")),(cat_prepro,selector(dtype_include = "object"))

pipe = Pipeline([("preprocessing",preprocessing),("model",LogisticRegression())])

如果您想通过列表而不是类型来分隔每个步骤的功能,您应该创建一个包含特定列的列表,就像您在示例中所做的那样,并删除选择器部分。

在你的情况下:

pipe_one = Pipeline([("num_impute",SimpleImputer(strategy='median')),('Std', StandardScaler())])

preprocessing = make_column_transformer((pipe_one,["feat_1","feat_2"]),remainder='passthrough')

pipe = Pipeline([("preprocessing",preprocessing),("model",LogisticRegression())])