web-dev-qa-db-fra.com

Obtention de noms de fonction depuis un pipeline FeatureUnion +

J'utilise une FeatureUnion pour rejoindre des fonctionnalités trouvées dans le titre et la description des événements:

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
    },
)

Cependant, l'appel de union.get_feature_names() me donne une erreur: "Le titre du transformateur (type Pipeline) ne fournit pas get_feature_names." J'aimerais voir certaines des fonctionnalités générées par mes différents vectoriseurs. Comment puis-je faire cela?

17
Huey

C'est parce que vous utilisez un transfomère personnalisé appelé TextSelector. Avez-vous implémenté get_feature_names dans TextSelector?

Vous devrez implémenter cette méthode dans votre transformation personnalisée si vous voulez que cela fonctionne.

Voici un exemple concret pour vous:

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']

Garde en tête que Feature Union va concaténer les deux listes émises depuis les get_feature_names de chacun de vos transformateurs. c'est pourquoi vous obtenez une erreur lorsqu'un ou plusieurs de vos transformateurs n'ont pas cette méthode.

Cependant, je peux voir que cela seul ne résoudra pas votre problème, car les objets Pipeline n'ont pas de get_feature_names méthode en eux, et vous avez des pipelines imbriqués (pipelines dans Feature Unions.). Vous avez donc deux options:

  1. Sous-classe Pipeline et ajoutez-le get_feature_names méthode vous-même, qui obtient les noms de fonction du dernier transformateur de la chaîne.

  2. Extrayez vous-même les noms des fonctionnalités de chacun des transformateurs, ce qui vous obligera à extraire ces transformateurs du pipeline vous-même et à appeler get_feature_names sur eux.

En outre, gardez à l'esprit que de nombreux transformateurs intégrés de Sklearn ne fonctionnent pas sur DataFrame mais transmettent des tableaux numpy, alors faites attention si vous allez enchaîner de nombreux transformateurs ensemble. Mais je pense que cela vous donne suffisamment d'informations pour vous donner une idée de ce qui se passe.

Encore une chose, jetez un œil à sklearn-pandas . Je ne l'ai pas utilisé moi-même mais cela pourrait vous apporter une solution.

10
hamel

Vous pouvez appeler vos différents vectoriseurs comme une fonction imbriquée par ceci (merci edesz):

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

Et puis vous avez obtenu l'instance TfidfVectorizer () pour passer dans une autre fonction:

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