当transformer包含嵌入式管道时,如何从ELI5中获取功能名称

2024-04-20 15:48:11 发布

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

ELI5库提供函数transform_feature_names来检索sklearn转换器输出的功能名称。{a3}表示,当转换器包含嵌套管道时,该函数可以开箱即用

我试图让函数在answer to SO 57528350中的示例的简化版本上工作。我的简化示例不需要Pipeline,但在现实生活中,我需要它来向categorical_transformer添加步骤,并且我还希望向ColumnTransformer添加转换器

import eli5
import pandas as pd
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder, StandardScaler

X_train = pd.DataFrame({'age': [23, 12, 12, 18],
                        'gender': ['M', 'F', 'F', 'F'],
                        'income': ['high', 'low', 'low', 'medium'],
                        'y': [0, 1, 1, 1]})

categorical_features = ['gender', 'income']
categorical_transformer = Pipeline(
    steps=[('onehot', OneHotEncoder(handle_unknown='ignore'))])

transformers=[('categorical', categorical_transformer, categorical_features)]
preprocessor = ColumnTransformer(transformers)
X_train_transformed = preprocessor.fit(X_train)

eli5.transform_feature_names(preprocessor, list(X_train.columns))

这会随着信息一起消失

AttributeError: Transformer categorical (type Pipeline) does not provide get_feature_names.

由于Pipeline嵌套在ColumnTransformer中,我从ELI5文档中了解到它将被处理

我是否需要使用get_feature_names方法创建Pipeline的修改版本,或者进行其他自定义修改以利用ELI5函数

我使用的是python 3.7.6、eli5 0.10.1、pandas 0.25.3和sklearn 0.22.1


Tags: 函数fromimportpipelinenamestransformtrainsklearn
1条回答
网友
1楼 · 发布于 2024-04-20 15:48:11

我认为问题在于eli5依赖于ColumnTransformer方法get_feature_names,它本身要求Pipelineget_feature_names,这在sklearn中还没有实现

I've opened an Issue with eli5 with your example.

一个可能的修复方法是:为ColumnTransformer添加一个transform_feature_names调度;这可能只是对其现有get_feature_names的修改,以便为其每个组件转换器调用eli5transform_feature_names(而不是sklearn自己的get_feature_names)。虽然我不确定如何处理input_names与训练数据帧列(可在ColumnTransformer中作为_df_columns使用)的不同,但下面的方法似乎有效

from eli5 import transform_feature_names

@transform_feature_names.register(ColumnTransformer)
def col_tfm_names(transformer, in_names=None):
    if in_names is None:
        from eli5.sklearn.utils import get_feature_names
        # generate default feature names
        in_names = get_feature_names(transformer, num_features=transformer._n_features)
    # return a list of strings derived from in_names
    feature_names = []
    for name, trans, column, _ in transformer._iter(fitted=True):
        if hasattr(transformer, '_df_columns'):
            if ((not isinstance(column, slice))
                    and all(isinstance(col, str) for col in column)):
                names = column
            else:
                names = transformer._df_columns[column]
        else:
            indices = np.arange(transformer._n_features)
            names = ['x%d' % i for i in indices[column]]
        # erm, want to be able to override with in_names maybe???

        if trans == 'drop' or (
                hasattr(column, '__len__') and not len(column)):
            continue
        if trans == 'passthrough':
            feature_names.extend(names)
            continue
        feature_names.extend([name + "__" + f for f in
                              transform_feature_names(trans, in_names=names)])
    return feature_names

我还需要为OneHotEncoder创建分派,因为它的get_feature_names需要参数input_features

@transform_feature_names.register(OneHotEncoder)
def _ohe_names(est, in_names=None):
    return est.get_feature_names(input_features=in_names)

相关链接:
https://eli5.readthedocs.io/en/latest/autodocs/eli5.html#eli5.transform_feature_names
https://github.com/TeamHG-Memex/eli5/blob/4839d1927c4a68aeff051935d1d4d8a4fb69b46d/eli5/sklearn/transform.py

相关问题 更多 >