# 通知設計書 5-ModelCheckpoint

## 概要

本ドキュメントは、TensorFlow Kerasの`ModelCheckpoint`コールバックに関する通知設計書である。`ModelCheckpoint`はモデルの重みまたはモデル全体を定期的に保存し、保存完了を通知する。

### 本通知の処理概要

`ModelCheckpoint`は、トレーニング中にモデルの重みまたはモデル全体を定期的にチェックポイントとして保存するコールバックである。エポック終了時またはN バッチごとに保存を行い、保存結果をユーザに通知する。

**業務上の目的・背景**：長時間のトレーニングでは、障害や中断に備えてモデルの状態を定期的に保存することが不可欠である。また、ベストモデル（監視メトリクスが最良のモデル）のみを保存する機能により、最も性能の良いモデルを自動的に選択・保存できる。

**通知の送信タイミング**：`save_freq='epoch'`の場合はエポック終了時（`on_epoch_end`）、整数値の場合はNバッチごと（`on_train_batch_end`）に保存を実行する。`verbose > 0`の場合、保存結果（改善/非改善）をコンソールに出力する。

**通知の受信者**：ファイルシステム（チェックポイントファイルの書き出し）、および`verbose > 0`の場合は標準出力を監視するユーザ。

**通知内容の概要**：モデル重みまたは全モデルのチェックポイントファイル。`save_best_only=True`の場合は監視メトリクスの改善状況も通知。

**期待されるアクション**：障害発生時にチェックポイントからトレーニングを再開する。ベストモデルを本番環境にデプロイする。

## 通知種別

ファイル出力通知（チェックポイントファイルの保存） + 標準出力通知（verbose時）

## 送信仕様

### 基本情報

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

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

`filepath`引数で指定されたパスにチェックポイントを保存する。filepathには`{epoch:02d}`や`{val_loss:.2f}`等のプレースホルダを使用可能。分散トレーニング時は`distributed_file_utils.write_filepath`でチーフワーカーのみが書き込む。

## 通知テンプレート

### メール通知の場合

該当なし

### 本文テンプレート

```
# save_best_only=True かつ改善時
Epoch 00005: val_loss improved from 0.50000 to 0.45000, saving model to /path/to/checkpoint

# save_best_only=True かつ非改善時
Epoch 00005: val_loss did not improve from 0.45000

# save_best_only=False
Epoch 00005: saving model to /path/to/checkpoint
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| チェックポイントファイル | TF SavedModel / HDF5 / Checkpoint | save_weighs_onlyの設定による | モデル重みまたはモデル全体 |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| filepath | 保存先パス | コンストラクタ引数 | Yes |
| monitor | 監視メトリクス名 | コンストラクタ引数（デフォルト: 'val_loss'） | No |
| epoch | エポック番号 | on_epoch_endの引数 | Yes |
| logs | メトリクス辞書 | on_epoch_end/on_train_batch_endの引数 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| エポック終了 | on_epoch_end | save_freq == 'epoch' | エポック終了時に保存 |
| バッチ終了 | on_train_batch_end | save_freq が整数かつ _should_save_on_batch | Nバッチごとに保存 |
| トレーニング開始 | on_train_begin | load_weights_on_restart == True | 既存チェックポイントの復元 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| save_best_only=True かつ改善なし | 監視メトリクスが改善しなかった場合は保存をスキップ |
| period未達 | 非推奨のperiod引数使用時、epochs_since_last_save < period の場合スキップ |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[トリガー発生: epoch_end / batch_end] --> B[_save_model呼び出し]
    B --> C[logs同期変換]
    C --> D[ファイルパス生成: _get_file_path]
    D --> E{save_best_only?}
    E -->|Yes| F{監視メトリクス取得可能?}
    F -->|No| G[警告出力、スキップ]
    F -->|Yes| H{メトリクス改善?}
    H -->|Yes| I[モデル保存]
    H -->|No| J[スキップ、verbose時メッセージ出力]
    E -->|No| I
    I --> K{save_weights_only?}
    K -->|Yes| L[model.save_weights]
    K -->|No| M[model.save]
    L --> N[_maybe_remove_file: 分散環境用クリーンアップ]
    M --> N
```

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

### 参照テーブル一覧

該当なし（ファイルシステムのみ使用）

### 更新テーブル一覧

該当なし（ファイルシステムへの書き出し）

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| IsADirectoryError | filepathがディレクトリの場合（h5py 3.x） | IOError再raiseでメッセージ付きエラー |
| IOError | filepathがディレクトリの場合（h5py 2.x） | メッセージ付きIOErrorを再raise |
| KeyError | filepath内のプレースホルダとlogsが不一致 | KeyErrorを再raiseでメッセージ付きエラー |
| TypeError | optionsの型が不正 | コンストラクタでTypeErrorをraise |

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

制限なし

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

- チェックポイントファイルにはモデルの重みが含まれるため、保存先ディレクトリのアクセス権限管理が必要
- `filepath`引数にはユーザ入力が含まれる可能性があるため、パストラバーサルに注意

## 備考

- `_chief_worker_only = False`に設定されているが、実際の保存はチーフワーカーのみが行い、他のワーカーは一時ディレクトリを使用して後でクリーンアップする
- `mode`パラメータで`'auto'`、`'min'`、`'max'`を選択可能。`'auto'`ではメトリクス名からモードを推定
- 非推奨の`period`引数と`load_weights_on_restart`引数がまだサポートされている

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | callbacks.py | `tensorflow/python/keras/callbacks.py` | `ModelCheckpoint.__init__`（行1273-1353）。monitor, filepath, save_best_only, save_weights_only, save_freq等の主要パラメータ |

**読解のコツ**: `mode`パラメータにより`monitor_op`（np.less/np.greater）と`best`初期値（np.inf/-np.inf）が決定される。`'auto'`モードではメトリクス名に`'acc'`が含まれるかで判定する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | callbacks.py | `tensorflow/python/keras/callbacks.py` | `on_epoch_end`（行1381-1385）。save_freq=='epoch'時の保存トリガー |
| 2-2 | callbacks.py | `tensorflow/python/keras/callbacks.py` | `on_train_batch_end`（行1374-1376）。バッチ単位保存のトリガー |
| 2-3 | callbacks.py | `tensorflow/python/keras/callbacks.py` | `_should_save_on_batch`（行1387-1402）。バッチ単位保存の条件判定 |

**主要処理フロー**:
1. **行1382**: `self.epochs_since_last_save += 1`
2. **行1384-1385**: `save_freq == 'epoch'`の場合に`_save_model`を呼び出し
3. **行1399-1401**: `_batches_seen_since_last_saving >= self.save_freq`で保存判定

#### Step 3: 保存処理の詳細を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | callbacks.py | `tensorflow/python/keras/callbacks.py` | `_save_model`（行1404-1463）。保存処理の中核ロジック |
| 3-2 | callbacks.py | `tensorflow/python/keras/callbacks.py` | `_get_file_path`（行1465-1478）。ファイルパス生成 |

**主要処理フロー**:
- **行1416-1417**: logs同期変換とepochs_since_last_saveリセット
- **行1418**: `_get_file_path`でプレースホルダ展開
- **行1421-1449**: save_best_onlyの場合の改善判定と保存分岐
- **行1433-1437**: save_weights_onlyに応じたsave_weights/save呼び出し

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

```
model.fit()
    |
    +-- CallbackList.on_epoch_end()
            +-- ModelCheckpoint.on_epoch_end()
                    +-- _save_model(epoch, logs)
                            +-- tf_utils.sync_to_numpy_or_python_type(logs)
                            +-- _get_file_path(epoch, logs)
                            |       +-- filepath.format(epoch=epoch+1, **logs)
                            |       +-- distributed_file_utils.write_filepath()
                            +-- [save_best_only判定]
                            +-- model.save_weights() / model.save()
                            +-- _maybe_remove_file()
                                    +-- distributed_file_utils.remove_temp_dir_with_filepath()
```

### データフロー図

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

epoch, logs            ---> ModelCheckpoint._save_model() ---> チェックポイントファイル
  {val_loss: 0.45}          1. ファイルパス生成                   /path/to/weights.05-0.45.h5
                            2. 改善判定（save_best_only時）
                            3. モデル保存                    ---> 標準出力メッセージ
                                                                  "Epoch 00005: val_loss
                                                                   improved from..."
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| callbacks.py | `tensorflow/python/keras/callbacks.py` | ソース | ModelCheckpointクラス定義 |
| distributed_file_utils.py | `tensorflow/python/keras/distribute/distributed_file_utils.py` | ソース | 分散トレーニング時のファイルパス管理 |
| checkpoint_management.py | `tensorflow/python/checkpoint/checkpoint_management.py` | ソース | latest_checkpoint関数 |
| checkpoint_options.py | `tensorflow/python/checkpoint/checkpoint_options.py` | ソース | CheckpointOptionsクラス |
| save_options.py | `tensorflow/python/saved_model/save_options.py` | ソース | SaveOptionsクラス |
