Python
MachineLearning
DeepLearning
Keras
TensorFlow

怠け者のためのディープラーニング入門 - ハイパーパラメータのチューニング

はじめに

学習率やドロップアウト率、活性化関数を選定するハイパーパラメータのチューニングについて紹介します。

ハイパーパラメータのチューニング

ハイパーパラメータ(Hypter Parameter)は、機械学習アルゴリズムに対して設計者が決めないといけない値です。ハイパーパラメータはモデルの性能を左右する値なので頭を悩ませる問題です。取り分け、より幅広く深く層を持つニューラルネットでは多くのパラメータを設定する必要があります。ニューラルネットにおいて次のようなハイパーパラメータが具体的に挙げられます。

  • 学習係数:一回のイテレーションで進む学習の度合い
  • イテレーション数:学習を繰り返す最大の回数
  • モーメンタム:最適な重みを導き出すための勾配法の高速化パラメーター
  • 隠れ層のユニット数:隠れ層の数。基本的に大きければ大きいほどよいが、過学習には注意
  • 活性化関数の数・種類:Sigmoid、Tanh、ReLUなどの関数の種類と、「層をいくつ、どのタイミングで組み入れるか」などの調整
  • Dropoutの数:学習時のパラメーターのいくつかを任意の確立で使わないようにし、汎化性能を上げる仕組み

深層学習の判別精度を向上させるコツとActive Learning (1/2)

試行錯誤でエイヤとハイパーパラメータを決めてしまうこともあるのですが、以下のような自動でパラメータを探索してくれる手法が提案されています。本記事では簡単で分かりやすいグリッドサーチを紹介します。

  • グリッドサーチ(Grid Search)
  • ランダムサーチ(Random Search)
  • ベイズ最適化(Bayesian Optimization)

グリッドサーチ

グリッドサーチは設計者によって指定された複数のハイパーパラメータの組合せを網羅的に探索する手法です。しらみつぶしに調べていくためパラメータの数に応じて計算量が大きくなってしまうのが難点です。ランダムサーチのほうが良いパラメータを見つけてくれるという報告もありますが、分かりやすさをとってこちらを紹介しました。

また適当に決めてしまうよりも、学習率はとりあえず「0.0001, 0.001, 0.01」、ノード数は「64, 128, 256, 512」のなかからグリッドサーチを実行して決定するほうが説明する際に説得力があると思います。

斎藤康毅『ゼロから作るDeep Learning』にも書いてあるのですが、経験的に近い値よりも大胆に数値を変えたほうがいいように思います。したがって、数値のハイパーパラメータは2のべき乗や10のべき乗のような指数スケールで候補を挙げていくとよいでしょう。例えば、64,128,256,512,1024,...のような感じです。

サンプルコード

グリッドサーチを実行するには、sklearn.model_selection.GridSearchCVを使います。内部的では交差検証を使って性能指標を算出してハイパーパラメータの組合せの甲乙を決めています。

次のような流れでプログラムを組みます。

  • ハイパーパラメータの候補を列挙する
  • keras.wrappers.scikit_learn.KerasClassifierによりKerasのモデルをScikit-Learn APIに適した形に変換する
  • sklearn.model_selection.GridSearchCVにより、ハイパーパラメータの候補、交差検証のためのデータセットの分割数、性能指標を設定します
  • model.fit(データセット, ラベル)によりグリッドサーチの実行を行う
import numpy as np
np.random.seed(1234)
from keras.models import Sequential
from keras.layers import Dense, Activation
from keras import optimizers
from keras.wrappers.scikit_learn import KerasClassifier

from sklearn.utils import shuffle
from sklearn.model_selection import GridSearchCV

param_grid = {
    "activation": ["relu", "tanh", "sigmoid", ],
    "learning_rate": [0.0001, 0.001, 0.01],
    "units": [64, 128, 256],
}

def mlp(activation="relu", learning_rate=0.001, units=128):
    model = Sequential()
    model.add(Dense(units=units, input_dim=2))
    model.add(Activation(activation))
    model.add(Dense(units=units))
    model.add(Activation(activation))
    model.add(Dense(units=1))
    model.add(Activation('sigmoid'))
    model.compile(loss='binary_crossentropy',
              optimizer=optimizers.SGD(lr=learning_rate),
              metrics=['accuracy',])
    return model

n_data = 200
n_class = n_data//2
X_positive = np.random.normal(loc=1.0, scale=1.0, size=(n_class, 2))
X_negative = np.random.normal(loc=-1.0, scale=1.0, size=(n_class, 2))
X = np.r_[X_positive, X_negative]
y = np.r_[[1]*n_class, [0]*n_class]
X, y = shuffle(X, y)

model = KerasClassifier(build_fn=mlp, nb_epoch=50, batch_size=20, verbose=0)
clf = GridSearchCV(estimator=model, param_grid=param_grid, cv=4, scoring='accuracy')
res = clf.fit(X, y)
print ("Accuracy:", res.best_score_)
print ("Hyper Parameters:", res.best_params_)

実行結果 :

候補に上げたハイパーパラメータの中では、活性化関数はReLu、学習率は0.01、中間層のノード数は64が最適であることが分かりました。

Accuracy: 0.915
Hyper Parameters: {'activation': 'relu', 'learning_rate': 0.01, 'units': 64}

おわりに

今回はグリッドサーチを紹介しました。今までは手作業でもうちょっと学習率を上げてみて…のような感じでヒューリスティックにハイパーパラメータを決めていたのですが、今回グリッドサーチを使ってみて気楽に値が求められたので非常に便利でした。