通过 Pipeline sklearn (Python) 使用多个自定义类

Posted

技术标签:

【中文标题】通过 Pipeline sklearn (Python) 使用多个自定义类【英文标题】:Using multiple custom classes with Pipeline sklearn (Python) 【发布时间】:2017-09-15 21:30:52 【问题描述】:

我尝试为学生编写有关 Pipeline 的教程,但我阻止了。我不是专家,但我正在努力改进。所以谢谢你的宽容。 事实上,我尝试在管道中执行几个步骤来为分类器准备数据框:

第 1 步:数据帧描述 第 2 步:填充 NaN 值 第 3 步:将分类值转换为数字

这是我的代码:

class Descr_df(object):

    def transform (self, X):
        print ("Structure of the data: \n ".format(X.head(5)))
        print ("Features names: \n ".format(X.columns))
        print ("Target: \n ".format(X.columns[0]))
        print ("Shape of the data: \n ".format(X.shape))

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

class Fillna(object):

    def transform(self, X):
        non_numerics_columns = X.columns.difference(X._get_numeric_data().columns)
        for column in X.columns:
            if column in non_numerics_columns:
                X[column] = X[column].fillna(df[column].value_counts().idxmax())
            else:
                 X[column] = X[column].fillna(X[column].mean())            
        return X

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

class Categorical_to_numerical(object):

    def transform(self, X):
        non_numerics_columns = X.columns.difference(X._get_numeric_data().columns)
        le = LabelEncoder()
        for column in non_numerics_columns:
            X[column] = X[column].fillna(X[column].value_counts().idxmax())
            le.fit(X[column])
            X[column] = le.transform(X[column]).astype(int)
        return X

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

如果我执行第 1 步和第 2 步或第 1 步和第 3 步,它会起作用,但如果我同时执行第 1、2 和 3 步。我有这个错误:

pipeline = Pipeline([('df_intropesction', Descr_df()), ('fillna',Fillna()), ('Categorical_to_numerical', Categorical_to_numerical())])
pipeline.fit(X, y)
AttributeError: 'NoneType' object has no attribute 'columns'

【问题讨论】:

可能其中一些没有:Xy。请全栈。 【参考方案1】:

出现此错误是因为在管道中,第一个估计器的输出转到第二个,然后第二个估计器的输出转到第三个,依此类推...

来自documentation of Pipeline:

一个接一个地拟合所有的变换并变换数据, 然后使用最终估计器拟合转换后的数据。

因此,对于您的管道,执行步骤如下:

    Descr_df.fit(X) -> 不做任何事情并返回自我 newX = Descr_df.transform(X) -> 应返回一些值以分配给 newX,该值应传递给下一个估算器,但您的定义不返回任何内容(仅打印)。所以 None 被隐式返回 Fillna.fit(newX) -> 什么都不做,返回自我 Fillna.transform(newX) -> 调用 newX.columns。但是来自 step2 的 newX=None。因此出现错误。

解决方案:更改 Descr_df 的转换方法,以原样返回数据帧:

def transform (self, X):
    print ("Structure of the data: \n ".format(X.head(5)))
    print ("Features names: \n ".format(X.columns))
    print ("Target: \n ".format(X.columns[0]))
    print ("Shape of the data: \n ".format(X.shape))
    return X

建议:让您的类继承自 scikit 中的 Base Estimator 和 Transformer 类,以确认良好做法。

即将class Descr_df(object)更改为class Descr_df(BaseEstimator, TransformerMixin),将Fillna(object)更改为Fillna(BaseEstimator, TransformerMixin)等等。

有关 Pipeline 中自定义类的更多详细信息,请参阅此示例:

http://scikit-learn.org/stable/auto_examples/hetero_feature_union.html#sphx-glr-auto-examples-hetero-feature-union-py

【讨论】:

我会看看,让你知道。您的回答似乎非常有趣和有帮助。谢谢!! @JeremieGuez 试试这个解决方案,如果它适合你,请考虑接受这个答案 看起来不错!!谢谢 我想在我的管道末尾(在我的随机森林分类器之后)添加一个性能指标(只是一个 auc),但我有一个 TypeError:如果没有指定评分,则传递的估计器应该有一种“评分”方法。如果更好的话,我可以打开另一个帖子... @JeremieGuez 我无法理解。您能否发布一个包含所有详细信息的新问题。

以上是关于通过 Pipeline sklearn (Python) 使用多个自定义类的主要内容,如果未能解决你的问题,请参考以下文章

从 sklearn.pipeline.Pipeline 获取转换器结果

从 sklearn 中的 Pipeline 对象返回系数

sklearn.pipeline.Pileline

如何使用 sklearn.pipeline 转换新数据

sklearn:无法使 OneHotEncoder 与 Pipeline 一起使用

Sklearn ColumnTransformer + Pipeline = TypeError