# 通知設計書 7-EarlyStopping

## 概要

本ドキュメントは、TensorFlow Kerasの`EarlyStopping`コールバックに関する通知設計書である。`EarlyStopping`は監視メトリクスの改善停止を検知し、トレーニング停止を通知する。

### 本通知の処理概要

`EarlyStopping`は、指定した監視メトリクスが`patience`エポック数分改善しなかった場合に`model.stop_training = True`を設定してトレーニングを早期終了させるコールバックである。オプションでベストエポックの重みに復元する機能も提供する。

**業務上の目的・背景**：機械学習モデルのトレーニングでは、一定以上学習を続けると過学習が進行しモデル性能が劣化する。`EarlyStopping`は最適な学習終了ポイントを自動検出し、不要な学習の継続を防止することで、計算リソースの節約とモデル品質の維持を両立する。

**通知の送信タイミング**：各エポック終了時（`on_epoch_end`）に監視メトリクスを取得し、改善の有無を判定する。`patience`回連続で改善がなければ`model.stop_training = True`を設定する。`on_train_end`で停止メッセージを出力する。

**通知の受信者**：Kerasモデル（`self.model`）。`model.stop_training = True`の設定によりトレーニングループに停止を通知する。`verbose > 0`の場合は標準出力にもメッセージを出力する。

**通知内容の概要**：トレーニング早期停止の判定結果。停止時にはエポック番号、およびオプションでベスト重みの復元が実行される。

**期待されるアクション**：トレーニングが自動停止し、ユーザは結果を確認する。`restore_best_weights=True`の場合はベストエポックのモデル重みが自動復元される。

## 通知種別

アプリ内通知（`model.stop_training`フラグ設定 + 標準出力メッセージ）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 高 |
| リトライ | 無し |

### 送信先決定ロジック

常にトレーニング中のモデル（`self.model`）に対して`stop_training`フラグを設定する。

## 通知テンプレート

### メール通知の場合

該当なし

### 本文テンプレート

```
# 早期停止時（verbose > 0）
Epoch 00015: early stopping

# ベスト重み復元時（verbose > 0, restore_best_weights=True）
Restoring model weights from the end of the best epoch.
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| monitor | 監視メトリクス名 | コンストラクタ引数（デフォルト: 'val_loss'） | Yes |
| patience | 改善待機エポック数 | コンストラクタ引数（デフォルト: 0） | Yes |
| min_delta | 改善と見なす最小変化量 | コンストラクタ引数（デフォルト: 0） | No |
| mode | 'auto' / 'min' / 'max' | コンストラクタ引数（デフォルト: 'auto'） | No |
| baseline | ベースライン値 | コンストラクタ引数 | No |
| restore_best_weights | ベスト重み復元の有無 | コンストラクタ引数（デフォルト: False） | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| トレーニング開始 | on_train_begin | 常に発火 | wait, stopped_epoch, best値の初期化 |
| エポック終了 | on_epoch_end | wait >= patience | 早期停止判定 |
| トレーニング終了 | on_train_end | stopped_epoch > 0 かつ verbose > 0 | 停止メッセージ出力 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 監視メトリクスがlogsに存在しない | 警告を出力し判定をスキップ |
| メトリクスが改善中 | waitカウンタをリセットし停止しない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[on_train_begin] --> B[wait=0, best初期化]
    B --> C[on_epoch_end]
    C --> D[get_monitor_value: 監視メトリクス取得]
    D --> E{メトリクス取得可能?}
    E -->|No| F[警告出力, return]
    E -->|Yes| G[wait += 1]
    G --> H{_is_improvement: 改善あり?}
    H -->|Yes| I[best更新, ベスト重み保存]
    I --> J{baseline超過?}
    J -->|Yes| K[wait = 0]
    J -->|No| L[waitはそのまま]
    H -->|No| L
    K --> M{wait >= patience?}
    L --> M
    M -->|No| C
    M -->|Yes| N[model.stop_training = True]
    N --> O{restore_best_weights?}
    O -->|Yes| P[model.set_weights: ベスト重み復元]
    O -->|No| Q[on_train_end]
    P --> Q
    Q --> R{stopped_epoch > 0 かつ verbose > 0?}
    R -->|Yes| S[早期停止メッセージ出力]
    R -->|No| T[終了]
    S --> T
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし（インメモリ処理のみ）

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 監視メトリクス不在 | logsに監視メトリクスが含まれない | 警告ログ出力、利用可能なメトリクス名を表示 |
| modeの不正値 | 'auto', 'min', 'max'以外 | 警告出力してautoモードにフォールバック |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 該当なし |
| リトライ間隔 | 該当なし |
| リトライ対象エラー | 該当なし |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし

## セキュリティ考慮事項

特になし。メトリクス値のみを扱う。

## 備考

- `min_delta`はモードに応じて符号が調整される（`np.greater`時は正、`np.less`時は負）
- `restore_best_weights=True`の場合、ベストエポックの重みがメモリに保持される（メモリ使用量に注意）
- `baseline`を指定すると、baselineを超えない限りwaitがリセットされない

---

## コードリーディングガイド

本通知を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | callbacks.py | `tensorflow/python/keras/callbacks.py` | `EarlyStopping.__init__`（行1755-1793）。monitor, patience, min_delta, wait, stopped_epoch, best_weights等 |

**読解のコツ**: `monitor_op`（np.less/np.greater）と`min_delta`の符号調整（行1790-1793）がポイント。`_is_improvement`メソッドで`monitor_value - self.min_delta`と`reference_value`を比較する。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | callbacks.py | `tensorflow/python/keras/callbacks.py` | `on_train_begin`（行1795-1800）。wait, stopped_epoch, best, best_weightsの初期化 |
| 2-2 | callbacks.py | `tensorflow/python/keras/callbacks.py` | `on_epoch_end`（行1802-1825）。早期停止判定の中核ロジック |

**主要処理フロー**:
1. **行1803**: `current = self.get_monitor_value(logs)` で監視メトリクス取得
2. **行1810**: `self.wait += 1` で待機カウンタ増加
3. **行1811**: `self._is_improvement(current, self.best)` で改善判定
4. **行1812-1817**: 改善時のbest更新、best_weights保存、wait リセット
5. **行1819-1825**: `wait >= patience`で停止判定、重み復元

#### Step 3: 補助メソッドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | callbacks.py | `tensorflow/python/keras/callbacks.py` | `get_monitor_value`（行1831-1838）。logsからの監視メトリクス取得と警告出力 |
| 3-2 | callbacks.py | `tensorflow/python/keras/callbacks.py` | `_is_improvement`（行1840-1841）。min_delta考慮の改善判定 |

### プログラム呼び出し階層図

```
model.fit()
    |
    +-- CallbackList.on_train_begin()
    |       +-- EarlyStopping.on_train_begin()  # wait=0, best初期化
    |
    +-- [エポックループ]
    |       +-- CallbackList.on_epoch_end()
    |               +-- EarlyStopping.on_epoch_end()
    |                       +-- get_monitor_value(logs)
    |                       +-- _is_improvement(current, best)
    |                       +-- [改善時] model.get_weights()  # best_weights保存
    |                       +-- [停止時] model.stop_training = True
    |                       +-- [停止時] model.set_weights(best_weights)
    |
    +-- CallbackList.on_train_end()
            +-- EarlyStopping.on_train_end()
                    +-- print("Epoch N: early stopping")
```

### データフロー図

```
[入力]                     [処理]                          [出力]

エポック終了時のlogs   ---> EarlyStopping.on_epoch_end() ---> model.stop_training = True
  {val_loss: 0.45}         1. 監視メトリクス取得                (patience超過時)
                           2. 改善判定
                           3. waitカウンタ管理           ---> model重み復元
                           4. patience比較                    (restore_best_weights時)

                                                         ---> 標準出力メッセージ
                                                              "Epoch N: early stopping"
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| callbacks.py | `tensorflow/python/keras/callbacks.py` | ソース | EarlyStoppingクラス定義 |
