kerasで変数の重みは学習してくれますが、いくつのニューロン数がいいのか、何層必要か、学習率の最適値など、固定で渡すパラメーターも存在します。
今回は、これらのパラメーターをチューニングするのにscikit-learnのGridSearchに渡して探索してみます。
この例では、irisなどのデータでクラス分類をやる場合を想定して書いています。
準備
モデルを作るのに必要なライブラリの他に、以下を読み込んでください。
from sklearn.grid_search import GridSearchCV
from sklearn.pipeline import Pipeline
モデルの構築を関数化する
変更したいパラメタを引数にした関数を作ります。
この例では、簡略化のために2レイヤー目以降のニューロン数は元のニューロン数のn乗根で出しています。
def create_model(self, evMethod, neurons, layers, learn_rate):
# Criate model
model = Sequential()
model.add(Dense(neurons, input_dim=self.column_length, kernel_initializer='normal', activation='relu'))
for i in range(1, layers):
model.add(Dense(int(numpy.ceil(numpy.power(neurons,1/i))), kernel_initializer='normal', activation='relu'))
model.add(Dense(3, kernel_initializer='normal', activation='softmax'))
# Compile model
adam = optimizers.Adam(lr=learn_rate)
model.compile(loss='categorical_crossentropy', optimizer=adam, metrics=['accuracy'])
return model
モデルに渡す配列を準備する
すべて配列で渡す必要があります。
batch_size = [1000,300,100]
epochs = [10, 50, 100]
neurons = [20, 30, 45]
learn_rate = [0.001, 0.005, 0.01, 0.07]
layers = [1,3,5]
学習
モデルをパイプラインに渡す
作成したモデルをmlp
としてestimatorに追加します。初期値は使われないので適当。
estimators = []
estimators.append(('mlp', KerasClassifier(build_fn=self.create_model, epochs=10, batch_size=200, verbose=1)))
pipeline = Pipeline(estimators)
Pipelineにパラメーターを渡す
param_grid = dict(mlp__neurons = neurons, mlp__batch_size = batch_size, mlp__epochs=epochs, mlp__learn_rate=learn_rate, mlp__layers=layers)
GridSearchは通常の使い方と同じ
grid = GridSearchCV(estimator=pipeline, param_grid=param_grid)
grid_result = grid.fit(self.X, self.Y)
最適な組み合わせを表示
best_estimator_
で一番良いモデルのパラメタを教えてくれます。精度も表示させます。
clf = grid_result.best_estimator_
print(clf.get_params())
accuracy = clf.score(self.X, self.Y)
print("\nAccuracy: %.2f" % (accuracy))
最適なモデルの保存
GridSearchを使うと数十倍の学習時間がかかりますので、一番良いモデルを保存するのもおすすめです。普通にモデル構築した場合と比べて呼び出しが特殊なので気をつけてください。
clf.steps[1][1].model.save('file to path')
この要領で、活性化関数など他の変数もチューニングできますので活用してみてください。
追記:Randomized Gridsearch版
学習中にメモリオーバーになってしまったため、試行数を減らすべくただのGridSearchからRandomized GridSearchに変えました。
ほとんど関数名を置き換えるだけで動きます。パラメーターの組み合わせ数が多い場合、実行にはこちらのほうが現実的です。
grid = RandomizedSearchCV(estimator=pipeline, param_distributions=param_grid, n_iter=30)