首页 > 解决方案 > Python 管道自定义转换器

问题描述

我正在尝试编写一个自定义转换器,以在管道中使用来预处理数据。

这是我正在使用的代码(来源 - 不是我写的)。它接收一个数据框,缩放特征,并返回一个数据框:

class DFStandardScaler(BaseEstimator,TransformerMixin):

    def __init__(self):

        self.ss = None

    def fit(self,X,y=None):

        self.ss = StandardScaler().fit(X)
        return self

    def transform(self, X):

        Xss = self.ss.transform(X)
        Xscaled = pd.DataFrame(Xss, index=X.index, columns=X.columns)
        return Xscaled

我有同时具有分类和连续特征的数据。显然,转换器不会转换分类特征(“性别”)。当我将此管道与下面的数据框配合使用时,它会引发错误,因为它正在尝试缩放“性别”中的分类标签:

     sex  length  diameter  height  whole_weight  shucked_weight  \
0      M   0.455     0.365   0.095        0.5140          0.2245   
1      M   0.350     0.265   0.090        0.2255          0.0995   
2      F   0.530     0.420   0.135        0.6770          0.2565   
3      M   0.440     0.365   0.125        0.5160          0.2155   
4      I   0.330     0.255   0.080        0.2050          0.0895   
5      I   0.425     0.300   0.095        0.3515          0.1410   

如何将分类/连续特征列表传递给转换器,以便它缩放正确的特征?或者以某种方式在变压器内部编码特征类型检查是否更好?

标签: pythonpipelinetransformer

解决方案


基本上,您需要在管道中执行另一个步骤,其中一个类似的类继承自BaseEstimatorTransformerMixin

class ColumnSelector(BaseEstimator,TransformerMixin):
    def __init__(self, columns: list):
        self.cols = columns

    def fit(self,X,y=None):
        return self

    def transform(self, X, y=None):
        return X.loc[:, self.cols]

然后在你的主要管道看起来像这样:

selector = ColumnSelector(['length', 'diameter', 'height', 'whole_weight', 'shucked_weight'])
pipe = pipeline.make_pipeline(
    selector,
    DFStandardScaler()
)

pipe2 = pipeline.make_pipeline(#some steps for the sex column)

full_pipeline = pipeline.make_pipeline(
    pipeline.make_union(
        pipe,
        pipe2
    ),
    #some other step
)

推荐阅读