# 機能設計書 28-Adamオプティマイザ

## 概要

本ドキュメントは、TensorFlow/KerasにおけるAdamオプティマイザの機能設計を記述する。適応的学習率を持つ一次・二次モーメント推定に基づく最適化アルゴリズムを提供する。

### 本機能の処理概要

**業務上の目的・背景**：Adamは適応的学習率を持つ最適化アルゴリズムで、各パラメータの勾配の一次モーメント（平均）と二次モーメント（非中心分散）の移動平均を維持することで、パラメータごとに最適な学習率を自動調整する。メモリ効率が良く、大規模データ・パラメータの問題に適しており、深層学習で最も広く使用されるオプティマイザの一つである。

**機能の利用シーン**：自然言語処理（BERT, GPT等のTransformerモデル）、画像認識、生成モデル（GAN）、強化学習など、ほぼ全ての深層学習タスクで標準的に使用される。特にハイパーパラメータのチューニングに手間をかけたくない場合に好まれる。

**主要な処理内容**：
1. 一次モーメント（m）の更新: 勾配の指数移動平均
2. 二次モーメント（v）の更新: 勾配の二乗の指数移動平均
3. バイアス補正: 初期ステップでのモーメント推定のバイアスを補正
4. パラメータ更新: バイアス補正済みモーメントに基づく更新
5. AMSGrad変種: 二次モーメントの最大値を追跡（オプション）
6. スパース勾配対応

**関連システム・外部連携**：損失関数（No.40）、自動微分（No.37）、学習率スケジューリング（No.35）と連携。

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面機能マッピングに該当なし |

## 機能種別

計算処理（パラメータ最適化）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| learning_rate | float/Schedule/callable | No | 学習率 | デフォルト: 0.001 |
| beta_1 | float | No | 一次モーメントの減衰率 | デフォルト: 0.9 |
| beta_2 | float | No | 二次モーメントの減衰率 | デフォルト: 0.999 |
| epsilon | float | No | 数値安定性のための小定数 | デフォルト: 1e-7 |
| amsgrad | bool | No | AMSGrad変種を使用するか | デフォルト: False |

### 入力データソース

GradientTapeまたはmodel.fit()から計算された勾配テンソル。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| updated_variables | Variable | 更新されたモデルパラメータ |
| iteration | int64 | 更新ステップ数 |

### 出力先

モデルのtrainable_variablesが直接更新される。

## 処理フロー

### 処理シーケンス

```
1. _create_slots(var_list)
   └─ 各変数にm（一次モーメント）、v（二次モーメント）スロット作成
   └─ amsgrad=Trueの場合、vhat（最大v）スロットも作成
2. _prepare_local(var_device, var_dtype, apply_state)
   └─ beta_1^t, beta_2^tのべき乗計算
   └─ バイアス補正済み学習率: lr * sqrt(1-beta_2^t) / (1-beta_1^t)
3. _resource_apply_dense(grad, var)
   └─ amsgrad=False: ResourceApplyAdam
   └─ amsgrad=True: ResourceApplyAdamWithAmsgrad
4. _resource_apply_sparse(grad, var, indices)
   └─ スパース更新: m, vの部分更新 + パラメータ更新
```

### フローチャート

```mermaid
flowchart TD
    A[勾配 g] --> B[m = beta1 * m + (1-beta1) * g]
    B --> C[v = beta2 * v + (1-beta2) * g^2]
    C --> D{amsgrad?}
    D -->|Yes| E[vhat = max(vhat, v)]
    D -->|No| F[v_corrected = v]
    E --> G[w = w - lr_corrected * m / (sqrt(vhat) + eps)]
    F --> H[w = w - lr_corrected * m / (sqrt(v) + eps)]
    G --> I[iteration++]
    H --> I
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-28-01 | バイアス補正 | lr_t = lr * sqrt(1-beta2^t) / (1-beta1^t) | 毎ステップ |
| BR-28-02 | AMSGrad | vhat = max(vhat, v)で二次モーメントの単調増加を保証 | amsgrad=True |
| BR-28-03 | スパース等価性 | スパース実装は密実装と等価な動作 | IndexedSlices入力時 |
| BR-28-04 | V1互換 | V1のvhatsを含む重みをV2でフィルタリング | set_weights時 |

### 計算ロジック

$$lr_t = lr \cdot \frac{\sqrt{1 - \beta_2^t}}{1 - \beta_1^t}$$
$$m_t = \beta_1 \cdot m_{t-1} + (1 - \beta_1) \cdot g$$
$$v_t = \beta_2 \cdot v_{t-1} + (1 - \beta_2) \cdot g^2$$
$$\theta_t = \theta_{t-1} - lr_t \cdot \frac{m_t}{\sqrt{v_t} + \epsilon}$$

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 注意 | epsilon=1e-7がタスクに最適でない可能性 | タスクに応じて1.0や0.1を試す |

### リトライ仕様

該当なし。

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

該当なし。

## パフォーマンス要件

- ResourceApplyAdam / ResourceApplyAdamWithAmsgrad はC++融合カーネルで実装
- NonFusedAdam版も提供（デバッグ・カスタマイズ用）
- _HAS_AGGREGATE_GRAD=Trueで勾配集約を最適化

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

特になし。

## 備考

- 論文: Kingma et al., 2014 (Adam), Reddi et al., 2018 (AMSGrad)
- epsilon hatは論文のSection 2.1直前の数式のもの（Algorithm 1のepsilonとは異なる）
- Inception on ImageNetでは epsilon=1.0 or 0.1 が推奨

---

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

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

### 推奨読解順序

#### Step 1: 初期化とスロット作成

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | adam.py | `tensorflow/python/keras/optimizer_v2/adam.py` | __init__（104-118行目）: ハイパーパラメータ設定 |
| 1-2 | adam.py | `tensorflow/python/keras/optimizer_v2/adam.py` | _create_slots（120-129行目）: m, v, vhatスロット |

**読解のコツ**: `add_slot(var, 'm')`と`add_slot(var, 'v')`でモーメント用の状態変数が作成される。amsgradの場合のみ`add_slot(var, 'vhat')`が追加される。

#### Step 2: バイアス補正済み学習率の準備

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | adam.py | `tensorflow/python/keras/optimizer_v2/adam.py` | _prepare_local（131-154行目）: beta_1^t, beta_2^tの計算とlr補正 |

**主要処理フロー**:
- **134行目**: local_step = iterations + 1
- **135-136行目**: beta_1_t, beta_2_tのテンソル化
- **137-138行目**: beta_1_power, beta_2_powerのべき乗計算
- **139-140行目**: lr = lr_t * sqrt(1-beta_2^t) / (1-beta_1^t)

#### Step 3: 密勾配の適用

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | adam.py | `tensorflow/python/keras/optimizer_v2/adam.py` | _resource_apply_dense（166-201行目） |

**主要処理フロー**:
- **174-186行目**: amsgrad=False → `ResourceApplyAdam`（融合カーネル呼び出し）
- **188-201行目**: amsgrad=True → `ResourceApplyAdamWithAmsgrad`

#### Step 4: スパース勾配の適用

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | adam.py | `tensorflow/python/keras/optimizer_v2/adam.py` | _resource_apply_sparse（203-241行目）: 手動m,v更新とvar更新 |

**主要処理フロー**:
- **208-214行目**: m_t = beta1 * m + (1-beta1) * g（scatter_add使用）
- **216-222行目**: v_t = beta2 * v + (1-beta2) * g^2（scatter_add使用）
- **224-229行目**: amsgrad=False: var -= lr * m_t / (sqrt(v_t) + eps)
- **230-241行目**: amsgrad=True: vhat更新後に同様の計算

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

```
optimizer.apply_gradients(grads_and_vars)
    │
    ├─ _create_slots(var_list)
    │      ├─ add_slot(var, 'm')     # 一次モーメント
    │      ├─ add_slot(var, 'v')     # 二次モーメント
    │      └─ add_slot(var, 'vhat')  # AMSGrad用 [optional]
    │
    ├─ _prepare_local()
    │      └─ バイアス補正済みlr計算
    │
    └─ _resource_apply_dense / _resource_apply_sparse
           ├─ gen_training_ops.ResourceApplyAdam          [amsgrad=False]
           ├─ gen_training_ops.ResourceApplyAdamWithAmsgrad [amsgrad=True]
           └─ 手動scatter更新                              [sparse]
```

### データフロー図

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

勾配 g              ───▶  Adam._resource_apply_dense     ───▶  更新後 w
パラメータ w         ───▶    ├─ m = beta1*m + (1-beta1)*g         更新後 m
m (1st moment)      ───▶    ├─ v = beta2*v + (1-beta2)*g^2       更新後 v
v (2nd moment)      ───▶    ├─ lr_corrected計算                   更新後 vhat (opt)
beta_1, beta_2, lr  ───▶    └─ w -= lr_c * m / (sqrt(v) + eps)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| adam.py | `tensorflow/python/keras/optimizer_v2/adam.py` | ソース | Adam/NonFusedAdamオプティマイザ |
| optimizer_v2.py | `tensorflow/python/keras/optimizer_v2/optimizer_v2.py` | ソース | OptimizerV2基底クラス |
| gen_training_ops.py | (自動生成) | ソース | ResourceApplyAdam等のバインディング |
| training_ops.cc | `tensorflow/core/ops/training_ops.cc` | ソース | 学習用OpのC++定義 |
| backend_config.py | `tensorflow/python/keras/backend_config.py` | ソース | デフォルトepsilon値 |
