読者です 読者をやめる 読者になる 読者になる

Itsukaraの日記

最新IT技術を勉強・実践中。最近はDeep Learningに注力。

機械学習で勾配降下法の収束を加速できるか、ちょっと試行

機械学習 ITのお勉強 Python

深層学習のp.37に、誤差関数の谷底に高低差が少ない場合に収束が遅くなることへの対策として、「3.6.5 モメンタム」というものが書かれていました。これは、重み係数の修正量を計算するときに、前回の修正量の定数倍を加えるというもの。

機械学習から離れて、単に、関数の谷底を求めるだけならば、上記よりも、ニュートン法を用いたほうが良いと感じました。ただ、ニュートン法では、2次微分が必要であり、一般には2次微分を求めるのは難しいため、あまり使われていないと、どこかに書かれてました(どの本か忘れた)。

機械学習の理解を深めるために簡単なBackward Propagationプログラムを自作したので、これにニュートン法的なプログラムを入れ込んで少し試してました。

具体的には、谷底近くの曲面の形状を、各次元で2次関数で近似し、収束を高速化できないか試しました。

各次元で2次関数ということは、各次元で1次微分が1次関数ということなので、(l)回目の重みW_{ji}^{(l)}に対する誤差Eの勾配を\frac{\partial E}{\partial W_{ji}^{(l)}}としたとき、2つの点(W_{ji}^{(l)}, \frac{\partial E}{\partial W_{ji}^{(l)}})(W_{ji}^{(l-1)}, \frac{\partial E}{\partial W_{ji}^{(l-1)}})を結ぶ直線がx軸と交差する点(y=0となる点)を求めれば良いだけであり、簡単に計算できます。

繰り返し毎の誤差の変化がある程度少なくなってきたところで上記を行うと、確かに収束は速くなりました。ただ、誤差が非常に小さくなると、2つの点が非常に近くなり、直線の傾きを計算する際の誤差が大きくなり、W_{ji}の値が発散してしまいます。これを防ぐには、値が発散しそうなW_{ji}に対しては、モメンタムを用いれば良さそうな気がします。

なお、上記は、非常に単純な場合(2層のパーセプトロンで「XOR」を学習する場合)で試しただけです。

ちなみにニュートン法は、かなり古典的な手法なのでもっと最新の数学的手法を用いれば、勾配降下法の収束を、もっと加速できるのではないか? 数学の専門家が機械学習に加われば、機械学習が飛躍的に高速化する可能性があるのではないか? などと、夢想しているところです。

2週間ぐらい前まで、上記の試行と、別の試行を行っていたのですが、これに時間を掛けていたせいで、1カ月ぐらい前に買った本を読むのが遅れてしまいました。色々と夢想も良いかなと思っていたのですが、まずは、機械学習の基礎をしっかりと理解して、TensorFlowを自由自在に活用できるようになることを、当面の目標しようと思います。

追記

上記、W_{ji}の新しい値として、谷底となる点でのW_{ji}の値を使っていました。図で例示すると、下図の赤い点でした。なお、下図は機械学習で実際に使った値ではなく、近似対象が4次曲線であった場合を例として、計算で谷底を推定した図です。

ちなみに、横軸がW_{ji}の値で、縦軸はEの値です。また、青い線は近似対象として試した4次曲線で、2つの青い点は直近2回のW_{ji}の値です。青い線と重なった赤い曲線は、「直近の2回の(W_{ji}, E)の値と、そこでの1次微分値を元に近似した2次曲線」です。赤い点は計算で推定した谷底の点で、斜めの黒線は最直近のW_{ji}での接線、水平の黒線は(推定された)谷底での接線です。

いきなり谷底となるW_{ji}の推定値を使うのは、やりすぎですね。せめて、通常のニュートン法と同じように、谷底での接線と、直近のW_{ji}での接線との交点を使うべきですね(下記の図のオレンジの点)。

なお、下記のグラフは、谷底の部分を拡大してます。図示した部分での実際の曲線は殆ど水平です。縦軸は「+3.035」を基準とした差分を表しており、上端と下端での差は、わずか0.001です。

f:id:Itsukara:20160628070902j:plain