ひとことで言うと
早期終了は、学習を無期限に続けず、検証誤差が改善しなくなった時点で反復を止める正則化です。採用するモデルは「最後に計算したもの」ではなく、検証誤差が最も小さかった時点のパラメータにできます。
坂道を下る途中で、目的地に近づいた記録を残しながら進みます。何回か進んでも記録が更新されなければ、歩き続けず、最も近かった地点へ戻る手続きです。
なぜ必要か
訓練誤差は、更新を続けるほど下がるよう最適化されます。しかし運用時の性能を直接測っているわけではないため、訓練誤差だけを停止条件にすると、学習時間の上限しか決められません。そこで各反復後に検証誤差を測り、改善が止まったら打ち切ります。学習の反復回数を制限することで、パラメータが訓練データへ合わせ込まれ過ぎる前に選択する、最も単純な正則化として働きます。
ただし検証データで停止時点を選ぶ以上、その検証誤差はモデル選択に使ったデータへの評価です。最終的な未知データの誤差より楽観的になり得るため、停止条件を調整した結果を同じ検証誤差だけで確定させません。
検証誤差を何度も見て停止点を選ぶほど、その値は「一度だけ測った評価」ではなくなります。停止条件を決めた後の評価には、学習時に使っていないデータを用います。
仕組み
反復 のパラメータを 、検証誤差を 、許容する改善幅を とします。 はモデルの全パラメータ、 は反復 の検証データ上の損失です。最小値を記録し、
を満たしたときだけ最良値とパラメータを更新します。改善しない反復が連続して 回になったら停止します。 が patience です。 のように待たなければ、検証誤差の一時的な揺れで早く止まり、学習不足になりやすいので、停止の敏感さと計算時間の兼ね合いで決めます。
停止時の実装には分岐があります。最後の をそのまま使う方法は簡単ですが、最良値を過ぎた後のパラメータかもしれません。通常は改善時にパラメータのコピーを保存し、停止後にその最良点へ戻します。ライブラリでは n_iter_no_change や tol が patience や改善幅に対応し、検証割合やスコアも停止挙動を変えます。
試験でどう問われるか
| 問われ方 | 正解に寄る条件 | 引っかけ |
|---|---|---|
| 停止条件の説明 | 検証誤差の改善が一定回数止まったら停止 | 訓練誤差が最小になったら停止 |
| patience の意味 | 改善なしを何回待つか | 学習率やバッチサイズ |
| 採用する重み | 最良検証値の時点を保存して復元できる | 停止した最終時点を必ず採用 |
| 評価上の注意 | 検証誤差は停止点選択に使ったため楽観的になり得る | 未使用の未知データと同じ扱い |
実装で確かめる
検証誤差を監視し、改善時だけ重みを保存する最小例です。patience 回待ってから、保存済みの最良値へ戻します。
import numpy as np
val_loss = [0.90, 0.72, 0.61, 0.64, 0.63, 0.66]
weights = [np.array([t]) for t in range(len(val_loss))]
best_loss, best_weight = np.inf, None
stale, patience = 0, 2
for step, (loss, weight) in enumerate(zip(val_loss, weights)):
if loss < best_loss - 1e-3:
best_loss, best_weight, stale = loss, weight.copy(), 0
else:
stale += 1
if stale >= patience:
break
print(step, best_loss, best_weight[0])
取り違えやすいもの
| 用語 | 早期終了との切り分け |
|---|---|
| L2正則化 | 損失にパラメータのペナルティを加える。反復を止める手法ではない |
| 学習率スケジューラ | 学習率を変える。停止や最良点の復元は別に指定する |
| チェックポイント | パラメータを保存する仕組み。早期終了は検証値で保存・停止を判断する |
| 最大エポック数 | 学習の上限。検証誤差の改善を見て途中停止する条件とは別 |
想起チェック
早期終了が正則化として働く理由は
更新を続ける前に、検証誤差が最も小さい時点のパラメータを選ぶためです。
patience は何を数える値か
検証誤差の改善が起きない反復を、何回まで待つかを表します。
停止後に復元する重みはどの時点のものか
停止した時点ではなく、検証誤差が最良だった時点の保存コピーです。