sklearn 中的 GridSearchCV 和 Pipeline 是否存在拟合差异?
Is there a diffrence of fit on GridSearchCV and Pipeline in sklearn?
也许这只是一个错误或者我真的很愚蠢,我包装了(或者更确切地说是同事包装了)一个使用一些 Keras 转换的 Keras 模型也包装了所以我们可以将 Keras 模型与 sklearn 库一起使用。
现在,当我在 Pipeline 上使用 fit 时,它工作正常。它 运行 和 returns 一个工作模型实例。但是,当我出于某种原因使用 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
时它起作用了:
GridSearchCV
和Pipeline
中的fit()
有区别吗?我真的很傻还是这只是一个错误?
顺便说一句,我目前被迫使用 Sklearn 0.19.1。
经过几个小时的思考和调试,我得出以下结论:
Pipeline.fit()
能够自动填充 **kwargs
个参数。
GridSearchCV.fit()
无法自动填充 **kwargs
个参数。
我在 sklearn 0.19.1
上测试了这个
我的问题是,使用 Keras Tokenizer
创建的词袋是使用 num_words
参数创建的,该参数将词袋限制为最大词数。我的同事在这方面做得不好,因此单词的数量与 LSTM 模型中的输入维度数量相匹配。因为从未设置 num_words
,包总是大于输入尺寸。
num_words
作为 **kwargs
参数传递给了 Tokenizer
。
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()
有效。
也许这只是一个错误或者我真的很愚蠢,我包装了(或者更确切地说是同事包装了)一个使用一些 Keras 转换的 Keras 模型也包装了所以我们可以将 Keras 模型与 sklearn 库一起使用。
现在,当我在 Pipeline 上使用 fit 时,它工作正常。它 运行 和 returns 一个工作模型实例。但是,当我出于某种原因使用 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
时它起作用了:
GridSearchCV
和Pipeline
中的fit()
有区别吗?我真的很傻还是这只是一个错误?
顺便说一句,我目前被迫使用 Sklearn 0.19.1。
经过几个小时的思考和调试,我得出以下结论:
Pipeline.fit()
能够自动填充 **kwargs
个参数。
GridSearchCV.fit()
无法自动填充 **kwargs
个参数。
我在 sklearn 0.19.1
上测试了这个我的问题是,使用 Keras Tokenizer
创建的词袋是使用 num_words
参数创建的,该参数将词袋限制为最大词数。我的同事在这方面做得不好,因此单词的数量与 LSTM 模型中的输入维度数量相匹配。因为从未设置 num_words
,包总是大于输入尺寸。
num_words
作为 **kwargs
参数传递给了 Tokenizer
。
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()
有效。