从FeatureUnion + Pipeline中获取要素名称

时间:2017-02-27 06:44:20

标签: python-3.x scikit-learn nlp feature-extraction

我正在使用FeatureUnion来加入从事件的标题和描述中找到的功能:

union = FeatureUnion(
    transformer_list=[
    # Pipeline for pulling features from the event's title
        ('title', Pipeline([
            ('selector', TextSelector(key='title')),
            ('count', CountVectorizer(stop_words='english')),
        ])),

        # Pipeline for standard bag-of-words model for description
        ('description', Pipeline([
            ('selector', TextSelector(key='description_snippet')),
            ('count', TfidfVectorizer(stop_words='english')),
        ])),
    ],

    transformer_weights ={
            'title': 1.0,
            'description': 0.2
    },
)

但是,调用union.get_feature_names()会给我一个错误:“Transformer title(type Pipeline)不提供get_feature_names。”我想看看我的不同矢量化器生成的一些功能。我该怎么做?

2 个答案:

答案 0 :(得分:6)

这是因为您使用的是名为TextSelector的自定义变换器。您是否在get_feature_names中实施了TextSelector

如果您希望这样做,您将必须在自定义转换中实现此方法。

以下是您的具体示例:

from sklearn.datasets import load_boston
from sklearn.pipeline import FeatureUnion, Pipeline
from sklearn.base import TransformerMixin
import pandas as pd

dat = load_boston()
X = pd.DataFrame(dat['data'], columns=dat['feature_names'])
y = dat['target']

# define first custom transformer
class first_transform(TransformerMixin):
    def transform(self, df):
        return df

    def get_feature_names(self):
        return df.columns.tolist()


class second_transform(TransformerMixin):
    def transform(self, df):
        return df

    def get_feature_names(self):
        return df.columns.tolist()



pipe = Pipeline([
       ('features', FeatureUnion([
                    ('custom_transform_first', first_transform()),
                    ('custom_transform_second', second_transform())
                ])
        )])

>>> pipe.named_steps['features']_.get_feature_names()
['custom_transform_first__CRIM',
 'custom_transform_first__ZN',
 'custom_transform_first__INDUS',
 'custom_transform_first__CHAS',
 'custom_transform_first__NOX',
 'custom_transform_first__RM',
 'custom_transform_first__AGE',
 'custom_transform_first__DIS',
 'custom_transform_first__RAD',
 'custom_transform_first__TAX',
 'custom_transform_first__PTRATIO',
 'custom_transform_first__B',
 'custom_transform_first__LSTAT',
 'custom_transform_second__CRIM',
 'custom_transform_second__ZN',
 'custom_transform_second__INDUS',
 'custom_transform_second__CHAS',
 'custom_transform_second__NOX',
 'custom_transform_second__RM',
 'custom_transform_second__AGE',
 'custom_transform_second__DIS',
 'custom_transform_second__RAD',
 'custom_transform_second__TAX',
 'custom_transform_second__PTRATIO',
 'custom_transform_second__B',
 'custom_transform_second__LSTAT']

请注意,Feature Union将连接每个变换器各自get_feature_names发出的两个列表。这就是为什么当一个或多个变压器没有这种方法时你会收到错误的原因。

但是,我可以看到仅凭这一点无法解决您的问题,因为Pipeline对象中没有get_feature_names方法,并且您有嵌套管道(功能联盟中的管道)。所以你有两个选择:

  1. Subclass Pipeline并自己添加get_feature_names方法,它从链中的最后一个变换器获取特征名称。

  2. 自己从每个变换器中提取功能名称,这需要您自己从管道中获取这些变换器并在其上调用get_feature_names

  3. 另外,请记住,许多内置变换器的sklearn不能在DataFrame上运行,而是通过numpy阵列,所以如果要将大量变压器链接在一起,请注意它。但我认为这可以为您提供足够的信息,让您了解正在发生的事情。

    还有一件事,请看sklearn-pandas。我自己没有使用它,但它可能为你提供解决方案。

答案 1 :(得分:0)

通过此操作(感谢edesz),您可以将不同的Vectorizer称为嵌套功能:

pipevect= dict(pipeline.named_steps['union'].transformer_list).get('title').named_steps['count']

然后您将TfidfVectorizer()实例传递给另一个函数:

Show_most_informative_features(pipevect,
       pipeline.named_steps['classifier'], n=MostIF)
# or direct   
print(pipevect.get_feature_names())