勾配降下法とは

Python, ML24 December 2020

What's

ニューラルネットワークの各ニューロンには、重み(データの重要度的な)が伝達される。 その重みのパラメータを適切にしてやることで最終的な損失(損失関数によって求められる)を少なくすることができる。

勾配降下法はその適切なパラメータを探索するための方法の1つ

勾配とは

そもそも勾配とはなんなのか? 勾配は微分によって求められた、ある関数の傾き。またその方向のこと。

関数の微分によって求められるのは、その微小区間での関数の接線の傾きを示すがそのことを勾配と言う。

何をするのか

勾配降下法はその名前の通り、勾配を求めることによって損失を0に近づける。 求めたい重みのパラメータをどっちの方向に動かせば良いか(勾配の方向でわかる)に応じてパラメータの値を修正する。

それを繰り返す。

問題点

勾配降下法は繰り返していけば理論上最も損失の小さくなるパラメータにたどり着きそうだが、問題点がある。

1. たどり着いた最も損失の小さくなる点が、全体で見た時に最も小さい点かわからない

基本的に勾配は坂道をイメージすれば良いので、 ある点Aから坂道を下った時に一番下までたどり着いても、 隣にもっと下まで下る坂道があればそちらの方が最も低い点までたどり着くよね。と言う話

点Aがどこかはほぼランダムなのでこれが問題点として挙げられる。

2. 重みパラメータはネットワーク全体で10万〜1億もしくはそれ以上あり、時間がかかりすぎる

ニューラルネットワークでは、途方もない数のニューロンが存在しそれ1つ1つに重みが存在するため 計算二時間がかかりすぎると言う欠点がある

Backpropagation(誤差逆伝播法)

超大事な考え方。重みパラメータの計算において最強であるが、非常に難しい。

勾配を求めるには損失関数の微分をすればいい、つまり損失関数のある微小区間で重みを変化させればいい。 その勾配に基づいて損失が最も低い点を探しに行くが、計算がしんどすぎる。

1つ1つのニューロンに対して、逆向きに出力の間違いを教えてあげるのがBackpropagation(誤差逆伝播法)

算出された出力に対して、逆にこれだけ間違ってるよ。を教えてあげる。

通常、ニューラルネットでの計算方向をfoward, 逆向きをbackwardと言う。

入力xに対してニューロンの出力をf(x)とすると、
fowardの時はf(x)を出すのみ。
backwardの時は「自身の微分」と「前の層(順方向で後ろの層)が伝えてきた値」を掛け算して、
次(順方向で前の層)に送る。

つまり、まとめると。

順伝播(通常のニューラルネットの方向)で、入力xと重みWから出力yを求める。 逆伝播で、既知の入力xと重みW、出力yから勾配を求めて重みWを更新する

勾配消失

Backpropagationで前の層に勾配を伝えて重みを更新していく際に、入力値によっては勾配が0になってしまう問題がある。 これを勾配消失と言う。 0になるとその時点で次の層に誤差信号が伝わらなくなるので、パラメータ更新ができなくなる。

長年この問題は解決されなかったが、活性化関数にReLUができてからは劇的に改善された。

ReLU: 入力が0以下の時は0、0より大きい時はその値を出力する

ミニバッチ学習

そもそもバッチ学習とは、学習データ全てを利用して損失を測定しそれに応じて重みパラメータを更新することを言う。

それに対してミニバッチ学習では、 学習データの中から、ランダムにN個取り出し損失を測定、重みの更新を行うことを言う。 そのため以下のようなメリットがある。

  • 少ない学習単位で行うためコスト(時間やCPUなど)が少ない
  • データごとに損失関数が変化するため、そのデータに特化せず汎化性能が上がる。

確率的勾配法

Backpropagationを使えば適切にパラメータのチューニングができるが、それには時間がかかるし難易度が高い。 そのため、確率的勾配法(SGD)もしくはその改良版のAdamがよく使われる。

確率的勾配法では、ミニバッチ学習を使用して様々な初期値から最も損失の低い点を探しにいく。 その結果広い範囲で見たときの本当に最も損失の低くなる点にたどり着く確率が高くなる。

Momentum + Nestrov

SGDの欠点を補う形で出てきたMomentum と Nestrovだが実際に昨今の言葉の使い方として、 SGD + Momentum + NestrovをまとめてSGDと呼ぶことも多い。

tags: Python, ML