勾配降下法とは?AIが損失関数を小さくする仕組みを新人エンジニア向けに数式つきで解説

こんにちは。ゆうせいです。

今回は、第2章として「勾配降下法」を解説します。

前回は、AIの予測がどれくらい間違っているかを測る「損失関数」について学びました。

損失関数は、AIにとっての反省点数です。

では、AIは反省点数を見たあと、どうやって賢くなるのでしょうか?

答えが、勾配降下法です。

勾配降下法とは、損失関数の値が小さくなる方向へ、パラメータを少しずつ動かしていく方法です。

たとえるなら、霧の中で山を下るようなものです。

遠くの景色は見えません。

でも、自分の足元がどちらに下っているかは分かります。

そこで、足元の傾きを見ながら、少しずつ低い方向へ進みます。

AIも同じです。

損失という山の上から出発し、損失が小さい谷底を目指して、パラメータを少しずつ更新していきます。

勾配降下法を学ぶ前に押さえる記号

まず、今回使う記号を整理しましょう。

記号意味初心者向けの説明
J損失関数AIの間違い具合を表す関数
θパラメータAIが調整する値の集まり
w重み入力をどれくらい強く使うかを決める値
bバイアス予測値を全体的にずらす値
η学習率1回の更新でどれくらい動かすかを決める値
∇J勾配損失がどちらに増えるかを表す傾き
t更新回数何回目の学習ステップかを表す番号

ηは「イータ」と読みます。

学習率は、AIの一歩の大きさです。

山下りで言えば、1歩を大きく踏み出すのか、小さく慎重に進むのかを決める値です。

勾配とは何か

勾配とは、損失関数がどちらの方向にどれくらい増えるかを表すものです。

まず、パラメータが1つだけの場合を考えましょう。

パラメータをw、損失関数をJ(w)とします。

dJ / dw

日本語で言えば、wを少し変えたときに、損失Jがどれくらい変わるかを表します。

dJ / dw が正の値なら、wを増やすと損失が増える傾向があります。

dJ / dw が負の値なら、wを増やすと損失が減る傾向があります。

微分の値意味損失を減らす動き
dJ / dw > 0wを増やすと損失が増えやすいwを減らす
dJ / dw < 0wを増やすと損失が減りやすいwを増やす
dJ / dw = 0その場では傾きがない更新量がほぼ0になる

ここで大切なのは、勾配は「損失が増える方向」を教えるという点です。

損失を減らしたいなら、その逆方向へ進みます。

坂道で上り方向が分かったら、下りたいときは反対に進みますよね。

AIの学習も同じです。

勾配降下法の基本式

勾配降下法の基本式は、次の通りです。

θ_{t+1} = θ_t - η * ∇J(θ_t)

日本語で言えば、次のパラメータは、今のパラメータから、学習率と勾配を掛けたものを引いて更新します。

この式を分解すると、意味が分かりやすくなります。

部分意味
θ_t現在のパラメータ
θ_{t+1}次のパラメータ
η学習率
∇J(θ_t)現在の位置における損失関数の勾配
- η * ∇J(θ_t)損失が小さくなる方向への移動量

この式は、AI学習のかなり重要な基本形です。

損失を見て、勾配を計算し、反対方向へ少し進む。

この繰り返しで、AIは少しずつ予測を改善していきます。

パラメータが2つある場合

線形回帰では、よく重みwとバイアスbを使います。

予測式は次の通りです。

ŷ_i = w * x_i + b

日本語で言えば、i番目の予測値は、入力x_iに重みwを掛け、バイアスbを足したものです。

このとき、損失関数は次のように書けます。

J(w, b) = (1 / n) * Σ_{i=1}^{n} (y_i - (w * x_i + b))^2

日本語で言えば、線形回帰の損失関数は、正解値と予測値の差を二乗し、全データで平均したものです。

パラメータがwとbの2つあるので、それぞれを更新します。

w_{t+1} = w_t - η * (∂J / ∂w)

日本語で言えば、次の重みwは、現在の重みwから、学習率とw方向の傾きを掛けたものを引いて更新します。

b_{t+1} = b_t - η * (∂J / ∂b)

日本語で言えば、次のバイアスbは、現在のバイアスbから、学習率とb方向の傾きを掛けたものを引いて更新します。

∂J / ∂w は「wについての偏微分」です。

偏微分とは、複数のパラメータがあるときに、1つのパラメータだけを動かした場合の変化を調べる方法です。

たとえば、カレーの味を調整するとき、塩だけ変える、スパイスだけ変える、水だけ変える、という確認をしますよね。

偏微分も似ています。

wだけ変えたら損失はどう変わるのか。

bだけ変えたら損失はどう変わるのか。

1つずつ見ていくのです。

wについての偏微分を省略せずに導く

ここから、線形回帰の損失関数をwで偏微分してみます。

まず、損失関数を確認します。

J(w, b) = (1 / n) * Σ_{i=1}^{n} (y_i - (w * x_i + b))^2

日本語で言えば、正解値と予測値の差を二乗して平均したものです。

計算しやすくするため、誤差を次のように置きます。

e_i = ŷ_i - y_i

日本語で言えば、i番目の誤差は、予測値から正解値を引いたものです。

予測値は次の通りです。

ŷ_i = w * x_i + b

日本語で言えば、予測値は、wとx_iの積にbを足したものです。

したがって、誤差は次のように書けます。

e_i = w * x_i + b - y_i

日本語で言えば、誤差は、w * x_i + b から正解値y_iを引いたものです。

損失関数は、誤差e_iを使って次のように書けます。

J(w, b) = (1 / n) * Σ_{i=1}^{n} e_i^2

日本語で言えば、損失関数は、各データの誤差を二乗して平均したものです。

wで偏微分します。

∂J / ∂w = ∂ / ∂w [(1 / n) * Σ_{i=1}^{n} e_i^2]

日本語で言えば、損失関数全体をwについて微分します。

1 / n は定数なので外に出せます。

∂J / ∂w = (1 / n) * Σ_{i=1}^{n} ∂(e_i^2) / ∂w

日本語で言えば、平均の係数1 / nを外に出し、各データの二乗誤差をwについて微分します。

合成関数の微分を使います。

∂(e_i^2) / ∂w = 2 * e_i * (∂e_i / ∂w)

日本語で言えば、e_iの二乗をwで微分すると、2 * e_iに、e_iをwで微分したものを掛けます。

e_iは次の式でした。

e_i = w * x_i + b - y_i

日本語で言えば、誤差は、w * x_i + b - y_iです。

このe_iをwで微分します。

∂e_i / ∂w = ∂(w * x_i + b - y_i) / ∂w

日本語で言えば、w * x_i + b - y_iをwについて微分します。

x_i、b、y_iはwに対して定数として扱います。

∂(w * x_i) / ∂w = x_i

日本語で言えば、w * x_iをwで微分するとx_iになります。

∂b / ∂w = 0

日本語で言えば、bはwではないので、wで微分すると0になります。

∂y_i / ∂w = 0

日本語で言えば、y_iもwではないので、wで微分すると0になります。

したがって、次のようになります。

∂e_i / ∂w = x_i + 0 - 0 = x_i

日本語で言えば、e_iをwで微分するとx_iになります。

ここまでを戻します。

∂J / ∂w = (1 / n) * Σ_{i=1}^{n} 2 * e_i * x_i

日本語で言えば、損失関数のw方向の傾きは、各データの誤差に入力x_iを掛け、2倍して平均したものです。

e_iを元の式に戻します。

∂J / ∂w = (2 / n) * Σ_{i=1}^{n} (w * x_i + b - y_i) * x_i

日本語で言えば、wについての偏微分は、予測値と正解値の差に入力x_iを掛けたものを全データで合計し、2 / nを掛けたものです。

予測値ŷ_iを使うなら、次のようにも書けます。

∂J / ∂w = (2 / n) * Σ_{i=1}^{n} (ŷ_i - y_i) * x_i

日本語で言えば、w方向の勾配は、予測値と正解値の差に入力値を掛けたものの平均的な値です。

bについての偏微分を省略せずに導く

次に、bについて偏微分します。

損失関数は同じです。

J(w, b) = (1 / n) * Σ_{i=1}^{n} e_i^2

日本語で言えば、損失関数は、誤差の二乗平均です。

bで偏微分します。

∂J / ∂b = ∂ / ∂b [(1 / n) * Σ_{i=1}^{n} e_i^2]

日本語で言えば、損失関数全体をbについて微分します。

1 / n を外に出します。

∂J / ∂b = (1 / n) * Σ_{i=1}^{n} ∂(e_i^2) / ∂b

日本語で言えば、各データの二乗誤差をbについて微分します。

合成関数の微分を使います。

∂(e_i^2) / ∂b = 2 * e_i * (∂e_i / ∂b)

日本語で言えば、e_iの二乗をbで微分すると、2 * e_iに、e_iをbで微分したものを掛けます。

e_iは次の通りです。

e_i = w * x_i + b - y_i

日本語で言えば、誤差は、予測値から正解値を引いたものです。

e_iをbで微分します。

∂e_i / ∂b = ∂(w * x_i + b - y_i) / ∂b

日本語で言えば、w * x_i + b - y_iをbについて微分します。

w、x_i、y_iはbに対して定数として扱います。

∂(w * x_i) / ∂b = 0

日本語で言えば、w * x_iはbを含まないので、bで微分すると0になります。

∂b / ∂b = 1

日本語で言えば、bをbで微分すると1になります。

∂y_i / ∂b = 0

日本語で言えば、y_iはbではないので、bで微分すると0になります。

したがって、次のようになります。

∂e_i / ∂b = 0 + 1 - 0 = 1

日本語で言えば、e_iをbで微分すると1になります。

元の式に戻します。

∂J / ∂b = (1 / n) * Σ_{i=1}^{n} 2 * e_i * 1

日本語で言えば、b方向の傾きは、各データの誤差を2倍して平均したものです。

整理します。

∂J / ∂b = (2 / n) * Σ_{i=1}^{n} e_i

日本語で言えば、bについての偏微分は、誤差を全データで合計し、2 / nを掛けたものです。

e_iを元に戻します。

∂J / ∂b = (2 / n) * Σ_{i=1}^{n} (w * x_i + b - y_i)

日本語で言えば、b方向の勾配は、予測値と正解値の差を全データで合計し、2 / nを掛けたものです。

予測値ŷ_iを使うなら、次のようにも書けます。

∂J / ∂b = (2 / n) * Σ_{i=1}^{n} (ŷ_i - y_i)

日本語で言えば、b方向の勾配は、予測値と正解値の差そのものを平均的に見た値です。

線形回帰の更新式

ここまでで、wとbの勾配が分かりました。

あとは、勾配降下法の基本式に代入します。

wの更新式です。

w_{t+1} = w_t - η * (2 / n) * Σ_{i=1}^{n} (w_t * x_i + b_t - y_i) * x_i

日本語で言えば、次のwは、現在のwから、学習率とw方向の勾配を掛けたものを引いて求めます。

bの更新式です。

b_{t+1} = b_t - η * (2 / n) * Σ_{i=1}^{n} (w_t * x_i + b_t - y_i)

日本語で言えば、次のbは、現在のbから、学習率とb方向の勾配を掛けたものを引いて求めます。

この2つの式が、線形回帰を勾配降下法で学習するときの基本です。

難しく見えるかもしれません。

でも、やっていることはシンプルです。

予測する。

間違いを見る。

間違いが減る方向へwとbを少し動かす。

これだけです。

具体例で1回だけ更新してみる

では、実際に数値を使って、wとbを1回更新してみましょう。

データは次の4つです。

ix_iy_i
112
223
334
445

初期値を次のようにします。

w_0 = 0

日本語で言えば、最初の重みは0です。

b_0 = 0

日本語で言えば、最初のバイアスは0です。

学習率は次のようにします。

η = 0.01

日本語で言えば、1回の更新で勾配の1%だけ動かす設定です。

予測値を計算します。

ŷ_i = w_0 * x_i + b_0

日本語で言えば、初期状態ではwもbも0なので、すべての予測値は0になります。

ix_iy_iŷ_ie_i = ŷ_i - y_i
1120-2
2230-3
3340-4
4450-5

まず、初期状態の損失を計算します。

J(w_0, b_0) = (1 / 4) * ((-2)^2 + (-3)^2 + (-4)^2 + (-5)^2)

日本語で言えば、4つの誤差をそれぞれ二乗して平均します。

J(w_0, b_0) = (1 / 4) * (4 + 9 + 16 + 25)

日本語で言えば、二乗誤差は4、9、16、25です。

J(w_0, b_0) = 54 / 4 = 13.5

日本語で言えば、初期状態の平均二乗誤差は13.5です。

次に、w方向の勾配を計算します。

∂J / ∂w = (2 / 4) * Σ_{i=1}^{4} e_i * x_i

日本語で言えば、w方向の勾配は、誤差と入力値を掛けたものの合計に2 / 4を掛けます。

各項を計算します。

e_1 * x_1 = -2 * 1 = -2

日本語で言えば、1番目の誤差と入力値の積は-2です。

e_2 * x_2 = -3 * 2 = -6

日本語で言えば、2番目の誤差と入力値の積は-6です。

e_3 * x_3 = -4 * 3 = -12

日本語で言えば、3番目の誤差と入力値の積は-12です。

e_4 * x_4 = -5 * 4 = -20

日本語で言えば、4番目の誤差と入力値の積は-20です。

合計します。

Σ_{i=1}^{4} e_i * x_i = -2 + (-6) + (-12) + (-20) = -40

日本語で言えば、誤差と入力値の積の合計は-40です。

したがって、w方向の勾配は次の通りです。

∂J / ∂w = (2 / 4) * (-40) = -20

日本語で言えば、w方向の勾配は-20です。

次に、b方向の勾配を計算します。

∂J / ∂b = (2 / 4) * Σ_{i=1}^{4} e_i

日本語で言えば、b方向の勾配は、誤差の合計に2 / 4を掛けます。

誤差を合計します。

Σ_{i=1}^{4} e_i = -2 + (-3) + (-4) + (-5) = -14

日本語で言えば、4つの誤差の合計は-14です。

したがって、b方向の勾配は次の通りです。

∂J / ∂b = (2 / 4) * (-14) = -7

日本語で言えば、b方向の勾配は-7です。

更新式に代入します。

w_1 = w_0 - η * (∂J / ∂w)

日本語で言えば、次のwは、今のwから、学習率とw方向の勾配を掛けたものを引きます。

w_1 = 0 - 0.01 * (-20)

日本語で言えば、w方向の勾配が-20なので、0から-0.2を引く形になります。

w_1 = 0.2

日本語で言えば、更新後のwは0.2です。

bも更新します。

b_1 = b_0 - η * (∂J / ∂b)

日本語で言えば、次のbは、今のbから、学習率とb方向の勾配を掛けたものを引きます。

b_1 = 0 - 0.01 * (-7)

日本語で言えば、b方向の勾配が-7なので、0から-0.07を引く形になります。

b_1 = 0.07

日本語で言えば、更新後のbは0.07です。

更新後に損失が下がったか確認する

更新後のモデルは次の通りです。

ŷ_i = 0.2 * x_i + 0.07

日本語で言えば、更新後の予測値は、入力x_iに0.2を掛け、0.07を足したものです。

新しい予測値を計算します。

ix_iy_iŷ_i = 0.2 * x_i + 0.07e_i = ŷ_i - y_ie_i^2
1120.27-1.732.9929
2230.47-2.536.4009
3340.67-3.3311.0889
4450.87-4.1317.0569

二乗誤差を合計します。

2.9929 + 6.4009 + 11.0889 + 17.0569 = 37.5396

日本語で言えば、更新後の二乗誤差の合計は37.5396です。

MSEを計算します。

J(w_1, b_1) = 37.5396 / 4 = 9.3849

日本語で言えば、更新後の平均二乗誤差は9.3849です。

初期状態の損失は13.5でした。

13.5 -> 9.3849

日本語で言えば、損失が13.5から9.3849へ下がりました。

つまり、wとbを1回更新しただけで、モデルは少し正解に近づいたのです。

これが勾配降下法の感覚です。

一気に完璧を目指すな。

少しずつ下りましょう!

学習率が大きすぎるとどうなるか

学習率ηは、勾配降下法でとても重要です。

更新式をもう一度見てください。

θ_{t+1} = θ_t - η * ∇J(θ_t)

日本語で言えば、学習率ηが大きいほど、1回の更新で大きく動きます。

学習率が大きすぎると、谷底を飛び越えてしまうことがあります。

たとえば、山を下っているのに、1歩が大きすぎて、谷を越えて反対側の斜面まで行ってしまうイメージです。

場合によっては、損失が下がるどころか増えていきます。

η = large

日本語で言えば、学習率が大きすぎる状態です。

J(θ_{t+1}) > J(θ_t)

日本語で言えば、更新後の損失が更新前より大きくなってしまう場合があります。

この状態が続くと、学習は不安定になります。

さらに悪い場合、損失がどんどん大きくなる発散が起こります。

発散とは、損失が小さくならず、むしろ大きくなっていく状態です。

学習率が小さすぎるとどうなるか

逆に、学習率が小さすぎる場合も問題です。

η = small

日本語で言えば、学習率が小さすぎる状態です。

この場合、1回の更新量がとても小さくなります。

谷底には向かっていますが、進むスピードが遅すぎます。

|θ_{t+1} - θ_t| ≈ 0

日本語で言えば、更新前後のパラメータの差がほとんどない状態です。

山下りでたとえるなら、1歩が1ミリしかないようなものです。

いつかは着くかもしれません。

でも、時間がかかりすぎます。

実務では、学習に時間がかかりすぎるとコストも増えます。

そのため、学習率は大きすぎても小さすぎても困るのです。

適切な学習率のイメージ

学習率状態起こりやすい問題
大きすぎる一歩が大きい振動、発散
小さすぎる一歩が小さい学習が遅い
適切ほどよい一歩安定して損失が下がる

学習率は、AI学習のアクセルです。

強く踏みすぎると事故ります。

弱すぎると進みません。

ほどよい強さで踏む必要があります。

勾配降下法の種類

勾配降下法には、いくつか種類があります。

違いは、勾配を計算するときに、どれだけのデータを使うかです。

バッチ勾配降下法

バッチ勾配降下法は、すべてのデータを使って勾配を計算します。

θ_{t+1} = θ_t - η * (1 / n) * Σ_{i=1}^{n} ∇L_i(θ_t)

日本語で言えば、全データの勾配を平均してから、パラメータを更新します。

全員の意見を聞いてから決める会議のようなものです。

安定しやすい一方で、データが多いと計算が重くなります。

確率的勾配降下法

確率的勾配降下法は、1つのデータだけを使って勾配を計算します。

θ_{t+1} = θ_t - η * ∇L_i(θ_t)

日本語で言えば、1つのデータから計算した勾配だけで、パラメータを更新します。

1人の意見を聞いてすぐ動くようなものです。

更新は速いですが、動きが不安定になりやすいです。

ミニバッチ勾配降下法

ミニバッチ勾配降下法は、一部のデータのまとまりを使って勾配を計算します。

θ_{t+1} = θ_t - η * (1 / m) * Σ_{i∈B} ∇L_i(θ_t)

日本語で言えば、Bという小さなデータのまとまりに含まれるm個のデータを使って勾配を平均し、パラメータを更新します。

クラス全員ではなく、班ごとに意見を聞くようなものです。

実務では、ミニバッチ勾配降下法がよく使われます。

種類使うデータ特徴
バッチ勾配降下法全データ安定しやすいが重い
確率的勾配降下法1データ速いが不安定になりやすい
ミニバッチ勾配降下法一部のデータ速度と安定性のバランスがよい

勾配降下法の全体手順

勾配降下法の流れをまとめると、次のようになります。

initialize θ_0
for t = 0, 1, 2, ..., T - 1:
    compute J(θ_t)
    compute ∇J(θ_t)
    θ_{t+1} = θ_t - η * ∇J(θ_t)

日本語で言えば、最初にパラメータを決め、損失を計算し、勾配を計算し、損失が小さくなる方向へパラメータを更新する流れを繰り返します。

停止条件を入れるなら、次のように考えます。

|J(θ_{t+1}) - J(θ_t)| < ε

日本語で言えば、更新前後の損失の変化が十分小さくなったら、学習を止めるという意味です。

εは「イプシロン」と読みます。

非常に小さな値を表すときによく使います。

たとえば、損失がほとんど変わらなくなったら、「もうだいたい谷底に近づいた」と判断できます。

新人エンジニアがつまずきやすいポイント

つまずき原因理解のコツ
なぜマイナスするのか分からない勾配が損失の増える方向を示すため下るには坂の上り方向と逆へ進む
微分が急に出てきて混乱する損失の変化量を知る必要があるため微分は傾きを調べる道具と考える
学習率の意味が分からない更新量を決める係数だから山下りの一歩の大きさと考える
偏微分が難しい複数のパラメータを扱うため1つずつ動かして影響を見ると考える
損失が下がらない理由が分からない学習率、データ、モデル構造などが影響する更新前後の損失と勾配を確認する

勾配降下法で一番大切なのは、式を丸暗記することではありません。

損失が小さくなる方向へ、少しずつパラメータを動かすというイメージです。

式は、そのイメージを正確に実行するための道具です。

第2章のまとめ

今回は、勾配降下法について解説しました。

勾配降下法とは、損失関数を小さくするために、パラメータを少しずつ更新する方法です。

基本式は次の通りです。

θ_{t+1} = θ_t - η * ∇J(θ_t)

日本語で言えば、次のパラメータは、現在のパラメータから、学習率と勾配を掛けたものを引いて求めます。

線形回帰では、次の更新式を使います。

w_{t+1} = w_t - η * (2 / n) * Σ_{i=1}^{n} (w_t * x_i + b_t - y_i) * x_i

日本語で言えば、wは、予測誤差に入力値を掛けた勾配を使って更新します。

b_{t+1} = b_t - η * (2 / n) * Σ_{i=1}^{n} (w_t * x_i + b_t - y_i)

日本語で言えば、bは、予測誤差そのものを使って更新します。

用語意味
勾配損失が増える方向と大きさ
勾配降下法勾配の逆方向へ進んで損失を減らす方法
学習率1回の更新でどれくらい動くかを決める値
偏微分1つのパラメータだけを動かしたときの変化を見る方法
ミニバッチ一部のデータを使って勾配を計算する方法

勾配降下法は、AIが学習するうえで中心となる考え方です。

損失関数が「どれくらい間違ったか」を測るものなら、勾配降下法は「どう直せばよいか」を決める方法です。

今後の学習では、今回の線形回帰の更新式を手計算で2回、3回と繰り返してみましょう。その後、学習率を変えると損失の下がり方がどう変わるかを確認すると、次章の「線形回帰で学ぶ勾配降下法」がより深く理解できます!

投稿者プロフィール

山崎講師
山崎講師代表取締役
セイ・コンサルティング・グループ株式会社代表取締役。
岐阜県出身。
海外放浪の末、2000年創業、2004年会社設立。
IT企業向け人材育成研修歴業界歴20年以上。
すべての無駄を省いた費用対効果の高い「筋肉質」な研修を提供します!
この記事に間違い等ありましたらぜひお知らせください。

学生時代は趣味と実益を兼ねてリゾートバイトにいそしむ。長野県白馬村に始まり、志賀高原でのスキーインストラクター、沖縄石垣島、北海道トマム。高じてオーストラリアのゴールドコーストでツアーガイドなど。現在は野菜作りにはまっている。