クリーム色の背景、色付き表示、高コントラスト、大きな文字のほうが読みやすいですか?配色と文字を選ぶと、すべてのページに一度で反映されます。

無料レッスン

SciPy の最適化と行き詰まり

このレッスンのあとで: SciPy で最小値を探し、勾配降下法が行き詰まる場合を見分けることができる。

60分のレッスンコマンド3件JupyterLab データサイエンスラボ:pandas、Matplotlib、scikit-learn をブラウザーで

局所最小とは、近くでだけいちばん低い点

局所最小(きょくしょさいしょう)とは、すぐ近くでは最も低いが、遠くにもっと低い点があるかもしれない谷底のことです。勾配降下法は、出発点に近い谷へ入ると、そこで止まります。

SciPy の最適化の道具を使うと、少ない書き方で最小値を探せます。ただし道具も、行き詰まりは避けられません。何が起きるかを知っておきます。

このレッスンのゴール

メモ

SciPy で最小値を探し、勾配降下法が行き詰まる場合を見分けることができる。

キーワード

ことばいみ
局所最小近くでは最も低いが、全体では最も低いとは限らない点
大域最小関数全体で、いちばん低い点
平らな所傾きが 0 でも、最小とは限らない点
発散更新のたびに値が大きく離れていくこと
最適化関数の値を最小や最大にする入力を探すこと

学生が入力するセルは、このプレビューでは空白です。

谷が2つあると、出発点で行き先が変わる

関数 f(x) = x⁴ − 3x² + x は、谷が2つあります。右の谷は x が約 1.131 で、値は −1.07 です。左の谷は x が約 −1.301 で、値は −3.514 と、さらに低いです。

勾配降下法は、足元の坂を下るだけです。出発点が右にあれば右の谷、左にあれば左の谷に入ります。

例: 出発点ごとの行き先

出発点行き着く xそこでの値全体で最も低いか
21.131−1.07いいえ(局所最小)
−2−1.301−3.514はい(大域最小)
0.1−1.301−3.514はい(大域最小)

学生が入力するセルは、このプレビューでは空白です。

出発点を変えて行き先を見る

コード: python
# 谷が2つある関数 f(x) = x⁴ - 3x² + x。傾きは 4x³ - 6x + 1 です。
def slope(x):
    return 4 * x ** 3 - 6 * x + 1

for start in [2.0, -2.0]:
    x = start
    for step in range(2000):
        x = x - 0.01 * slope(x)
    print("出発点", start, "から行き着いた x =", round(x, 3))
# 出発点を 0.1 に変えて、行き先を予想してから実行してください。

SciPy で出発点 2 から最小値を探す

コマンド
docker exec jupyter python3 -c "from scipy.optimize import minimize; r = minimize(lambda x: x[0] ** 4 - 3 * x[0] ** 2 + x[0], [2.0]); print(round(r.x[0], 3), round(r.fun, 3), r.success)"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

出発点 −2 から探す

コマンド
docker exec jupyter python3 -c "from scipy.optimize import minimize; r = minimize(lambda x: x[0] ** 4 - 3 * x[0] ** 2 + x[0], [-2.0]); print(round(r.x[0], 3), round(r.fun, 3), r.success)"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

SciPy の minimize は出発点から探す

scipy.optimize.minimize は、関数と出発点を渡すと、最小値を探して結果を返します。x が見つけた位置、fun がその値、success が「探索が終わった」という印です。

成功と表示されても、見つけたのは出発点に近い谷です。全体で最も低いとは、限りません。

傾きが 0 でも最小とは限らない

最小値の点では傾きが 0 になりますが、逆は成り立ちません。f(x) = x³ は、x = 0 で傾きが 0 ですが、左へ行くほど値が下がり、最小ではありません。

勾配降下法は、傾きが 0 の点で動けなくなります。傾きがとても小さい平らな所でも、更新が進まず、止まって見えます。

傾き 0 の点では更新で動かない

コマンド
docker exec jupyter python3 -c "x = 0.0; print(x - 0.1 * 3 * x ** 2)"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

学習率が大きすぎると値が発散する

学習率が大きすぎると、更新のたびに値が谷を飛び越えて、大きく離れていきます。コンピュータは、そのまま計算を続けて、とても大きな数を作ります。

そこで、値の大きさに上限を決めておき、超えたら「発散」とみなして止めます。止まったら、学習率を下げてやり直します。

発散を見つけて止める

コード: python
# 同じ関数を、学習率 0.01 と 0.2 で試します。|x| が 100 を超えたら発散とみなします。
def slope(x):
    return 4 * x ** 3 - 6 * x + 1

for rate in [0.01, 0.2]:
    x = 2.0
    blown_up = 0
    step = 0
    while step < 100 and blown_up == 0:
        step = step + 1
        x = x - rate * slope(x)
        if abs(x) > 100:
            blown_up = step
    if blown_up > 0:
        print("学習率", rate, ":", blown_up, "回目で発散")
    else:
        print("学習率", rate, ": 収束 x =", round(x, 3))
# 学習率を 0.05 に変えて、どうなるか見てください。

例: 行き詰まりの種類と対策

様子原因対策
浅い谷で止まる局所最小出発点を変えて、何度も試す
ほとんど動かない平らな所、小さすぎる学習率学習率を少し上げる、出発点を変える
値が大きく離れる大きすぎる学習率学習率を下げて、上限を決める

学生が入力するセルは、このプレビューでは空白です。

よくある間違い

注意

止まった点は、全体で最も低い点だと考えがちです。実際は、近くの谷で止まっただけかもしれません。出発点を変えて何度か試し、行き先をくらべます。

このラボとソースについて: JupyterLab データサイエンスラボ:pandas、Matplotlib、scikit-learn をブラウザーで

授業で使いますか?このモジュールを学生に割り当てると、教員用ガイド、自動採点つきの課題、学生ごとのラボを使えます。