web-dev-qa-db-ja.com

KerasClassifierにコールバックを送信できますか?

分類器をより速く実行し、忍耐力が設定した数に達した場合は早期に停止するようにします。次のコードでは、モデルのフィッティングを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
_

このコードはここから来ました 。このコードは、私がこれまでに使用した中で最も正確です。問題は、コードのどこにも定義されたmodel.fit()がないことです。また、フィットするのに永遠にかかります。 fit()操作はresults = cross_val_score(...)で発生し、そこにコールバックをスローするパラメーターはありません。

どうすればこれを行うことができますか?また、テストセットでトレーニングされたモデルを実行するにはどうすればよいですか?

後で使用するために、トレーニング済みモデルを保存できるようにする必要があります...

13
Ravaal

KerasClassifierのソースコードである ここから を読み取ると、fitの引数を渡すことができ、それらを使用する必要があります。私はあなたのデータセットを持っていないのでそれをテストすることはできませんが、これがうまくいくかどうか教えてくれます。うまくいかない場合は、ソリューションを適応させようとします。この行を変更します:

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

何が起こっているのかについての簡単な説明:KerasClassifierは、fitpredictscoreのすべての可能な引数を取り、各メソッドが呼び出されるときにそれに応じてそれらを使用します。彼らは、パイプラインで呼び出すことができる上記の各関数に行く必要がある引数をフィルタリングする関数を作成しました。 fitステップ内にpredictStratifiedKFoldの呼び出しがいくつかあり、毎回異なる分割をトレーニングしていると思います。

フィットするのに永遠に時間がかかり、10回フィットする理由は、あなたが尋ねたように、1回のフィットが300エポックを実行しているためです。したがって、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_に戻った場合。

ネットワークがコンパイルされたので、トラブルシューティングを開始できます。

これがあなたの解決策です

これで、実際のエラーメッセージを受け取ることができました。 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回トレーニングします。つまり、あなたが言っていたようにエポックを実行しているのではなく、300エポックを10回実行しています。このツールを使用した結果としても何が起こっていますか:モデルは常に異なるため、fit()メソッドが異なるモデルに10回適用されることを意味します。したがって、コールバックも10回適用され、 ModelCheckpoint()によって保存されたファイルは上書きされ、最後の実行の最良のモデルのみを使用していることに気付きます。

これはあなたが使用するツールの本質であり、私はこれを回避する方法がわかりません。これは、考えられるすべての構成と一緒に使用することを特に考えられていなかったさまざまな一般的なツールを使用した結果として発生します。

6
Nassim Ben

試してください:

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

どこ list_of_callbacksは、適用するコールバックのリストです。あなたは詳細を見つけることができます ここ 。そこでは、KerasClassifierに供給されるパラメーターが正当な適合パラメーターである可能性があると述べられています。

GPUで複数の実行を使用している場合、特にtheanoを使用しているときに、いくつかの報告されたメモリリークが原因で問題が発生する可能性があることにも言及する価値があります。また、複数の近似を実行すると、sklearnAPIを使用したときに独立していないように見える結果が表示される場合があることにも気づきました。

編集:

また試してみてください:

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

ラッパーのインスタンス化にコールバックリストを配置する代わりに。

3
Marcin Możejko

これは私がしたことです

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

そしてこれまで働いてきました

1
agcala