首页 > 解决方案 > sklearn 中的 GridSearchCV 和 Pipeline 是否存在拟合差异?

问题描述

也许这只是一个错误,或者我真的很愚蠢,我使用一些 Keras 转换包装(或者更好地说是一个同事包装)了一个 Keras 模型,因此我们可以将 Keras 模型与 sklearn 库一起使用。

现在,当我在 Pipeline 上使用 fit 时,它可以正常工作。它运行并返回一个工作模型实例。但是,当我出于某种原因使用 GridSearchCV 时,它无法进行转换(或者看起来如此)并且它给了我以下错误:

InvalidArgumentError (see above for traceback): indices[11,2] = 26048 is not in [0, 10001)
     [[Node: embedding_4/Gather = Gather[Tindices=DT_INT32, Tparams=DT_FLOAT, validate_indices=true, _device="/job:localhost/replica:0/task:0/cpu:0"](embedding_4/embeddings/read, embedding_4/Cast)]]

代码看起来像这样:

vocab_size = 10001

class TextsToSequences(Tokenizer, BaseEstimator, TransformerMixin):
    def __init__(self,  **kwargs):
        super().__init__(**kwargs)

    def fit(self, X, y=None):
        print('fitting the text')
        print(self.document_count)
        self.fit_on_texts(X)
        return self

    def transform(self, X, y=None):
        print('transforming the text')
        r = np.array(self.texts_to_sequences(X))
        print(r)
        print(self.document_count)
        return r

class Padder(BaseEstimator, TransformerMixin):
    def __init__(self, maxlen=500):
        self.maxlen = maxlen
        self.max_index = None

    def fit(self, X, y=None):
        #self.max_index = pad_sequences(X, maxlen=self.maxlen).max()
        return self

    def transform(self, X, y=None):
        print('pad the text')
        X = pad_sequences(X, maxlen=self.maxlen, padding='post')
        #X[X > self.max_index] = 0

        print(X)

        return X

maxlen = 15

def makeLstmModel():
    model = Sequential()
    model.add(Embedding(10001, 100, input_length=15))
    model.add(LSTM(35, dropout=0.2, recurrent_dropout=0.2))
    model.add(Dense(16, activation='sigmoid'))
    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
    model.summary()
    return model

lstmmodel = KerasClassifier(build_fn=makeLstmModel, epochs=5, batch_size=1000, verbose=42)

pipeline =  [
        ('seq', TextsToSequences(num_words=vocab_size)),
        ('pad', Padder(maxlen)),
        ('clf', lstmmodel)
    ]

textClassifier = Pipeline(pipeline)

#Setup parameters
parameters = {} #Some params to use in gridsearch

skf = StratifiedKFold(n_splits=numberOfFolds, shuffle=True, random_state=1)
gscv = GridSearchCV(textClassifier, parameters, cv=skf, iid=False, n_jobs=1, verbose=50)

gscv.fit(x_train, y_train)

现在上面的代码因 InvalidArgumentError 而失败,但是当我fit使用Pipeline它运行时:

在此处输入图像描述

fit()inGridSearchCV和 和有区别Pipeline吗?我真的很愚蠢还是这只是一个错误?

顺便说一句,我目前被迫使用 Sklearn 0.19.1。

标签: pythonmachine-learningscikit-learnkerasgrid-search

解决方案


经过数小时的思考和调试,我得出以下结论:

Pipeline.fit()能够自动填充**kwargs参数。

GridSearchCV.fit()无法自动填充**kwargs参数。

我在 sklearn 0.19.1 上测试了这个

我的问题是使用 KerasTokenizer创建的词袋是使用将num_words袋子限制为最大词数的参数创建的。我的同事在这方面做得不好,因此单词数与 LSTM 模型中的输入维度数相匹配。因为num_words从未设置过,所以袋子总是大于输入尺寸。

num_words传递给Tokenizer作为**kwargs参数。

class TextsToSequences(Tokenizer, BaseEstimator, TransformerMixin):
    def __init__(self,  **kwargs):
        super().__init__(**kwargs)

由于某种原因GridSearchCV.fit()无法自动填充。解决方案是使用固定参数。

class TextsToSequences(Tokenizer, BaseEstimator, TransformerMixin):
    def __init__(self, num_words=8000, **kwargs):
        super().__init__(num_words, **kwargs)

在此更改生效后GridSearchCV.fit()


推荐阅读