gpt4 book ai didi

python - 我可以向 KerasClassifier 发送回调吗?

转载 作者:太空狗 更新时间:2023-10-29 18:31:13 25 4
gpt4 key购买 nike

如果耐心达到我设置的数字,我希望分类器运行得更快并早点停止。在下面的代码中,它进行了 10 次拟合模型的迭代。

import numpy
import pandas
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.wrappers.scikit_learn import KerasClassifier
from keras.callbacks import EarlyStopping, ModelCheckpoint
from keras.constraints import maxnorm
from keras.optimizers import SGD
from sklearn.model_selection import cross_val_score
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import StratifiedKFold
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
# fix random seed for reproducibility
seed = 7
numpy.random.seed(seed)
# load dataset
dataframe = pandas.read_csv("sonar.csv", header=None)
dataset = dataframe.values
# split into input (X) and output (Y) variables
X = dataset[:,0:60].astype(float)
Y = dataset[:,60]
# encode class values as integers
encoder = LabelEncoder()
encoder.fit(Y)
encoded_Y = encoder.transform(Y)

calls=[EarlyStopping(monitor='acc', patience=10), ModelCheckpoint('C:/Users/Nick/Data Science/model', monitor='acc', save_best_only=True, mode='auto', period=1)]

def create_baseline():
# create model
model = Sequential()
model.add(Dropout(0.2, input_shape=(33,)))
model.add(Dense(33, init='normal', activation='relu', W_constraint=maxnorm(3)))
model.add(Dense(16, init='normal', activation='relu', W_constraint=maxnorm(3)))
model.add(Dense(122, init='normal', activation='softmax'))
# Compile model
sgd = SGD(lr=0.1, momentum=0.8, decay=0.0, nesterov=False)
model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])
return model

numpy.random.seed(seed)
estimators = []
estimators.append(('standardize', StandardScaler()))
estimators.append(('mlp', KerasClassifier(build_fn=create_baseline, nb_epoch=300, batch_size=16, verbose=0, callbacks=calls)))
pipeline = Pipeline(estimators)
kfold = StratifiedKFold(n_splits=10, shuffle=True, random_state=seed)
results = cross_val_score(pipeline, X, encoded_Y, cv=kfold)
print("Baseline: %.2f%% (%.2f%%)" % (results.mean()*100, results.std()*100))

这是由此产生的错误 -
RuntimeError: Cannot clone object <keras.wrappers.scikit_learn.KerasClassifier object at 0x000000001D691438>, as the constructor does not seem to set parameter callbacks

我在以下更改了 cross_val_score-
numpy.random.seed(seed)
estimators = []
estimators.append(('standardize', StandardScaler()))
estimators.append(('mlp', KerasClassifier(build_fn=create_baseline, nb_epoch=300, batch_size=16, verbose=0, callbacks=calls)))
pipeline = Pipeline(estimators)
kfold = StratifiedKFold(n_splits=10, shuffle=True, random_state=seed)
results = cross_val_score(pipeline, X, encoded_Y, cv=kfold, fit_params={'callbacks':calls})
print("Baseline: %.2f%% (%.2f%%)" % (results.mean()*100, results.std()*100))

现在我收到此错误-
ValueError: need more than 1 value to unpack

This code came from here .该代码是迄今为止我使用过的最准确的代码。问题是没有定义 model.fit()代码中的任何地方。也需要永远适应。 fit()操作发生在 results = cross_val_score(...)并且没有参数可以在那里抛出回调。

我该怎么做?
另外,如何运行在测试集上训练的模型?

我需要能够保存经过训练的模型以备后用...

最佳答案

阅读from here ,这是 KerasClassifier 的源代码,您可以将 fit 的参数传递给它,它们应该被使用。
我没有你的数据集,所以我无法测试它,但你可以告诉我这是否有效,如果无效,我会尝试调整解决方案。改变这一行:

estimators.append(('mlp', KerasClassifier(build_fn=create_baseline, nb_epoch=300, batch_size=16, verbose=0, callbacks=[...your_callbacks...])))

对正在发生的事情的一个小解释:KerasClassifier 正在为 fit 获取所有可能的参数, predict , score并在调用每个方法时相应地使用它们。他们制作了一个函数,用于过滤应进入上述每个可在管道中调用的函数的参数。
我猜有几个 fitpredict StratifiedKFold内部调用每次都在不同的分组上进行训练。

正如您所问的,为什么需要永远拟合并且拟合 10 次是因为一次拟合是 300 个 epoch。所以 KFold 在不同的折叠上重复这个步骤:
  • 电话fit将所有参数赋予 KerasClassifier (300 个时代和批量大小 = 16)。它对 9/10 的数据进行训练,并使用 1/10 作为验证。

  • 编辑:

    好的,所以我花时间下载数据集并尝试您的代码...首先,您需要纠正网络中的“一些”问题:
  • 您的输入有 60 个功能。您在数据准备中清楚地显示了它:
    X = dataset[:,:60].astype(float)

    那你为什么会有这个:
    model.add(Dropout(0.2, input_shape=(33,)))

    请改为:
    model.add(Dropout(0.2, input_shape=(60,)))
  • 关于您的目标/标签。您将目标从原始代码 ( binary_crossentropy ) 更改为 categorical_crossentropy .但是你没有改变你的 Y 数组。因此,要么在您的数据准备中执行此操作:
    from keras.utils.np_utils import to_categorical
    encoded_Y = to_categorical(encoder.transform(Y))

    或将您的目标更改回 binary_crossentropy .
  • 现在网络的输出大小:最后一个密集层上的 122?您的数据集显然有 2 个类别,那么您为什么要尝试输出 122 个类别?它不会匹配目标。请将您的最后一层改回:
    model.add(Dense(2, init='normal', activation='softmax'))

    如果您选择使用 categorical_crossentropy , 或者
    model.add(Dense(1, init='normal', activation='sigmoid'))

    如果你回到 binary_crossentropy .

  • 所以现在你的网络已经编译好了,我可以开始解决问题了。

    这是您的解决方案

    所以现在我可以得到真正的错误信息。原来,喂食时 fit_params=whatevercross_val_score()函数,您将这些参数提供给管道。为了知道您想将这些参数发送到管道的哪一部分,您必须像这样指定它:
    fit_params={'mlp__callbacks':calls}

    您的错误是说该进程无法解包 'callbacks'.split('__', 1)成 2 个值。它实际上是在寻找应用它的管道步骤的名称。

    它现在应该可以工作了:)
    results = cross_val_score(pipeline, X, encoded_Y, cv=kfold, fit_params={'mlp__callbacks':calls})

    但是,你应该知道这里发生了什么......交叉验证实际上调用了 create_baseline()函数从头开始重新创建模型 10 次,并在数据集的不同部分训练 10 次。所以它没有像你说的那样做 epochs,它做了 10 次 300 epochs。
    使用此工具还会发生什么:由于模型总是不同的,这意味着 fit()方法在不同的模型上应用了 10 次,因此,回调也应用了 10 次不同的时间和由 ModelCheckpoint() 保存的文件。被覆盖,你会发现自己只有上次运行的最佳模型。

    这对于您使用的工具来说很重要,我看不出有任何解决方法。这是因为使用了不同的通用工具,这些工具并未特别被认为与所有可能的配置一起使用。

    关于python - 我可以向 KerasClassifier 发送回调吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42492824/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com