GridsearchCV:尝试在参数中传递lambda时无法解决函数错误

Eri*_*c F 7 python scikit-learn grid-search

我在stackoverflow和其他地方看了很多,我似乎无法找到下面问题的答案.

我试图修改一个函数的参数,该函数本身就是GridSearchCV function of sklearn. More specifically, I want to change parameters (herepreserve_case = False ) inside thecasual_tokenize function that is passed to the parametertokenizer of the functionCountVectorizer`中的一个参数.

这是具体的代码:

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
Run Code Online (Sandbox Code Playgroud)

从20newsgroup生成虚拟数据

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

创建分类管道.
请注意,可以使用修改标记生成器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
Run Code Online (Sandbox Code Playgroud)

然后我想比较默认的tokenizer和CountVectorizernltk中的一个.请注意,我问这个问题,因为我想比较多个tokenizer,每个tokenizer都有需要指定的特定参数.

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])
Run Code Online (Sandbox Code Playgroud)

gs_clf.fit出现以下错误:PicklingError:无法在0x1138c5598处进行pickle>:在main上的属性查找失败

所以我的问题是:
1)是否有人知道如何专门处理这个问题GridSearchCV.
2)是否有更好的pythonic方法来处理将参数传递给函数,该函数也是一个参数?

phi*_*phi 5

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
Run Code Online (Sandbox Code Playgroud)

对于您的情况:

tokenizer=partial(casual_tokenize, preserve_case=False)
Run Code Online (Sandbox Code Playgroud)

2)是否有更好的pythonic方法来处理将参数传递给也将是参数的函数?

我认为使用lambdapartial都是“pythonic 方式”。

这里的问题是GridSearchCV使用多处理。这意味着它可能会启动多个进程,它必须序列化一个进程中的参数并将它们传递给其他进程(然后目标进程反序列化以获得相同的参数)。

GridSearchCVjoblib用于多处理/序列化。Joblib 无法处理lambda函数。