今日も窓辺でプログラム

外資系企業勤めのエンジニアが勉強した内容をまとめておくブログ

「ゼロから作るDeep Learning」を読んで知ったことのメモ

ディープラーニングの知識があまりない私が「ゼロから作るDeep Learning」を読んで知ったことを、自分用のメモも兼ねてまとめておきます。
本では実際のコードを使ってディープラーニングの基礎を解説していますが、今回の記事はメモなのでコードは出さずに断片的にメモしておきたいことを残しておきます。。
詳細が気になる方は、本やこの本のGitHubレポジトリを参考にしてください。

ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装

ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装

活性化関数が非線形である理由 (3.2.6章)

ニューラルネットの活性化関数には通常非線形関数が使われる。では、線形関数ではダメな理由は何か?
答えは線形関数を使うと、層を重ねてもニューラルネットの表現力が上がらないからです。

多層のニューラルネットワークの活性化関数が全て線形だと仮定します。
最終的な出力層の値は、(1)エッジの重みを掛ける、(2)活性化関数を重ねるという操作を複数回繰り返して得られた値となりますが、
(1)と(2)はともに線形な操作のため、最終的な出力の値も最初の入力に対して線形な関数を使って表現できます。

つまり、多層のネットワークと同じ出力をする単層のネットワークが必ず存在するということになり、層を重ねたとしてもネットワークの表現力は向上せず嬉しくありません。
このような理由で活性化関数には非線形関数が用いられるようです。

パラメータ最適化のアルゴリズム (6.1章)

パラメータの最適化のためのアルゴリズムも、TensorFlowを使っていた時はなんとなくで指定していましたが、この本を機にある程度知ることができました。

確率的勾配降下法 (SGD, Stochastic Gradient Descent)

ニューラルネットのパラメータを {\bf W}、損失関数を L、学習率を \etaと表記すると、確率的勾配降下法ではあるデータのサンプルが与えられるごとに次のようにデータを更新します。

 \displaystyle
{\bf W} \leftarrow {\bf W} - \eta \frac{\partial L}{\partial {\bf W}}

この手法の欠点のひとつに、関数の形状によっては探索の経路が非効率的になってしまうという点があるようです。
例えば、この記事の図2のように関数が一方向に伸びたような形をしている場合、探索の経路はジグザグとした非効率的な動きになります。

モーメンタム (Momentum)

上述の確率的勾配降下法の欠点を克服するための手法の一つに、モーメンタムと呼ばれるものがあります。物理学の運動量の発想を使った手法のようで、下記数式を使用してパラメータを更新します。
 \displaystyle
{\bf v} \leftarrow \alpha {\bf v} - \eta \frac{\partial L}{\partial {\bf W}}
 \displaystyle
{\bf W} \leftarrow {\bf W} + {\bf v}

このvというのが物理で言うところの速度に対応していて、[tex: \alpha}を0.9などに設定すると極端なジグザグな動きはしなくなり、その直前までの動きから徐々に向きが変わっていくような挙動になります。慣性が働いているようなもので、イメージとしてはボールを転がした時のようにふらふらしながら最小値に到達するイメージのようです。

AdaGrad

最適化においては、学習率  \eta の設定は非常に大切です。大きくしすぎると正しく最適化できず、小さすぎるとなかなか最適化が進みません。
この学習率の値を学習が進むにつれて調節するための手法が AdaGrad と呼ばれているものです。AdaGradのAdaはadaptiveに由来しているようです。
イメージとしては、最初は学習率を大きめに設定しておいて最適化を早く進め、最適化が進むにつれて学習率を徐々に小さくしていく、という手法です。

具体的には、次の数式でパラメータを更新するようです。
 \displaystyle
{\bf h} \leftarrow {\bf h} + \frac{\partial L}{\partial {\bf W}} \odot \frac{\partial L}{\partial {\bf W}}
 \displaystyle
{\bf W} \leftarrow {\bf W} - \eta \frac{1}{\sqrt{\bf h}} \frac{\partial L}{\partial {\bf W}}

 \odotは要素ごとの積です。
 {\bf h}は、これまでに経験した勾配の2乗を要素ごとに保持している変数です。一つ目の式で、この値を更新しています。
2つ目の式の学習率がこの {\bf h}によって調整されています。今まで大きな勾配をたどってきた要素ほど、学習率が小さくなるような式になっていることがわかるかと思います。

Adam

詳しい数式などは書いていなかったのですが、Adamと呼ばれる手法はモーメンタムとAdaGradを融合する、というのがアイデアのベースになっている手法のようです。
元論文はここにあるようです。
https://arxiv.org/abs/1412.6980

どの手法を用いるのが良いかというのは、問題によって異なるみたいです。先人たちがどのような問題にはどのような手法を使っているのか、いろいろ見てみる必要がありそうです。

重みの初期値の設定方法 (6.2章)

活性化関数がReLUの場合はHeの初期値、シグモイドなどのS字カーブのときはXavierの初期値を使うのがベストプラクティス

ハイパーパラメータの最適化

データセットを訓練データとテストデータの2つに分けて、テストデータに対してハイパーパラメータを最適化していく、という方法ではいけない。
この方法だと、ハイパーパラメータがテストデータに対して過学習を起こしてしまう。一般的に、この2つのデータとは別に検証用データを用意して、検証用データをもとにしてハイパーパラメータを最適化していく。