向ColumnTransformer pipelin添加get_feature_名称

2024-10-01 15:36:47 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试创建一个sklearn.compose.ColumnTransformer管道,用于转换分类和连续输入数据:

import pandas as pd

from sklearn.base import TransformerMixin, BaseEstimator
from sklearn.preprocessing import OneHotEncoder, FunctionTransformer
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer, make_column_transformer
from sklearn.impute import SimpleImputer

df = pd.DataFrame(
    {
            'a': [1, 'a', 1, np.nan, 'b'],
            'b': [1, 2, 3, 4, 5],
            'c': list('abcde'),
            'd': list('aaabb'),
            'e': [0, 1, 1, 0, 1],
    }
)

for col in df.select_dtypes('object'):
    df[col] = df[col].astype(str)

categorical_columns = list('acd')
continuous_columns = list('be')

categorical_transformer = OneHotEncoder(sparse=False, handle_unknown='ignore')
continuous_transformer = 'passthrough'

column_transformer = ColumnTransformer(
    [
        ('categorical', categorical_transformer, categorical_columns),
        ('continuous', continuous_transformer, continuous_columns),
    ]
    ,
    sparse_threshold=0.,
    n_jobs=-1
)

X = column_transformer.fit_transform(df)

我想访问此转换管道创建的功能名称,因此我尝试以下操作:

^{pr2}$

这引发了:

NotImplementedError: get_feature_names is not yet supported when using a 'passthrough' transformer.

由于技术上我没有对列be做任何操作,所以技术上我可以在对所有其他特性进行一次热编码后将它们附加到X上,但是有没有什么方法可以使用scikit基类之一(例如TransformerMixinBaseEstimator,或者FunctionTransformer)来添加到这个管道中,这样我就可以以一种非常友好的方式获取连续的特性名称?在

可能是这样的:

class PassthroughTransformer(FunctionTransformer, BaseEstimator):
    def fit(self):
        return self
    def transform(self, X)
        self.X = X
        return X
    def get_feature_names(self):
        return self.X.values.tolist()

continuous_transformer = PassthroughTransformer()

column_transformer = ColumnTransformer(
    [
        ('categorical', categorical_transformer, categorical_columns),
        ('continuous', continuous_transformer, continuous_columns),
    ]
    ,
    sparse_threshold=0.,
    n_jobs=-1
)

X = column_transformer.fit_transform(df)

但这引发了一个例外:

TypeError: Cannot clone object '<__main__.PassthroughTransformer object at 0x1132ddf60>' (type <class '__main__.PassthroughTransformer'>): it does not seem to be a scikit-learn estimator as it does not implement a 'get_params' methods.

Tags: columnsfromimportselfdf管道columnsklearn
1条回答
网友
1楼 · 发布于 2024-10-01 15:36:47

这里有多个问题:

  1. 无法克隆对象错误是由并行处理引起的:

    默认情况下,scikit-learn克隆(它使用pickle)所提供的转换器和估计器(FeatureUnion、ColumnTransformer等)或交叉验证(cross_val_scoreGridSearchCV等)工作时提供的转换器和估计器。在

    现在,您已经在ColumnTransformer中指定了n_jobs=-1,这在代码中引入了多处理。Python内置的pickling不能很好地用于多处理。所以才有了错误。在

    选项

    1. n_jobs = 1设置为不使用多处理。仍然需要根据第2点和第3点更正代码。

    2. 如果要使用多处理,那么最简单的解决方案是在单独的文件(模块)中定义自定义类,并将其导入主文件中。像这样:

    在同一文件夹中创建一个名为custom的新文件_变形金刚.py内容:

    from sklearn.base import TransformerMixin, BaseEstimator
    
    # Changed the base classes here, see Point 3
    class PassthroughTransformer(BaseEstimator, TransformerMixin):
    
        # I corrected the `fit()` method here, it should take X, y as input
        def fit(self, X, y=None):
            return self
    
        def transform(self, X):
            self.X = X
            return X
    
        # I have corrected the output here, See point 2
        def get_feature_names(self):
            return self.X.columns.tolist()
    

    现在在主文件中,执行以下操作:

    ^{pr2}$

    有关详细信息,请参阅以下问题:

  2. 返回self.X.values.tolist()

    这里的X是一个PandasDataFrame,因此X.values.tolist()将返回指定列的实际数据,而不是列名。所以即使你解决了第一个错误,你也会得到错误。更正为:

    return self.X.columns.tolist()
    
  3. 次要)类继承:

    您将PassthroughTransformer定义为:

    PassthroughTransformer(FunctionTransformer, BaseEstimator)
    

    FunctionTransformer已经从BaseEstimator继承,所以我认为没有必要从BaseEstimator继承。您可以通过以下方式进行更改:

    class PassthroughTransformer(FunctionTransformer):
    
                           OR
    # Standard way 
    class PassthroughTransformer(BaseEstimator, TransformerMixin):
    

希望这有帮助。在

相关问题 更多 >

    热门问题