# 機能設計書 134-Kerasモデル保存

## 概要

本ドキュメントは、TensorFlowのKerasにおけるモデル保存機能（HDF5形式およびSavedModel形式）の機能設計について記載する。

### 本機能の処理概要

Kerasモデル保存機能は、訓練済みモデルのアーキテクチャ・重み・オプティマイザ状態をファイルに永続化し、復元する機能を提供する。

**業務上の目的・背景**：モデルの訓練は時間とリソースを大量に消費するプロセスであり、訓練結果を保存・再利用する仕組みが必須である。モデル保存機能により、訓練済みモデルの配布、本番環境へのデプロイ、訓練の中断・再開が可能となる。

**機能の利用シーン**：モデル訓練完了後の保存、チェックポイントからの再開、他の環境へのモデル移植、TFServingへのデプロイ用モデル出力、モデルの共有・配布など。

**主要な処理内容**：
1. `model.save()` / `save_model()`によるモデルの保存（SavedModel形式またはHDF5形式）
2. `load_model()`によるモデルの復元
3. HDF5形式での保存（モデル構成JSON + 重みデータ + オプティマイザ状態）
4. SavedModel形式での保存（tf.saved_model.saveベース + Keras固有メタデータ）
5. `model.save_weights()` / `model.load_weights()`による重みのみの保存・復元
6. `model_from_json()` / `model_from_yaml()` / `model_from_config()`によるアーキテクチャのみの復元

**関連システム・外部連携**：SavedModel保存（No.62）、チェックポイント保存・復元（No.64）、Kerasモデル構築API（No.131）、TFLiteモデル変換（No.80）と連携する。

**権限による制御**：ファイルシステムのアクセス権限に依存する。

## 関連画面

本機能は画面機能マッピングにおいて直接的な関連画面は定義されていない。

## 機能種別

データ永続化 / シリアライゼーション

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| model | keras.Model | Yes | 保存対象のKerasモデル | Modelインスタンスであること |
| filepath | str / pathlib.Path / h5py.File | Yes | 保存先パス | 有効なファイルパス |
| overwrite | bool | No | 既存ファイルの上書き許可（デフォルト: True） | ブール値 |
| include_optimizer | bool | No | オプティマイザ状態を含めるか（デフォルト: True） | ブール値 |
| save_format | str | No | 保存形式（'tf' or 'h5'、デフォルト: 'tf'） | 'tf' or 'h5' |
| signatures | dict | No | SavedModel用の推論シグネチャ | ConcreteFunction or dict |
| options | SaveOptions | No | 保存オプション | SaveOptionsインスタンス |
| save_traces | bool | No | トレースされた関数を保存するか（デフォルト: True） | ブール値 |

### 入力データソース

Pythonコードからのプログラム的な呼び出し。訓練済みKerasモデルインスタンス。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| SavedModel | ディレクトリ | SavedModel形式のモデルファイル群 |
| HDF5 file | .h5ファイル | HDF5形式のモデルファイル |
| loaded model | keras.Model | 復元されたKerasモデルインスタンス |

### 出力先

ファイルシステム（ローカルディスクまたはクラウドストレージ）。

## 処理フロー

### 処理シーケンス

```
1. save_model呼び出し
   └─ save_formatの判定（'tf' or 'h5'、ファイル拡張子から推定可能）

2a. SavedModel形式の場合
   └─ saved_model_save.save() 呼び出し
       └─ モデル構成（config）の保存
       └─ 変数（重み）の保存
       └─ トレースされた関数の保存
       └─ Keras固有メタデータの保存

2b. HDF5形式の場合
   └─ hdf5_format.save_model_to_hdf5() 呼び出し
       └─ モデル構成JSONの保存
       └─ 重みデータの保存
       └─ オプティマイザ状態の保存（include_optimizer=True時）

3. load_model呼び出し
   └─ 形式の自動判定
   └─ モデルの復元（構成 → 重み → オプティマイザ）
```

### フローチャート

```mermaid
flowchart TD
    A[model.save filepath] --> B{save_format判定}
    B -->|tf| C[saved_model_save.save]
    B -->|h5| D[hdf5_format.save_model_to_hdf5]
    C --> E[SavedModelディレクトリ生成]
    D --> F[HDF5ファイル生成]

    G[load_model filepath] --> H{形式判定}
    H -->|SavedModel| I[saved_model_load.load]
    H -->|HDF5| J[hdf5_format.load_model_from_hdf5]
    I --> K[復元されたModel]
    J --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-134-01 | デフォルト形式 | TF2ではSavedModel形式がデフォルト | save_format未指定時 |
| BR-134-02 | HDF5セキュリティ | HDF5プラグインのデフォルトパスからの読み込みを無効化（ZDI-CAN-25480対策） | h5pyインポート時 |
| BR-134-03 | 上書き確認 | overwrite=Falseかつ既存ファイルが存在する場合、ユーザに確認を求める | overwrite=False時 |
| BR-134-04 | save_traces無効化 | save_traces=Falseの場合、カスタムクラスのロード時にcustom_objectsが必須 | save_traces=False |

### 計算ロジック

特段の計算ロジックはない。シリアライゼーション/デシリアライゼーション処理。

## データベース操作仕様

本機能にデータベース操作はない。ファイルシステムへの書き込み/読み込み操作のみ。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ImportError | 依存関係エラー | h5pyがインストールされていない場合（HDF5保存時） | pip install h5py |
| ValueError | 形式エラー | 不正なsave_formatを指定した場合 | 'tf' or 'h5'を指定 |
| IOError | IOエラー | 保存先にアクセスできない場合 | ファイルパス・権限の確認 |
| ValueError | 復元エラー | custom_objectsが不足している場合 | 必要なカスタムクラスを指定 |

### リトライ仕様

該当なし。

## トランザクション仕様

該当なし。ファイル書き込みはアトミックではないため、書き込み中の中断でファイルが破損する可能性がある。

## パフォーマンス要件

大規模モデルの保存はディスクI/Oがボトルネックとなる。HDF5_OBJECT_HEADER_LIMITが64512バイトに設定されており、これを超えるレイヤー設定はJSONとして分割保存される。

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

- HDF5プラグインのデフォルトパス読み込みは脆弱性（ZDI-CAN-25480）対策として無効化されている（save.py 28-33行目、hdf5_format.py 36-43行目）
- model_from_yamlは任意コード実行の危険性があるため、信頼できないソースからのYAMLは使用しないこと
- load_modelのcustom_objectsに信頼できないオブジェクトを指定しないこと

## 備考

- h5pyライブラリはオプション依存関係であり、HDF5保存を使用しない場合はインストール不要
- SavedModel形式はTFServingでの推論に直接使用可能
- `save_traces=False`を指定すると保存時間とディスク使用量を削減できるが、ロード時にカスタムクラス定義が必要

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | save.py | `tensorflow/python/keras/saving/save.py` | save_model/load_model関数のインターフェース定義 |

**読解のコツ**: save_formatの判定ロジックに注目。ファイル拡張子、h5pyオブジェクト、明示的な指定のいずれかで形式が決まる。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | save.py | `tensorflow/python/keras/saving/save.py` | save_model（37行目）、load_model |

**主要処理フロー**:
1. **37-44行目**: save_model関数のシグネチャ定義
2. **46-93行目**: docstring - SavedModelとHDF5の保存内容・違いの説明
3. ZDI-CAN-25480対策としてHDF5_PLUGIN_PATH='disable'を設定（28-33行目）

#### Step 3: HDF5保存を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | hdf5_format.py | `tensorflow/python/keras/saving/hdf5_format.py` | save_model_to_hdf5（55行目）、load_model_from_hdf5 |

**主要処理フロー**:
- **55行目**: save_model_to_hdf5 - モデル構成JSON + 重み + オプティマイザ状態の保存
- HDF5_OBJECT_HEADER_LIMIT = 64512（41行目）

#### Step 4: SavedModel保存を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | saved_model_experimental.py | `tensorflow/python/keras/saving/saved_model_experimental.py` | SavedModel形式の保存・復元 |

#### Step 5: ユーティリティを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | saving_utils.py | `tensorflow/python/keras/saving/saving_utils.py` | 保存ユーティリティ関数 |
| 5-2 | model_config.py | `tensorflow/python/keras/saving/model_config.py` | model_from_config/json/yaml |

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

```
model.save(filepath) / save_model(model, filepath)
    |
    +-- save.py: save_model()
    |       |
    |       +-- [SavedModel形式]
    |       |       +-- saved_model_save.save()
    |       |
    |       +-- [HDF5形式]
    |               +-- hdf5_format.save_model_to_hdf5()
    |                       +-- model.get_config() -> JSON
    |                       +-- model.get_weights() -> HDF5 datasets
    |                       +-- optimizer.get_config() -> JSON
    |
load_model(filepath)
    |
    +-- save.py: load_model()
            |
            +-- [SavedModel形式]
            |       +-- saved_model_load.load()
            |
            +-- [HDF5形式]
                    +-- hdf5_format.load_model_from_hdf5()
                            +-- model_from_config(config)
                            +-- model.set_weights()
```

### データフロー図

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

keras.Model         ---> save_model()               ---> SavedModel dir / .h5 file
  - config (JSON)        |
  - weights (ndarray)    +-> hdf5_format
  - optimizer state      +-> saved_model_save

filepath            ---> load_model()               ---> keras.Model
                         |
                         +-> hdf5_format.load
                         +-> saved_model_load.load
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| save.py | `tensorflow/python/keras/saving/save.py` | ソース | save_model/load_modelエントリーポイント |
| hdf5_format.py | `tensorflow/python/keras/saving/hdf5_format.py` | ソース | HDF5形式保存・復元 |
| saving_utils.py | `tensorflow/python/keras/saving/saving_utils.py` | ソース | 保存ユーティリティ |
| model_config.py | `tensorflow/python/keras/saving/model_config.py` | ソース | モデル設定からの復元 |
| saved_model_experimental.py | `tensorflow/python/keras/saving/saved_model_experimental.py` | ソース | SavedModel実験的機能 |
| __init__.py | `tensorflow/python/keras/saving/__init__.py` | ソース | モジュール定義 |
