最急降下法(Gradient descent)
前々回、線形回帰とは、y = ax + b のa、bを求めることで未知のxに対し、yを予想できるようになると書き、前回はa、bを求めるために最小二乗法という方法があると書きましたが、今回の最急降下法というものを使って、実際にa、bを求めてみます。
y = ax + b のa、bをどうやって求める?
前回は、y = ax + b のa、bに適当な値を入れて、実績値のxを使って計算して計算結果と実績値のyの値を近づけるということをやりましたが、 このa、bはどうやって最終的な値に持っていけば良いでしょうか?a、bに適当な値を入れて、実績値y、xを使って計算して、a、bを適当に変えてまた計算して・・・を繰り返し行えば、いつかは適当なa、bがわかるかもしれませんが、a、bをどのように変えて 再計算させるかを考えるのは大変だと思います。
そこで今回の最急降下法(Gradient descent)というものを使います。最急降下法を使うと、a、bに入れるべき値を自動で算出してくれます。
最急降下法
y = ax + b の a、b の値を少しづつ上げていくと、最初はかなり差異のある状態から段々、差異がなくなっていき、ある時点で差異が一番小さくなり、それからまた差異が増えていきます。
aと差異合計のイメージ
bと差異合計のイメージ
最急降下法とは、このグラフの傾きから答えを求める方法です。
どこかにスタート地点を決めて、差異のグラフに傾きがあるうちは、傾いている方向に値を移動していき、傾きがなくなったら、そこが求めている値(差異が一番ない状態)になります。
傾きは目的関数を微分することで求められます。
目的関数は前回でてきた最小二乗法の式になります。
\(J(\theta_0, \theta_1) = \frac{1}{2m}\sum_{i=1}^m(h_\theta (x_i) - y_i)^2 \)
微分
微分すると傾きが求められると書きましたが、少し微分の復習をします。微分とは、以下と言われます。
・傾きを求めること。
・ある地点の接線を求めること。
・導関数を求めること。
どういうことかというと、xの変化量とyの変化量を極限まで縮めると、
xの時点の傾き(グラフ接線)になります。
上記のように変化量を極限まで縮め、傾き(グラフ接線)を求めることを微分するといいます。
ちなみに微分の公式は以下です。
\( (x^n)'=nx^{n-1} \)
a、bを求めるのに微分した値をどのように使うか
最小二乗法で出てきた式をa、bに対してそれぞれ微分すると、以下になります。(a、bのそれぞれに対し微分するには、偏微分というものを使うのですが、ここでは説明を省略します。ググって下さい)
元となる目的関数(最小二乗法で出てきた式)
\(J(\theta_0, \theta_1) = \frac{1}{2m}\sum_{i=1}^m(h_\theta (x_i) - y_i)^2 \)
aを微分
\({ \sum_{i=1}^m (h_\theta (x^{(i)}) - y^{(i)}) } x_j ^{(i)} \)
bを微分
\({ \sum_{i=1}^m (h_\theta (x^{(i)}) - y^{(i)}) }\)
a、bに初期値として適当な値を入れておき、テストデータ(y、x)を使って、上記の式を行うと、微分した値(傾き)の合計値が求められます。
その値がプラスの場合、グラフは右上がりの状態(答えとなるべき値を超えている)なので、a、bの値を少し減らします。
その値がマイナスの場合、グラフは右下がりの状態(答えとなるべき値に至っていない)なので、a、bの値を少し増やします。
学習率 (learning rate)
微分した値(傾き)の合計値をa、bに対して引けば上記の計算がされることになりますが、(仮) 次の計算で使うaを求める計算
\(a - { \sum_{i=1}^m (h_\theta (x^{(i)}) - y^{(i)}) } x_j ^{(i)} \)
(仮)次の計算で使うbを求める計算
\(b - { \sum_{i=1}^m (h_\theta (x^{(i)}) - y^{(i)}) }\)
a、bに与える値がプラスでもマイナスでも大きすぎるとと、答えにたどり着くことができず、
小さすぎると答えにたどり着くまで時間が掛かります。
大きすぎる場合
小さすぎる場合
なので微分した値(傾き)の合計値を適度な大きさに変換するのに学習率 (learning rate)というものを使います。
次の計算で使うaを求める計算(\(\alpha\)は学習率)
\(a - \alpha{ \sum_{i=1}^m (h_\theta (x^{(i)}) - y^{(i)}) } x_j ^{(i)} \)
次の計算で使うbを求める計算(\(\alpha\)は学習率)
\(b - \alpha{ \sum_{i=1}^m (h_\theta (x^{(i)}) - y^{(i)}) }\)
コロンイコール(定義)
a、bに対して微分した値をプラス、マイナスした後に、次のa、bに値をセットすることを表すのは := を使用します。:= は プログラムで使われる = と同じ意味です(a = a + 1;のイコールと同じ意味)。
次の計算で使うaを求める計算(\(\alpha\)は学習率)
\(a := a - \alpha{ \sum_{i=1}^m (h_\theta (x^{(i)}) - y^{(i)}) } x_j ^{(i)} \)
次の計算で使うbを求める計算(\(\alpha\)は学習率)
\(b := b - \alpha{ \sum_{i=1}^m (h_\theta (x^{(i)}) - y^{(i)}) }\)
上記の計算を繰り返すとそのうちa、bの変動がなくなるので、その状態になるまで繰り返します。
計算するときに
aを計算 → bを計算 → a、bの値を修正 → aを計算 → bを計算 → a、bの値を修正 → ・・・
のようにaの計算とbの計算は同時に行う必要があります。
ページのトップへ戻る