はじめに
今流行りのディープラーニング(深層学習)ですが、いざ自分でやってみると思ったように精度が出なかったり、重みの初期化や学習率をどのように選択したらよいのか、といったことで戸惑うことがよくあります。
重みの初期化や学習率といった、ニューラルネットではなく人間が選択しなければいけないパラメータをハイパーパラメータ(Hyperparameter)と呼びます。逆に言えば、ハイパーパラメータとは学習アルゴリズムによって決定できず、ヒューリスティックな部分でもあります。
ハイパーパラメータは試行錯誤で決定していくのが基本ですが(もちろん自動化技術もあります)、50年以上の歴史があるニューラルネットには知恵やテクニックが多くの先人によって培われてきました。そして、今もなお研究が盛んに行われている分野でもあります。
あとで参照しやすいように本記事では、ハイパーパラメータの指南をまとめてみました。
実際にハイパーパラメータを変えて、学習がどのように変化するのか実験して見たい方は以下のページで実験してみてください。
http://playground.tensorflow.org/
実際にサンプルコードとともにハイパーパラメータの検討を行っているテキストとしては、Michael Nielsen "ニューラルネットワークと深層学習"の第3章"ニューラルネットワークの学習の改善"がまとまっています。
http://nnadl-ja.github.io/nnadl_site_ja/chap3.html
フレームワークのバージョン
- TensorFlow 1.0.0
- Chainer 1.21.0
学習のコツ
精度改善の流れ
"データサイエンティスト養成読本 機械学習入門編"p.167 より
一般的に画像認識では、訓練データの量と質、特徴量、機械学習手法の順で認識精度に影響すると言われています。
Hugo Larochelle氏の提案
- 実数値を規格化すること。全ての値について平均値を引き、標準偏差で割る。
- 訓練中は学習レートを下げること。
- ミニバッチ学習で勾配を更新することできます。ミニバッチ学習では勾配がより安定的になります。
- 学習が停滞状態に陥ったのを脱出させるために、モーメントを使うことができる。
http://postd.cc/26-things-i-learned-in-the-deep-learning-summer-school/
戒め
アンチパターン
ハイパーパラメータの概略
深層学習の判別精度を向上させるコツとActive Learning (1/2)より
- 学習係数:一回のイテレーションで進む学習の度合い
- イテレーション数:学習を繰り返す最大の回数
- モーメンタム:最適な重みを導き出すための勾配法の高速化パラメーター
- 隠れ層のユニット数:隠れ層の数。基本的に大きければ大きいほどよいが、過学習には注意
- 活性化関数の数・種類:Sigmoid、Tanh、ReLUなどの関数の種類と、「層をいくつ、どのタイミングで組み入れるか」などの調整
- Dropoutの数:学習時のパラメーターのいくつかを任意の確立で使わないようにし、汎化性能を上げる仕組み
Yurie Oka氏のスライドより
ミニバッチサイズ
サンプル数 : 10〜100前後
メモ :
SGDの利点と計算資源でバランスをとって決める。多クラス分類の問題では、ミニバッチに各クラスのサンプルが1つ以上入るようにする。 p.27
# TensorFlow
tf.train.shuffle_batch(tensors, batch_size, capacity, min_after_dequeue, num_threads=1, seed=None, enqueue_many=False, shapes=None, allow_smaller_final_batch=False, shared_name=None, name=None)
# Chainer
chainer.iterators.SerialIterator(dataset, batch_size, repeat=True, shuffle=True)
ドロップアウト
$0.1\leq p\leq 0.9$
メモ :
各層の$p$は入力層から出力層に向けて$0.1\leq p\leq 0.9$の範囲で徐々に小さくなる値が選ばれる。p.32
# TensorFlow
tf.nn.dropout(x, keep_prob, noise_shape=None, seed=None, name=None)
# Chainer
chainer.functions.dropout(x, ratio=0.5, train=True)
学習率
学習の初期ほど大きな値を用いて、学習の進捗とともに学習係数を小さくする。
Adam
論文が推奨する値 :
- $\alpha$ : 0.001
- $\beta_{1}$ : 0.9
- $\beta_{2}$ : 0.999
- $\epsilon$ : 1e-08
# TensorFlow
tf.train.AdamOptimizer(learning_rate=0.001, beta1=0.9, beta2=0.999, epsilon=1e-08, use_locking=False, name='Adam')
# Chainer
chainer.optimizers.Adam(alpha=0.001, beta1=0.9, beta2=0.999, eps=1e-08)
デフォルトで論文が推奨する値に設定してあるようです。
重みとバイアスの初期化
重み :
正規分布$N(0,{\sigma}^{2})$から生成したランダム値。p.32,link
- $\mu$ : $0$
- $\sigma$ : $\frac{wscale}{\sqrt{insize}}$
- $wscale$ : 重みのスケール
バイアス :
$0$にするのが一般的。p.39
ReLU使う場合、dying ReLU問題を考慮してバイアスを小さい正の値で初期化する。
# TensorFlow
x = tf.placeholder(tf.float32, shape=[input_size, input_size])
wscale = 1.0
sigma = tf.sqrt(1/input_size) * wscale
W = tf.Variable(tf.random_normal(shape=[input_size, out_size], stddev=sigma))
b = tf.Variable(tf.zeros(shape=[out_size], dtype=tf.float32))
y = tf.matmul(x, W) + b
# Chainer
chainer.links.Linear(in_size, out_size, wscale=1, bias=0, nobias=False, initialW=None, initial_bias=None)
おわりに
逐次更新していきます。
参考
- 岡谷貴之, "深層学習", 講談社, 2015
- 本記事のページ指定はこの本のページ数を指している
- To_Murakami, "【機械学習】ニューラルネットワークにおける効率的なパラメータ調整方法についてまとめてみた", Qiita, 2016
- MAREK REI, "ディープラーニングのサマースクールで学んだ26のこと", POSTD, 2015
- 石川信行, "深層学習の判別精度を向上させるコツとActive Learning", @IT, 2015
- Yurie Oka, "実装ディープラーニング", SlideShare, 2013
- Sebastian Ruder, "勾配降下法の最適化アルゴリズムを概観する", Qiita, 2016
- http://deepdish.io/2015/02/24/network-initialization/
補足
ハイパーパラメータのチューニング技法
他にどのようなものがあるのか。
- グリッド探索(Grid Search)
- ランダム探索(Random Search)
- ベイズ最適化(Bayesian Optimization)
麻生英樹 他,"深層学習 Deep Learning"より
"dying ReLU" problems
Reluを利用した場合、なぜバイアスを微小な正の値で初期化するのか。