Sklearn Pipeline: передать параметр в пользовательский Transformer? - PullRequest
3 голосов
/ 13 марта 2019

У меня есть пользовательский Transformer в моем sklearn конвейере, и мне интересно, как передать параметр в мой Transformer:

В приведенном ниже коде вы можете видеть, что я использую словарь "weight" в моемТрансформатор.Я хочу не определять этот словарь внутри моего Transformer, а вместо этого передавать его из конвейера, чтобы я мог включить этот словарь в поиск по сетке.Можно ли передать словарь в качестве параметра моему Трансформатору?

# My custom Transformer
  class TextExtractor(BaseEstimator, TransformerMixin):
        """Concat the 'title', 'body' and 'code' from the results of 
        Stackoverflow query
        Keys are 'title', 'body' and 'code'.
        """
        def fit(self, x, y=None):
            return self

        def transform(self, x):
            # here is the parameter  I want to pass to my transformer
            weight ={'title' : 10, 'body': 1, 'code' : 1}
            x['text'] = weight['title']*x['Title'] +  
            weight['body']*x['Body'] +  
            weight['code']*x['Code']

            return x['text']

param_grid = {
    'min_df' : [10],
    'max_df' : [0.01],
    'max_features': [200],
    'clf' : [sgd]
    # here is the parameter  I want to pass to my transformer
    'weigth' : [{'title' : 10, 'body': 1, 'code' : 1}, {'title' : 1, 'body': 
     1, 'code' : 1}]

}

for g in ParameterGrid(param_grid) :   

    classifier_pipe = Pipeline(

    steps=[    ('textextractor', TextExtractor()), #is it possible to pass 
                my parameter ?
               ('vectorizer', TfidfVectorizer(max_df=g['max_df'], 
                     min_df=g['min_df'], max_features=g['max_features'])),
               ('clf', g['clf']), 
            ],
    )

1 Ответ

2 голосов
/ 14 марта 2019

Для этого вам просто нужно добавить метод __init__() в начале определения вашего класса.На этом шаге вы определите свой класс TextExtractor как аргумент, который вы называете weight.

Вот как это можно сделать: (Я добавил много строк кода раньше радиВоспроизводимость - учитывая, что вы ничего не указали, я составил некоторые фальшивые данные. Я также предположил, что вы пытаетесь сделать с весами умножение строк?)

# import all the necessary packages
from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.pipeline import Pipeline
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import ParameterGrid, GridSearchCV
from sklearn.linear_model import SGDClassifier

import pandas as pd
import numpy as np

#Sample data
X = pd.DataFrame({"Title" : ["T1","T2","T3","T4","T5"], "Body": ["B1","B2","B3","B4","B5"], "Code": ["C1","C2","C3","C4","C5"]})
y = np.array([0,0,1,1,1])

#Define the SGDClassifier
sgd = SGDClassifier()

Ниже я только добавил init step:

# My custom Transformer

class TextExtractor(BaseEstimator, TransformerMixin):
    """Concat the 'title', 'body' and 'code' from the results of 
    Stackoverflow query
    Keys are 'title', 'body' and 'code'.


    """

    def __init__(self, weight = {'title' : 10, 'body': 1, 'code' : 1}):

        self.weight = weight

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

    def transform(self, x):

        x['text'] = self.weight['title']*x['Title'] + self.weight['body']*x['Body'] + self.weight['code']*x['Code']

        return x['text']

Обратите внимание, что я передал значение параметра по умолчанию, если вы его не указали.Это зависит от вас.Затем вы можете вызвать ваш преобразователь, выполнив:

textextractor = TextExtractor(weight = {'title' : 5, 'body': 2, 'code' : 1})
textextractor.transform(X)

Это должно вернуть:

0    T1T1T1T1T1B1B1C1
1    T2T2T2T2T2B2B2C2
2    T3T3T3T3T3B3B3C3
3    T4T4T4T4T4B4B4C4
4    T5T5T5T5T5B5B5C5

Затем вы можете определить свою сетку параметров:

param_grid = {
'vectorizer__min_df' : [0.1],
'vectorizer__max_df' : [0.9],
'vectorizer__max_features': [200],
# here is the parameter  I want to pass to my transformer
'textextractor__weight' : [{'title' : 10, 'body': 1, 'code' : 1}, {'title' : 1, 'body': 
 1, 'code' : 1}]
}

И, наконец,do:

for g in ParameterGrid(param_grid) :   

classifier_pipe = Pipeline(

steps=[    ('textextractor', TextExtractor(weight = g['textextractor__weight'])), 
           ('vectorizer', TfidfVectorizer(max_df=g['vectorizer__max_df'], 
                 min_df=g['vectorizer__min_df'], max_features=g['vectorizer__max_features'])),
           ('clf', sgd),  ] )

Вместо этого вы можете выполнить поиск по сетке, который затем потребует от вас написать:

pipe = Pipeline( steps=[    ('textextractor', TextExtractor()), 
           ('vectorizer', TfidfVectorizer()),
           ('clf', sgd) ] )
grid = GridSearchCV(pipe, param_grid, cv = 3)
grid.fit(X,y)
...