【问题标题】:Python Pipeline Custom TransformerPython 管道自定义转换器
【发布时间】:2020-03-08 10:29:25
【问题描述】:

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

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

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   

如何将分类/连续特征列表传递给转换器,以便它缩放适当的特征?还是以某种方式在转换器内部编写特征类型检查代码更好?

【问题讨论】:

    标签: python pipeline transformer


    【解决方案1】:

    基本上,您需要在管道中再迈出一步,使用继承自 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
    )
    

    【讨论】:

    • 如果我正确理解您的答案,我会通过在进入管道之前传入连续特征列表来创建原始数据框的子集,然后在您拥有“选择器”的管道中使用该数据框' 这就是在 DFStandardScaler() 中处理的内容?我看到你用 pipe2 建立了一个特征联合来处理分类。在#some other step退出featureunion之后,我需要一个将管道2中的已处理分类和管道1中的连续分类再次连接到单个数据帧中的过程?对吗?
    • 没错!您唯一不需要做的是 concat 层,它由 make Union 处理,大多数 sklearn 模型都可以很好地处理输出
    • 还有一件事。我按照你的建议做了。我现在正在运行 pipe1(连续功能)。当我运行 pipeline.fit(X) 时,X 是上面的数据框,我得到以下结果:Pipeline(memory=None, steps=[('column_selector', column_selector(columns=None)), ('scaler', DFStandardScaler())])。它似乎无法识别我传递给column_selector 的列列表?
    • 想通了。我需要做一个transform。感谢您的帮助!
    • 现在看到了!很高兴你想通了,基本上你想在整个管道上运行fit_transform(),无论是逐步还是端到端
    猜你喜欢
    • 2018-11-04
    • 2016-04-16
    • 2020-06-17
    • 2017-12-24
    • 2017-05-14
    • 2019-11-20
    • 2019-09-30
    • 1970-01-01
    • 2014-10-21
    相关资源
    最近更新 更多