機械学習 基礎の基礎 – 勾配降下法 –

2021.08.21

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Introduction

表題の件や機械学習に関する良書・良サイトは多々ありますが、
やはり自分で手を動かさないと理解できない、ということで実際にやっていきます。

以前の記事では、 機械学習の分析手法である、最小二乗法について解説しました。

そこでは

yとモデル関数結果の差を二乗した数の和が最小になるようにθ0とθ1を決めればよい

といいましたが、実際にはどうやって最小になるようにパラメータをもとめればよいでしょうか。
こういう場合に本稿で解説する勾配法(勾配降下法)をつかって適切な値を求めることができます。

Gradient(Gradient descent)?

まずは勾配法についての解説です。
これは、モデル関数に対してコストが最小になるようにパラメータを少しづつ変化させ、
トレーニングに適合したパラメータを算出するアルゴリズムです。

機械学習での課題は、「いかに精度の高いモデルを構築するか」です。
ということは、「トレーニング時にどれだけ最適なパラメータをみつけることができるか」が
大事ということになります。

機械学習でいう「学習」は、 トレーニングにより最適なパラメータの値を自動で獲得することです。
適切な学習をおこなうために、損失関数で評価を行います。
損失関数とは、実際の正しい値と予測値とのズレを計算するための関数です。
この損失関数を基準として、その値が最も小さくなるパラメータを求めるのが
トレーニングの目的であり、
それを効率よく求めるための手法が勾配法ということになります。

勾配法では、現在の場所から勾配する方向に任意の距離だけ進んでいきます。
移動先でも同じく勾配を求めてまた進む、と繰り返していって
損失関数の値を減らしていきます。

また、どれだけの距離を進むかは「学習率(η)」とよばれるパラメータで決まります。
学習率、損失関数、パラメータを組み合わせて、対象パラメータの最適値を求めます。

簡単な例で降下法の説明

例えば、

f(x) = (x - 2)^2

という関数について考えてみましょう。
この関数で結果が最小となるのは x = 2のときです。

この関数を微分すると以下のようになります。

d(f(x)) / dx
= (x - 2)^2
= x^2 - 4x + 4
= 2x - 4

導関数は↓のように増減し、最小値となるのはx = 2のときです。

x = -1 : y = -6
x =  0 : y = -4
x =  1 : y = -2
x =  2 : y = 0
x =  3 : y = 2
x =  4 : y = 4

x < 2 のときはグラフが右下がり、x > 2 のときは左下がりになります。
なので、x = -1を開始点としてf(x)を小さくするにはxを右にずらします(xを大きくする)、
x = 4から開始した場合は左にずらす(xを小さくする)ことで、f(x)が最小にむかっていくことになります。

これが勾配降下法です。
式で記述すると↓のようになります。

a := bという記述は、aをbによって定義するという意味です。 また、ηは学習率とよばれるパラメータです。
この大きさによって最小値にいきつくまでの回数がかわってきます。
この値が大きい場合、少ない回数で収束(最小値へ到達する)することもありますが、
値がとびとびになり、いつまでも収束しないことがあります。
逆に学習値が小さい場合、収束しやすいが計算回数が多くコストがかかります。

では試しに、η = 1、xの開始点を3で計算してみましょう。
f(x)の微分は2x-4なので、式は↓になります。

x := η(2x -4)

実際に値をあてはめてみると、値が1、3、1、3と最小値となる x = 2をとびこえて
いつまでも収束しません(発散)。

x :=  3  - 1(2 * 3 - 4) =  1
x :=  1  - 1(2 * 1 - 4) =  3
x :=  3  - 1(2 * 3 - 4) =  1
x :=  1  - 1(2 * 1 - 4) =  3
・・・

次に学習率を0.2にして試してみます。 10回ほどで2.01まで収束しました。

#省略可のため小数点第2位で切り捨て
x :=  4  - 0.2(2 * 4 - 4) = 3.2
x :=  3.2  - 0.2(2 * 3.2 - 4) = 2.72
x :=  2.72  - 0.2(2 * 2.72 - 4) = 2.43
・
・
・
x :=  2.02  - 0.2(2 * 2.02 - 4) = 2.01

じわじわと最小値に向かっていっています。
更新回数は多くなりますが、少しずつ最適な値に進んでいるのがわかります。

最小二乗法の例で勾配降下法の説明

では次に、ここでの目的関数をさきほどのf(x)と
おなじように考えてみます。

この目的関数で記述されているf(x)は、

です。 θ0とθ1をもっています。
この場合には各々のパラメータで偏微分をおこない、
下記のような更新式になります。

※↑の目的関数をE(θ)と定義する

E(θ) = f(x)を含んでおり、θ0とθ1のパラメータをもっているためこのようになります。
では↑の式を偏微分してみます。

連鎖律

↑を偏微分する前に連鎖律について確認。
連鎖律とは、複数の関数が合成された関数(合成関数)を微分するとき、その導関数が
それぞれの導関数の積で与えられるという式のことを指します。
すなわち、対象の合成関数の微分が各関数の微分の積へと分解できることになります。

例えば↓のような式があり、

y = E(x)

関数Fは a=A(x) , b = B(a) , y = C(b)といった構成で成り立っているとします。
このときxに関するyの微分は↓のようになります。


※dy/dyは自分自身に対する微分(yが変化すれば自身も同じだけ変化するので結果は1)

このように、xに関するyの微分は、「各関数の微分の積」となります。
※合成関数の微分は各関数の微分へ分解可能

これをふまえてさきほどの目的関数を計算してみます。

偏微分の計算

以下を前提として計算します。

  • β = E(θ)
  • γ = f(x)

E(θ)をθ0で微分すると↓のようになります。

∂β / ∂θ0 = (∂β / ∂γ) * (∂γ / ∂θ0)
① ∂β / ∂γ = ∂(Σ(y - γ)^2)) / ∂γ
            = Σ( ∂(y - γ)^2 / ∂γ)
            = Σ( ∂(y^2 - 2yγ +  γ^2) / ∂γ) //展開 
            = Σ( 2γ -  2y)

② ∂γ / ∂θ0 = ∂(θ0x + θ1) / θ0
             = x

∂β / ∂θ0 = Σ( 2γ -  2y) * x  // ① * ②
          = Σ( 2f(x) - 2y)x

次にθ1の微分です。

∂β / ∂θ1 = (∂β / ∂γ) * (∂γ / ∂θ1)

∂β / ∂γで微分するところは同じなので
∂γをθ1の微分します。

∂γ / ∂θ1 = ∂(θ0x + θ1) / θ1
             = 1
∂β / ∂θ1 = Σ( 2γ -  2y) * 1  // ① * ②
          = Σ( 2f(x) - 2y)

というわけで、θ0とθ1の更新式は結果的に↓になります。

上記の式にしたがってθ0とθ1を更新していくことで、
最適なパラメータのf(x)関数を定義することができます。
そうやって定義したf(x)関数に対して、体重(x)を与えれば、
予測した身長(y)をかえしてくれるということになります。

Summary

勾配降下法のアルゴリズムには、
確率的勾配降下法やミニバッチ勾配降下法などいろいろあるので、
知りたいひとはこのあたりを参照してください。

今回は勾配法についてどのようなものか解説しました。
以前のscikit-learnを使った例では
fit関数を実行するだけで学習を行い、精度の高いパラメータやモデル関数が生成されましたが、
内部ではこういったアルゴリズムを用いてパラメータを探したりしています。

中身を知らなくても機械学習ライブラリ/フレームワークの使い方がわかれば、
機械学習モデルを構築して予測することはできますが、
内側を知ることでより機械学習の理解やイメージがより鮮明になると思います。

References