Объединение CountVectorizer и SelectKBest приводит к исчезновению меток - PullRequest
0 голосов
/ 11 октября 2019

У меня есть класс, который создает конвейер извлечения объектов и соответствует модели логистической регрессии. Входные данные представляют собой набор строковых данных в структуре DF. Класс ItemSelector просто возвращает столбец, содержащий чистые данные из исходного фрейма данных, а затем передает его в CountVectorizer и селектор Kbest. Если я удаляю Kbest, этот конвейер работает:

from sklearn.base import BaseEstimator, TransformerMixin


class ItemSelector(BaseEstimator, TransformerMixin):
    # returns a single column from a DF
    def __init__(self, key):
        self.key = key

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

    def transform(self, data_dict):
        return data_dict[self.key]

class LogisticRegressionWithWordFeatures(object):

    def __init__(self):
        self.model = LogisticRegression()

    def fit(self, df, labels):
        self.pipeline = self.get_preprocessing_pipeline(df)
        fitted_df = self.pipeline.fit_transform(df)
        self.model.fit(fitted_df, labels)
        return self

    def predict(self, df):
        fitted_df = self.pipeline.transform(df)
        y = self.model.predict(fitted_df)
        return y


    def get_preprocessing_pipeline(self, data_frame):
        """
        Get data frame containing features and labels from raw feature input DF.
        :param input_file: input DF
        """

        process_and_join_features = Pipeline([
            ('features', FeatureUnion([
            ('count_lemma_features', Pipeline([
                ('selector', ItemSelector(key='clean_Invoice_Description')),
                ('counts', CountVectorizer(analyzer="word", stop_words='english'))]))])),
            ('reducer', SelectKBest(chi2, k=1000))
        ])
        return process_and_join_features

Если я пытаюсь подогнать / преобразовать на основе этого конвейера, я получаю эту ошибку:

    model = LogisticRegressionWithWordFeatures()
    model.fit(train_data, train_labels)
    test_y = model.predict(test_data)

>>>

    TypeError                                 Traceback (most recent call last)
<ipython-input-183-536a1c9c0a09> in <module>
      1 b_logistic_regression_with_hypers_bow_clean = LogisticRegressionWithWordFeatures()
----> 2 b_logistic_regression_with_hypers_bow_clean = b_logistic_regression_with_hypers_bow_clean.fit(b_ebay_train_data, b_ebay_train_labels)
      3 b_ebay_y_with_hypers_bow_clean = b_logistic_regression_with_hypers_bow_clean.predict(b_ebay_test_data)
      4 b_gold_y_with_hypers_bow_clean = b_logistic_regression_with_hypers_bow_clean.predict(gold_df)

<ipython-input-181-6974b6ea2a5b> in fit(self, df, labels)
      6     def fit(self, df, labels):
      7         self.pipeline = self.get_preprocessing_pipeline(df)
----> 8         fitted_df = self.pipeline.fit_transform(df)
      9         self.model.fit(fitted_df, labels)
     10         return self

~/anaconda3/lib/python3.7/site-packages/sklearn/pipeline.py in fit_transform(self, X, y, **fit_params)
    391                 return Xt
    392             if hasattr(last_step, 'fit_transform'):
--> 393                 return last_step.fit_transform(Xt, y, **fit_params)
    394             else:
    395                 return last_step.fit(Xt, y, **fit_params).transform(Xt)

~/anaconda3/lib/python3.7/site-packages/sklearn/base.py in fit_transform(self, X, y, **fit_params)
    551         if y is None:
    552             # fit method of arity 1 (unsupervised transformation)
--> 553             return self.fit(X, **fit_params).transform(X)
    554         else:
    555             # fit method of arity 2 (supervised transformation)

TypeError: fit() missing 1 required positional argument: 'y'

Очевидно, проблема в том, что обучениеэтикетки не попадают в конвейер. Я попытался добавить другой селектор элементов для меток обучения:

        process_and_join_features = Pipeline([
            ('features', FeatureUnion([
                ('count_lemma_features', Pipeline([
                    ('selector', ItemSelector(key='clean_Invoice_Description')),
                    ('counts', CountVectorizer(analyzer="word", stop_words='english'))])),
                ('labels', ItemSelector(key='Expense_Category'))])),
            ('reducer', SelectKBest(chi2, k=1000))
        ])
        return process_and_join_features

Но это вызывает ключевую ошибку для метки (Expense_Category), даже если этот столбец присутствует в данных обучения.

ЕслиЯ делаю это шаг за шагом, это работает:

item_selector = ItemSelector(key='clean_Invoice_Description').fit(train_data)
count_selector = CountVectorizer(analyzer="word", stop_words='english')
k_best = SelectKBest(chi2, k=1000)

invoice_desc = item_selector.transform(train_data)
invoice_desc = count_selector.fit_transform(invoice_desc)
reduced_desc = k_best.fit_transform(invoice_desc, train_labels)
print(reduced_desc.shape)
>>> (6130, 1000)

Проблема с пошаговым способом заключается в том, что в других столбцах есть другие функции, которые я хотел бы использовать вместе с ними,и pipe предоставляет хороший способ сделать это без необходимости вручную объединять их.

1 Ответ

0 голосов
/ 12 октября 2019

Решил это. Основная проблема заключается во вложении каждой функции. Pipelines () ожидает список кортежей, где первый элемент в кортеже - это имя объекта / канала, а второй - фактический класс. Очень легко потерять учет вложенности, если добавить больше функций. Вот окончательный код:

   def get_preprocessing_pipeline(self, data_frame):
        """
        Get data frame containing features and labels from raw feature input csv file"""

        process_and_join_features = Pipeline([
            ('features', 
             FeatureUnion([
                ('tokens',
                    Pipeline([
                        ('selector', ItemSelector(key='clean_Invoice_Description')),
                        ('vec', CountVectorizer(analyzer="word", stop_words='english')),
                        ('dim_red', SelectKBest(chi2, k=5000))
                    ])),
                ('hypernyms',
                    Pipeline([
                        ('selector', ItemSelector(key='hypernyms_combined')),
                        ('vec', TfidfVectorizer(analyzer="word")),
                        ('dim_red', SelectKBest(chi2, k=5000))
                ]))]))])
        return process_and_join_features
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...