2017-02-27 104 views
5

我希望分类器跑得更快,如果耐心达到我设定的数字,就要提前停下来。在下面的代码中,它会进行10次拟合模型的迭代。我可以发送回调给KerasClassifier吗?

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 

我在以下各项

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)) 

改变了cross_val_score,现在我得到这个错误 -

ValueError: need more than 1 value to unpack 

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

我该如何去做这件事? 另外,如何运行在测试集上训练的模型?

我需要能够保存以供日后使用训练的模型......

+0

你能为我们提供一个回调列表定义也工作了? –

+0

请参阅修改请 – NickTheInventor

+0

您可以显示发生错误的位置?多一点跟踪 –

回答

3

阅读from here,这是KerasClassifier的源代码,你可以通过它适合的论点,他们应该被使用。 我没有你的数据集,所以我不能测试,但你能告诉我,如果这个工程,如果没有,我会尝试和适应的解决方案。改变这一行:

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

所发生的事情的一个小的解释:KerasClassifier正在采取所有的候选条件论点fitpredictscore并相应地使用他们时,每个方法被调用。他们创建了一个函数,用于过滤应该传递给管道中可以调用的上述每个函数的参数。 我想有该StratifiedKFold步骤在不同的拆分每次训练里面几个fitpredict电话。

为什么它需要永远适合,它适合10次是因为一个适合做300个时代,正如你问。所以KFold被重复该步骤在不同的折叠:与给予KerasClassifier的所有参数

  • 呼叫fit(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

所以,现在你的网络编译,我可以开始排除故障。

这里是您的解决方案

所以现在我能得到真正的错误消息。事实证明,当您在cross_val_score()函数中输入fit_params=whatever时,您正在将这些参数提供给管道。为了知道管道的哪一部分要发送那些你必须像这样指定它的参数:

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次​​在数据集的不同部分。所以它不像你说的那样划时代,它有10次300个时代。 由于使用此工具也会发生什么情况:由于模型始终是不同的,这意味着fit()方法在不同模型上应用了10次,因此,回调也应用了10次不同的时间,并且由ModelCheckpoint()保存的文件获得重写,你只能找到最后一次运行的最佳模型。

这是内置于您使用的工具,我没有看到任何解决方法。这是因为使用不同的通用工具,这些工具并不是特别被认为与所有可能的配置一起使用。

+0

请参阅我的编辑。我把错误放在那里。 – NickTheInventor

+1

如果没有你的帮助,我怎么能想出来呢?你真是太棒了!此外,我只分享了我的一半代码,所以您提到的所有更改都不适用于我的实际代码......无论如何,它都可以工作。 – NickTheInventor

+0

实际上,您可以在管道中找到'__'信息文档: 管道的目的是组装几个可以在设置不同参数的同时进行交叉验证的步骤。为此,它可以使用名称和参数名称以'__'分隔来设置各个步骤的参数,如下例所示。一个步骤的估算器可以完全通过将参数名称设置为另一个估算器或通过将其设置为无来移除变压器来替换。 链接:http://scikit-learn.org/stable/modules/generated/sklearn.pipeline.Pipeline.html –

3

尝试:

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

其中list_of_callbacks是要应用回调的列表。你可以找到详细信息here。在那里提到,输入到KerasClassifier的参数可能是合法的拟合参数。

另外值得一提的是,如果你正在使用多个运行于GPU的有可能是一个问题,由于一些报道的内存泄漏尤其是当你使用theano。我还注意到,使用sklearn API时,运行多个拟合可能会显示似乎不是独立的结果。

编辑:

尝试也:

results = cross_val_score(pipeline, X, encoded_Y, cv=kfold, fit_params = {'mlp__callbacks': calls}) 

而不是投入包装实例的回调列表。

+1

比我早30秒^^干得不错。 –

+0

RuntimeError:无法克隆对象,因为构造函数似乎没有设置参数回调 – NickTheInventor

+0

您能否提供完整的代码? –

0

这是我做了什么

results = cross_val_score(estimator, X, Y, cv=kfold, 
         fit_params = {'callbacks': [checkpointer,plateau]}) 

,迄今已

相关问题