# 機能設計書 63-SavedModel読み込み

## 概要

本ドキュメントは、TensorFlowにおけるSavedModel形式のモデルを読み込み、推論可能な状態に復元する機能の設計を記述する。

### 本機能の処理概要

SavedModel読み込み機能は、ディスクに保存されたSavedModel形式のモデルをメモリにロードし、Pythonオブジェクトとして再構築する機能である。保存時の変数値、計算グラフ、シグネチャ、アセットを忠実に復元し、読み込まれたモデルを推論や転移学習に直接利用可能にする。

**業務上の目的・背景**：機械学習のワークフローにおいて、モデルの再利用性は生産性向上の鍵である。学習済みモデルを別のプロセスやマシンで読み込み、推論サービスの起動、転移学習のベースモデルとしての利用、モデルの検査・デバッグを行う必要がある。SavedModel読み込み機能はこれらのユースケースを実現する基盤機能である。

**機能の利用シーン**：TensorFlow Servingでの推論サービス起動、転移学習でのベースモデル読み込み、Kerasモデルのload_model、保存済みモデルの検査・デバッグ、分散学習環境でのモデル共有。

**主要な処理内容**：
1. SavedModel protobufの読み込みとパース
2. FunctionDefLibraryからのConcreteFunction復元
3. SavedObjectGraphからのTrackableオブジェクト再構築
4. チェックポイントからの変数値復元
5. 分散環境対応（DistributedVariable等のハンドリング）
6. フィンガープリントの検証

**関連システム・外部連携**：ファイルシステム（ローカル、GCS、S3等）からの読み込み。分散ストラテジーシステムとの連携。

**権限による制御**：入力ディレクトリへの読み取り権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面機能マッピングに直接該当なし（機能No.62のSavedModel保存と対をなす） |

## 機能種別

データ連携（モデルデシリアライゼーション）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| export_dir | str | Yes | SavedModelが保存されたディレクトリパス | saved_model.pb/pbtxtが存在すること |
| tags | set | No(TF1) | 読み込むMetaGraphのタグ | TF1 APIで使用 |
| options | LoadOptions | No | 読み込みオプション | LoadOptionsインスタンスであること |

### 入力データソース

ファイルシステム上のSavedModelディレクトリ（saved_model.pb、variables/、assets/）。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| loaded_object | AutoTrackable | 復元されたTrackableオブジェクト。元のオブジェクトの構造と変数値を再現 |

### 出力先

Python上のインメモリオブジェクト。

## 処理フロー

### 処理シーケンス

```
1. SavedModel protobufの読み込み
   └─ saved_model.pb (バイナリ) またはsaved_model.pbtxt (テキスト) をパース
2. FunctionDefLibraryの復元
   └─ ConcreteFunctionの再構築（_WrapperFunctionでの分散対応ラップ含む）
3. SavedObjectGraphの走査
   └─ ノードの依存関係順でソートし、再構築順序を決定
4. オブジェクトの再構築
   └─ 登録されたクラスまたはビルトイン型（Variable、Function、Asset等）に基づいてPythonオブジェクトを生成
5. エッジ（親子関係）の復元
   └─ Trackableオブジェクト間の依存関係を再接続
6. チェックポイントからの変数値復元
   └─ variables/ディレクトリから重みを読み込み
7. リソースの初期化
   └─ CapturableResource（ハッシュテーブル等）の初期化
```

### フローチャート

```mermaid
flowchart TD
    A[tf.saved_model.load 呼び出し] --> B[saved_model.pb パース]
    B --> C[FunctionDefLibrary復元]
    C --> D[SavedObjectGraph走査]
    D --> E[依存関係順ソート]
    E --> F[Pythonオブジェクト再構築]
    F --> G[エッジ復元]
    G --> H{チェックポイントスキップ?}
    H -->|No| I[変数値復元]
    H -->|Yes| J[リソース初期化]
    I --> J
    J --> K[完了: AutoTrackable返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-63-01 | ファイル形式優先順位 | pb形式を優先、存在しなければpbtxt形式を読み込む | 常時 |
| BR-63-02 | 分散変数ハンドリング | 分散ストラテジースコープ内で読み込む場合、変数はDistributedVariableとしてラップされる | strategy.scope()内での読み込み |
| BR-63-03 | ノードフィルタリング | node_filtersが指定された場合、指定されたノードとその子孫のみ読み込む | node_filters指定時 |
| BR-63-04 | 関数エイリアス復元 | experimental_load_function_aliasesが有効な場合、関数エイリアスを復元する | オプション有効時 |

### 計算ロジック

該当なし。

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

### 操作別データベース影響一覧

データベース操作は行わない。ファイルシステムからの読み込みのみ。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| IOError | ファイル不存在 | saved_model.pb/pbtxtが存在しない | 正しいexport_dirを指定 |
| IOError | パースエラー | protobufのデシリアライズに失敗 | SavedModelの整合性を確認 |
| ValueError | 不明なSavedObject型 | SavedObjectGraphに未知のkindフィールドがある | 互換性のあるTensorFlowバージョンで保存し直す |
| ValueError | ノードパスエラー | node_filtersで指定されたパスが見つからない | 正しいノードパスを指定 |

### リトライ仕様

ファイルシステムエラーの場合、ユーザー側でリトライが必要。

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

該当なし。読み込み専用操作。

## パフォーマンス要件

大規模モデルの読み込みには数十秒を要する場合がある。FunctionDefLibraryの復元がボトルネックとなりやすい。

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

- 信頼できないソースからのSavedModel読み込みには注意が必要（任意のPythonコード実行のリスク）
- フィンガープリント検証により改ざんを検出可能

## 備考

- TF1ではtf.compat.v1.saved_model.loader.load、TF2ではtf.saved_model.loadを使用
- `_LOAD_V2_LABEL`メトリクスラベルで使用状況が追跡される
- `_BUILT_IN_REGISTRATIONS`でAsset、RestoredResource、TrackableConstantがビルトイン登録される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | load.py | `tensorflow/python/saved_model/load.py` | `_BUILT_IN_REGISTRATIONS`辞書（75-78行目）でビルトイン型を確認 |
| 1-2 | load.py | `tensorflow/python/saved_model/load.py` | `_WrapperFunction`クラス（104-146行目）で分散変数のハンドリングを理解 |

**読解のコツ**: `_WrapperFunction`はConcreteFunctionを継承し、レプリカコンテキストとクロスレプリカコンテキストで異なるキャプチャ入力の解決を行う。`_call_flat`メソッドが中心。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | load.py | `tensorflow/python/saved_model/load.py` | `tf.saved_model.load()`関数のエントリーポイント |

#### Step 3: Loaderクラスの内部処理

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | load.py | `tensorflow/python/saved_model/load.py` | `Loader.__init__`（152-231行目）：初期化とロード全体の流れ |
| 3-2 | load.py | `tensorflow/python/saved_model/load.py` | `_load_all`（318-326行目）：ノード・エッジ・関数のロード |
| 3-3 | load.py | `tensorflow/python/saved_model/load.py` | `_recreate`（620-674行目）：オブジェクトの再構築 |

**主要処理フロー**:
- **152-164行目**: Loader初期化。FunctionDefLibraryのロード、ConcreteFunctionの復元
- **198-221行目**: ノードフィルタリングの処理
- **223行目**: `_load_all()`で全ノード・エッジのロード開始
- **225-226行目**: チェックポイントスキップでない場合、変数値を復元

#### Step 4: TF1互換ローダー

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | loader_impl.py | `tensorflow/python/saved_model/loader_impl.py` | `parse_saved_model`関数（76-123行目）：pb/pbtxtファイルのパース |

**主要処理フロー**:
- **90-96行目**: pbtxt、pb、cpb形式のファイルパスを構築
- **103-122行目**: 優先順位に従いファイルを読み込み・パース

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

```
tf.saved_model.load(export_dir)
    │
    ├─ loader_impl.parse_saved_model(export_dir)
    │      └─ saved_model_pb2.SavedModel.ParseFromString()
    │
    ├─ Loader(object_graph_proto, saved_model_proto, ...)
    │      │
    │      ├─ function_deserialization.load_function_def_library()
    │      │      └─ _WrapperFunction でラップ
    │      │
    │      ├─ _load_all()
    │      │      ├─ _load_nodes()  [Pythonオブジェクト再構築]
    │      │      ├─ _load_edges()  [親子関係復元]
    │      │      └─ _setup_remaining_functions()
    │      │
    │      └─ _restore_checkpoint()  [変数値復元]
    │
    └─ fingerprinting.read_fingerprint()  [フィンガープリント検証]
```

### データフロー図

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

saved_model.pb ─────────────▶ parse_saved_model ──▶ SavedModel proto
                                │
FunctionDefLibrary ──────────▶ load_function_def_library ──▶ ConcreteFunctions
                                │
SavedObjectGraph ────────────▶ Loader._load_all ──▶ Python Trackable objects
                                │
variables/checkpoint ────────▶ _restore_checkpoint ──▶ 変数値の復元
                                │
assets/ ─────────────────────▶ Asset復元 ──▶ アセットパスの解決

                                最終出力: AutoTrackable (復元されたモデル)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| load.py | `tensorflow/python/saved_model/load.py` | ソース | SavedModel読み込みのメインロジック（TF2 API） |
| loader_impl.py | `tensorflow/python/saved_model/loader_impl.py` | ソース | SavedModelパースとTF1互換ローダー |
| load_options.py | `tensorflow/python/saved_model/load_options.py` | ソース | 読み込みオプションの定義 |
| load_v1_in_v2.py | `tensorflow/python/saved_model/load_v1_in_v2.py` | ソース | TF1形式SavedModelのTF2ロード |
| function_deserialization.py | `tensorflow/python/saved_model/function_deserialization.py` | ソース | FunctionDefLibraryのデシリアライゼーション |
| fingerprinting.py | `tensorflow/python/saved_model/fingerprinting.py` | ソース | フィンガープリント読み込み・検証 |
| revived_types.py | `tensorflow/python/saved_model/revived_types.py` | ソース | 復元されたオブジェクト型の管理 |
| registration.py | `tensorflow/python/saved_model/registration.py` | ソース | カスタムオブジェクトの登録・取得 |
