はじめに
第5章で「誤差逆伝播法」という強力な武器を手に入れたので、いよいよ実戦で役立つ「第6章:学習に関するテクニック」を復習したので、まとめてみました。
参考書籍
『ゼロから作るDeep Learning ーPythonで学ぶディープラーニングの理論と実装』
著者:斎藤 康毅
第6章の目標は、AIモデルの精度が上がらない状況になった際、原因を見抜いて正しい対策を立てられるようになること。そのために、4つの最適化の違いと、過学習の対策法について理解できるように学習を進めました。
第6章では、4つの最適化について学びました。
最初に誕生したのが「SGD」という手法です。
これは、「ゼロつく①」第4章で学んだ「勾配降下法」の弱点を解決するために誕生しました。
最適化に入る前にまずは、「勾配降下法」がどんな手法なのか確認をしました。
❓勾配降下法とは
➡ 足元の傾きだけを頼りに、最小値へ1歩ずつ下っていく手法
この1歩の進む大きさのことを「学習率」と呼びます。
そして、学習率と勾配を用いてパラメータを計算しますが、これは以下の式で求めることができました。
$$x_0 = x_0 - \eta \frac{\partial f}{\partial x_0}$$
$$x_1 = x_1 - \eta \frac{\partial f}{\partial x_1}$$
しかし、勾配降下法には弱点がありました。
- データが巨大だと計算に時間がかかる
全てのデータを計算するまで「1歩」も動くことができない
メモリを大量に消費し、パソコンがフリーズしてしまう - 局所最適解で止まる
途中の小さな窪みでも、傾きが0になればそこで進むのをやめてしまう - 歪んだ地形で激しくジグザグする
横幅が狭く立てに長い関数の形状では、ゴールに直進することができずに左右の壁に激しく衝突しながら進むため。計算効率が悪くなる
これらの弱点のうち、1つめの「計算に時間がかかる」という弱点を解決するために生まれたのがSGD(確率的勾配降下法)です。そして残りの弱点を克服するためにこの後に出てくるMomentumやAdamが作られたのです。
第4章との内容が繋がったところで、最適化手法の1つ「SGD」の学習に入りました。
❓SGDとは
➡ すべてのデータを見るのをやめて、ランダムに選んだデータだけを頼りに、高速で1歩ずつ進む手法
$$
W \leftarrow W - \eta \frac{\partial L}{\partial W}
$$
SGDの最大のメリットは、圧倒的に計算が早いところです。データが何件あろうが、毎回小数のデータしか見ないため、ものすごいスピードでパラメータを更新できます。
勾配降下法の弱点を解決するために誕生したSGDですが、SGDにも弱点が残されていました。
- ゴールの手前で激しく「ジグザク」する
- 局所最適解にハマってしまう
- 学習率を人間が手探りで調整し続けなければいけない
この3つの弱点のうち「ゴールの手前でジグザグしてしまう」、「局所最適解にハマってしまう」という弱点を克服しようと誕生したのがMomentumです。
❓Momentumとは
➡ 前回の進んだ勢いを記憶しておくことで、SGDのフラフラしたジグザグを打ち消し、ゴールへ向かって加速しながら直進する、物理ベースの手法
$$
v \leftarrow \alpha v - \eta \frac{\partial L}{\partial W}
$$
$$
W \leftarrow W + v
$$
SGDは「その場で1歩ずつ足元を見てステップを踏む」ような動きでしたが、左右の壁に激しくぶつかりジグザグした動きになっていました。
一方、Momentumは「ボールが地面の傾斜を転がるような」動きをします。
このMomentumの誕生により、以下の問題が解決しました。
*ジグザグ大回りの解消
左右への無駄な動き(フラフラ)が減り、谷底のゴールへ向かって圧倒的に最短ルートでたどり着けるようになりました。
- 局所最適解を飛び越える
途中に小さな窪みがあっても、坂を猛スピードで下ってきた「勢い(慣性)」のおかげで、止まらずにそのままビューンと飛び越えることができるようになりました。
次に誕生したのが「AdaGrad」です。
これはSGDの「学習率を人間が手探りで調整し続けなければいけない」という問題を解決するために生まれました。
❓AdaGradとは
➡ よく動く方向にはブレーキをかけ、動かない方向にはアクセルを踏むことで、効率よくゴールを目指す『自動歩幅調整』の手法
$$
h \leftarrow h + \frac{\partial L}{\partial W} \odot \frac{\partial L}{\partial W}
$$
$$
W \leftarrow W - \eta \frac{1}{\sqrt{h}} \odot \frac{\partial L}{\partial W}
$$
SGDは、どのパラメータに対しても、最初から最後まで同じ「一律の歩幅」で進むため、ジグザグと進んでいました
一方、AdaGradはパラメータごとに「学習の履歴」を記録し、歩幅を最適化します
- すでによく通った道
「ここはもう何度も通って地形がわかっているから、行き過ぎないように慎重に(歩幅を小さく)進もう」と自動でブレーキを踏みます - まだあまり通ってない道
「こっちはまだ探索が足りないから、大胆に(歩幅を大きく)進もう」と自動でアクセルを踏みます。
そして、AdaGradの最大のメリットは「学習率を細かく調整しなくてよくなる」です。AIが学習を進めながら、自分でちょうどいい歩幅にどんどん縮めていってくれるため、最初の設定が少々ズレていても上手くゴール(谷底)にたどり着いてくれます。
ただし、このAdaGradにも弱点があります。
それは、学習が長く続くと蓄積された値が大きくなりすぎてしまい、「歩幅がほぼゼロになって、ゴールに着く前に完全に足が止まってしまう」ということです。これはAdaGradの、過去の傾きをひたすら足し算して蓄積していくという特徴があるためです。
この、途中で止まってしまう弱点を解決したのが「Adam」という手法です。
❓Adamとは
➡ 「勢い」と「自動歩幅調整」を組み合わせ、さらに「過去を適度に忘れる機能」まで備えた手法
Adamは、「Momentum」と「AdaGrad」を組み合わせた手法で、それぞれの良いところを以下のように引き継いでいます。
- Momentum から:物理の「勢い(慣性)」を引き継ぎ、ジグザグの横ブレを抑えてまっすぐ直進する
- AdaGrad から:パラメータごとの「歩幅(学習率)の自動調整」を引き継ぎ、よく動く方向は慎重に、動かない方向は大胆に進む
続いて、重みの初期値について学びました。
❓重みの初期値とは
➡ ニューロンのスタート時の数値を、どうバラつかせれば全員がサボらずに働いてくれるか?を決める手法
❓なぜ初期値を全部0にする、適当に決めるのはいけないのか
- 全部同じ値にした場合
すべてのニューロンが「全く同じ計算」をして「全く同じミス」をします。すると、どれだけ学習させても全員が同じようにしか修正されず、「1つの巨大なニューロン」があるのと同じ状態になってしまいます。せっかくたくさん敷き詰めたニューロンの意味がありません。 - 適当なランダムにした場合
ディープラーニングでは、途中の層でデータがすべて 0 に潰れてしまったり、逆に数値が巨大化して爆発したりします。これを「勾配消失」や「勾配爆発」と呼び、AIの学習が途中で完全にストップしてしまいます。
これらの問題を起こさないようにするために、活性化関数に合わせた2つの初期値があります。
①Xavierの初期値
活性化関数:Sigmoid関数、tanh関数
②Heの初期値
活性化関数:ReLU関数
❓なぜ初期値を使い分けるのか
➡ 活性化関数のグラフの形状と、値のばらつきが深く関係するから
Sigmoid関数にXavierの初期値が適しているのは、最も傾きが大きい中央付近にデータを集めるためです。
Sigmoid関数は、どんなに入力された数値が大きくても小さくても、必ず 0 から 1 の間の波(S字カーブ)に変換する関数です。この関数の両端はグラフが完全に平ら(傾きがゼロ)になってしまいます。
- 初期値のばらつきが大きすぎる場合
➡ 出力はすべて「0」か「1」に張り付いてしまいます。グラフの端の方は傾きがゼロなので、微分が消滅してAIが全く学習できなくなります - 初期値のばらつきが小さすぎる場合
➡ 計算結果がすべて 0 の近くに集まります。Sigmoid関数に通すと、出力はすべて中央の「0.5」付近にガチガチに固まってしまいます。ニューロン全員が同じ「0.5」しか出力しないため、AIとしての表現力が失われて賢くなれません。
ReLU関数にHeの初期値が適しているのは、ReLU関数がデータの半分をゼロにして消してしまう特性を持っているからです。
ReLU関数は、現代のディープラーニングで最もよく使われる活性化関数ですが、非常に極端な形をしています。
- 入力がプラスのとき:数値をそのままスルーして通す
- 入力がマイナスのとき:すべて一律で 0 にカットして消去する
そのため、ランダムに数値が入ってきた場合、確率的にデータの約半分(マイナス側)がすべて 0 に潰されて消えてしまうことになります。
Heの初期値はそれを考慮して、あらかじめ広めにバラつかせることができます。
おわりに
第6章を通して、AIを「ただ動かす」だけでなく「より良く育てる」ためのコツを学びました。特に初期値の設定や過学習の対策は、「なぜ学習が止まってしまうのか」という理由が分かったことで、次に同じような壁にぶつかっても、どう調べればいいかの道筋が見えた気がします。