勾配降下法とは、坂を下って最小値を探す方法
勾配降下法(こうばいこうかほう)とは、関数の値が減る向きへ少しずつ進んで、最小値を探す方法です。式を解けない関数でも、傾きさえ計算できれば使えます。
ある店の費用が、仕入れの量で変わるとします。費用がいちばん低くなる量を、傾きを頼りに、一歩ずつ探していきます。
このレッスンのゴール
メモ
学習率を決め、傾きと逆の向きへ進んで、関数の最小値に近づくことができる。
キーワード
| ことば | いみ | れい |
|---|---|---|
| 最小値 | 関数がとる値の中で、いちばん小さい値 | |
| 更新 | 今の x から、次の x を求める1回の計算 | |
| 学習率 | 1回の更新で、傾きに掛ける倍率 | 0.1 |
| 収束 | 更新をくり返して、ある値に落ち着くこと | |
| 発散 | 更新をくり返して、値が大きく離れていくこと |
学生が入力するセルは、このプレビューでは空白です。
傾きと逆の向きへ、少しだけ進む
費用が f(x) = (x − 3)² + 1 万円で、x は仕入れの量(百個)とします。傾きは 2 × (x − 3) です。x = 0 では −6 で、マイナスは「x を増やすと費用が減る」ことを意味します。
更新の式は「新しい x = x − 学習率 × 傾き」です。学習率 0.1 なら、0 − 0.1 × (−6) で 0.6 に進みます。
例: x = 0 から4回更新する(学習率 0.1)
| 回 | x | 傾き | 新しい x |
|---|---|---|---|
| 1 | 0 | −6 | 0.6 |
| 2 | 0.6 | −4.8 | 1.08 |
| 3 | 1.08 | −3.84 | 1.464 |
| 4 | 1.464 | −3.072 | 1.7712 |
学生が入力するセルは、このプレビューでは空白です。
1回目の更新を確かめる
docker exec jupyter python3 -c "print(round(0 - 0.1 * 2 * (0 - 3), 3))"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
更新をくり返して費用を下げる
# 費用 f(x) = (x - 3)² + 1 を小さくします。傾きは 2 * (x - 3) です。
x = 0.0
rate = 0.1
for step in range(1, 6):
slope = 2 * (x - 3)
x = x - rate * slope
print("回", step, "x =", round(x, 4), "費用 =", round((x - 3) ** 2 + 1, 4))
# rate を 1.1 に変えて、もう一度実行してください。
# 費用は減りますか、増えますか。
学習率が大きすぎると行き過ぎる
学習率が小さいと、安全ですが時間がかかります。大きいと、最小の位置を飛び越えます。この例では、1.0 で 6、0、6 と行ったり来たりします。
1.1 では、振れ幅が毎回大きくなり、費用が逆に増えます。値が離れていくこの状態を発散と呼びます。
例: 学習率ごとの x の動き
| 学習率 | 1回目 | 2回目 | 3回目 | 様子 |
|---|---|---|---|---|
| 0.1 | 0.6 | 1.08 | 1.464 | 3 に近づく(収束) |
| 0.5 | 3 | 3 | 3 | 1回で着く |
| 1.0 | 6 | 0 | 6 | 行ったり来たり |
| 1.1 | 6.6 | −1.32 | 8.184 | 遠ざかる(発散) |
学生が入力するセルは、このプレビューでは空白です。
学習率 1.1 の1回目を確かめる
docker exec jupyter python3 -c "print(round(0 - 1.1 * 2 * (0 - 3), 3))"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
傾きが十分小さくなったら止める
最小値では傾きが 0 になります。ただし小数の計算では、ぴったり 0 にならないことが多いです。そこで「傾きの大きさが小さな値より小さくなった」ら止めます。
さらに、回数の上限も決めておきます。発散する設定でも、いつか必ず止まります。
よくある間違い
注意
学習率は大きいほど、速く最小値に着くと考えがちです。大きすぎると、行き過ぎて費用が増えます。小さめの値から始め、費用が下がることを確かめてから、少しずつ上げます。