Loss が悪化したら学習を自動で打ち切る(Early Stopping)
「Early Stopping(早期停止)」は、学習の指標が改善しなくなったり悪化し始めたら、最後まで回さず途中で打ち切るパターンです。Loss(学習中のモデルの誤差を表す数値で、低いほどモデルが正解に近づいているサインです)が上がり始めたりNaN になったりしたら、それ以降の学習は無駄な計算になります。Arkor に Early Stopping は組み込まれていませんが、TypeScript 数行で組み立てるための材料はすべて揃っています。
このレシピは 3 つのプリミティブを組み合わせます:
- バックエンドからストリームされる loss を見る
onLog。 - そのシグナルをトレーナーに配線した
AbortController。 - ローカル Abort 後にバックエンドの学習も止める
trainer.cancel()。
パターン
arkor start(Studio の “Run training” や CLI)を使い続けるなら上のエクスポートだけで十分です: controller は依然として wait() を Abort しますが、CLI の await を自前の try / catch で囲むことはできません。バックエンドのキャンセルを保証したいなら上のパターンが安全策です。
なぜ abortSignal と cancel の両方?
abortSignal と cancel は別物です。混同するとお金を捨てるので、ドキュメントもここを明示しています。
abortSignalはローカルのwait()ループを止めます(SDK § トレーナー制御)。cancelを呼びませんし、バックエンドにも何も送らず、ジョブはマネージド GPU で走り続けます。trainer.cancel()はバックエンドにジョブの停止を依頼します。ベストエフォート: ジョブが既に終端状態(completed、failed、cancelled)にあるとリクエストは reject されることがあります。投機的に呼ぶならtry / catchで囲んでください。
abortSignal で十分。「もう課金させたくない」なら Abort の後に cancel も呼ぶこと。
バリエーション
スムージングしたしきい値。 1 ステップだけの悪い値はノイズかもしれません。クロージャー内でローリングウィンドウを保持:controller はトレーナーファイルの外からも動きます。Next.js API ルート、SIGINT ハンドラ、親プロセスから controller.abort() を呼べばオンデマンドに学習を止められます。
心に留めておくこと
- コールバック内で throw しない。 throw は SSE 再接続ループに catch されて学習が進み続けます(SDK § ライフサイクルコールバック 参照)。controller を使うこと。それが決定的なパスです。
abortSignalはバックエンドをキャンセルしない。 一番よくある落とし穴です。コストが問題ならcontroller.abort()とtrainer.cancel()を必ずペアで。lossフィールドはnumber | null。 バックエンドはメトリックスステップでしか loss を埋めません。非メトリックスフレームはnullを運びます。Number.isFiniteチェックはNaNも弾き、実用上はこちらの方が発散シグナルとしてよく出てきます。