GridsearchCV: невозможно зафиксировать ошибку функции при попытке передать лямбду в параметре - PullRequest
0 голосов
/ 05 июня 2018

Я довольно подробно рассмотрел стекопоток и другие места, и я не могу найти ответ на проблему ниже.

Я пытаюсь изменить параметр функции, которая сама является параметром внутриGridSearchCV function of sklearn. More specifically, I want to change parameters (here preserve_case = False ) inside the casual_tokenize function that is passed to the parameter tokenizer of the function CountVectorizer`.

Вот конкретный код:

from sklearn.datasets import fetch_20newsgroups
from sklearn.pipeline import Pipeline
from sklearn.naive_bayes import MultinomialNB
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.model_selection import GridSearchCV
from nltk import casual_tokenize

Генерация фиктивных данных из 20newsgroup

categories = ['alt.atheism', 'comp.graphics', 'sci.med', 
              'soc.religion.christian']
twenty_train = fetch_20newsgroups(subset='train',
                               categories=categories,
                               shuffle=True,
                               random_state=42)

Создание конвейера классификации.
Обратите внимание, что токенизатор можно изменить с помощью lambda.Мне интересно, есть ли другой способ сделать это, поскольку он не работает с GridSearchCV.

text_clf = Pipeline([('vect',
                      CountVectorizer(tokenizer=lambda text:
                                     casual_tokenize(text, 
                                     preserve_case=False))),
                     ('tfidf', TfidfTransformer()),
                     ('clf', MultinomialNB()),
                    ])

text_clf.fit(twenty_train.data, twenty_train.target) # this works fine

Затем я хочу сравнить токенизатор по умолчанию CountVectorizer с токенайзером в nltk.Обратите внимание, что я задаю вопрос, потому что я хотел бы сравнить несколько токенизаторов, каждый из которых имеет определенные параметры, которые необходимо указать.

parameters = {'vect':[CountVectorizer(),
                       CountVectorizer(tokenizer=lambda text:
                                       casual_tokenize(text, 
                                       preserve_case=False))]}

gs_clf = GridSearchCV(text_clf, parameters, n_jobs=-1, cv=5)
gs_clf = gs_clf.fit(twenty_train.data[:100], twenty_train.target[:100])

gs_clf.fit выдает следующую ошибку: PicklingError: Невозможно выполнить выборку при 0x1138c5598>: поиск атрибута на main не выполнен

Поэтому у меня следующие вопросы:
1) Кто-нибудь знает, как решить эту проблему, в частности, с GridSearchCV.
2) Есть ли лучший питонный способ справиться с передачей параметров в функцию, которая также будет параметром?

1 Ответ

0 голосов
/ 05 июня 2018

1) Кто-нибудь знает, как решить эту проблему специально с GridSearchCV.

Вы можете использовать partial вместо lambda

from functools import partial
from sklearn.externals.joblib import dump

def add(a, b):
    return a + b

plus_one = partial(add, b=1)
plus_one_lambda = lambda a: a + 1
dump(plus_one, 'add.pkl')          # No problem
dump(plus_one_lambda, 'add.pkl')   # Pickling error

Для вашего случая:

tokenizer=partial(casual_tokenize, preserve_case=False)

2) Есть ли лучший питонный способ справиться с передачей параметров в функцию, которая также будет параметром?

Я думаю,использование lambda или partial является «питоническим путем».

Проблема здесь в том, что GridSearchCV использует многопроцессорность.Это означает, что он может запускать несколько процессов, он должен сериализовать параметры в одном процессе и передавать их другим (а затем целевые процессы десериализуются для получения тех же параметров).

GridSearchCV использует joblib для многопроцессорной обработки /сериализации.Joblib не может обрабатывать lambda функций.

...