# 機能設計書 30-RMSPropオプティマイザ

## 概要

本ドキュメントは、TensorFlow/KerasにおけるRMSPropオプティマイザの機能設計を記述する。勾配の二乗の移動平均（割引平均）を使用した適応的学習率オプティマイザを提供する。

### 本機能の処理概要

**業務上の目的・背景**：RMSPropは、Adagradの学習率が単調に減少する問題を解決するために考案されたオプティマイザである。勾配の二乗の移動平均を使用することで、学習率の適応を維持しつつ、長期学習でも学習率が極端に小さくならない。RNNの学習で特に効果的であり、非定常な目的関数に対しても安定した学習が可能。

**機能の利用シーン**：RNNモデルの学習、強化学習（DQN等でよく使用）、非定常な目的関数を持つ問題、Adagradで学習率が過度に低下する場合の代替として使用される。

**主要な処理内容**：
1. 勾配の二乗の移動平均（rms）の更新
2. モーメンタム付き更新（オプション）
3. Centered RMSprop（勾配の移動平均による分散推定、オプション）
4. パラメータ更新
5. スパース勾配対応
6. 密勾配・スパース勾配の両方での最適化カーネル利用

**関連システム・外部連携**：損失関数（No.40）、自動微分（No.37）と連携。

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

## 関連画面

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

## 機能種別

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

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| learning_rate | float/Schedule/callable | No | 学習率 | デフォルト: 0.001 |
| rho | float | No | 移動平均の減衰率 | デフォルト: 0.9 |
| momentum | float | No | モーメンタム係数 | 0.0-1.0、デフォルト: 0.0 |
| epsilon | float | No | 数値安定性のための小定数 | デフォルト: 1e-7 |
| centered | bool | No | 中心化RMSPropを使用するか | デフォルト: False |

### 入力データソース

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

## 出力仕様

### 出力データ

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

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. _create_slots(var_list)
   └─ 各変数にrmsスロット作成
   └─ momentum > 0: momentumスロット追加
   └─ centered=True: mg（勾配移動平均）スロット追加
2. _prepare_local(var_device, var_dtype, apply_state)
   └─ rho, momentum, epsilon, neg_lr_t, one_minus_rhoのテンソル変換
3. _resource_apply_dense(grad, var)
   └─ momentum有り + centered: ResourceApplyCenteredRMSProp
   └─ momentum有り: ResourceApplyRMSProp
   └─ momentum無し: 手動計算（rms更新 → var更新）
4. _resource_apply_sparse(grad, var, indices)
   └─ 同様の分岐でスパース対応
```

### フローチャート

```mermaid
flowchart TD
    A[勾配 g] --> B[rms = rho * rms + (1-rho) * g^2]
    B --> C{centered?}
    C -->|Yes| D[mg = rho * mg + (1-rho) * g]
    C -->|No| E[denom = rms]
    D --> F[denom = rms - mg^2]
    E --> G{momentum > 0?}
    F --> G
    G -->|Yes| H[mom = momentum * mom + lr * g / (sqrt(denom) + eps)]
    G -->|No| I[w = w - lr * g / (sqrt(denom) + eps)]
    H --> J[w = w - mom]
    I --> K[iteration++]
    J --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-30-01 | モーメンタム範囲 | momentumは0-1の範囲内 | __init__時 |
| BR-30-02 | スパース動作差異 | スパース実装は密実装と動作が異なる（未使用スライスは更新されない） | IndexedSlices入力時 |
| BR-30-03 | Centered分散推定 | centered=Trueで勾配の分散で正規化（計算・メモリコスト増） | centered=True |
| BR-30-04 | プレーンモーメンタム | Nesterovではなくプレーンモーメンタムを使用 | momentum > 0 |

### 計算ロジック

**基本RMSProp**:
$$rms_t = \rho \cdot rms_{t-1} + (1-\rho) \cdot g_t^2$$
$$\theta_t = \theta_{t-1} - \frac{lr}{\sqrt{rms_t} + \epsilon} \cdot g_t$$

**Centered RMSProp**:
$$mg_t = \rho \cdot mg_{t-1} + (1-\rho) \cdot g_t$$
$$rms_t = \rho \cdot rms_{t-1} + (1-\rho) \cdot g_t^2$$
$$\theta_t = \theta_{t-1} - \frac{lr}{\sqrt{rms_t - mg_t^2} + \epsilon} \cdot g_t$$

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ValueError | 初期化エラー | momentumが0-1の範囲外 | 有効な範囲の値を指定 |

### リトライ仕様

該当なし。

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

該当なし。

## パフォーマンス要件

- momentum有り時はResourceApplyRMSProp/ResourceApplyCenteredRMSPropの融合カーネルを使用
- momentum無し時はPython/TFレベルで手動計算（若干のオーバーヘッド）
- _HAS_AGGREGATE_GRAD=Trueで勾配集約を最適化
- centered=Trueは追加の状態変数（mg）によりメモリ使用量が増加

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

特になし。

## 備考

- 参照: Hinton, 2012（Coursera講義スライド）
- スパース実装は密実装と異なり、未使用スライスのアキュムレータは更新されない
- set_weightsのV1後方互換: iterationを含まない重みリストに対応

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | rmsprop.py | `tensorflow/python/keras/optimizer_v2/rmsprop.py` | __init__（95-149行目）: rho, momentum, centered設定 |
| 1-2 | rmsprop.py | `tensorflow/python/keras/optimizer_v2/rmsprop.py` | _create_slots（151-159行目）: rms, momentum, mgスロットの条件付き作成 |

**読解のコツ**: スロット作成はmomentumとcenteredの組み合わせで最大3種類（rms, momentum, mg）。`self._momentum`フラグ（140-143行目）でmomentum > 0を判定。

#### Step 2: 係数の準備

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | rmsprop.py | `tensorflow/python/keras/optimizer_v2/rmsprop.py` | _prepare_local（161-175行目）: rho, one_minus_rho, epsilon等の準備 |

**主要処理フロー**:
- **164行目**: rho = self._get_hyper("rho", var_dtype)
- **167行目**: neg_lr_t = -lr_t（学習率の符号反転）
- **173行目**: one_minus_rho = 1.0 - rho

#### Step 3: 密勾配の適用（4パターン）

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | rmsprop.py | `tensorflow/python/keras/optimizer_v2/rmsprop.py` | _resource_apply_dense（177-221行目）: 4パターンの分岐 |

**主要処理フロー**:
- **183-197行目**: momentum有り + centered → `ResourceApplyCenteredRMSProp`
- **198-208行目**: momentum有り + 非centered → `ResourceApplyRMSProp`
- **209-221行目**: momentum無し → 手動計算（rms_t, mg_t, var_t）
  - **210-212行目**: rms更新: rho * rms + one_minus_rho * g^2
  - **214-218行目**: centered時のmg更新とdenom計算
  - **219-221行目**: var更新: var - lr * g / (sqrt(denom) + eps)

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | rmsprop.py | `tensorflow/python/keras/optimizer_v2/rmsprop.py` | _resource_apply_sparse（223-279行目）: scatter操作を使った部分更新 |

**主要処理フロー**:
- **229-256行目**: momentum有り時は融合カーネル（ResourceSparseApplyRMSProp等）使用
- **257-279行目**: momentum無し時は手動scatter更新

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

```
optimizer.apply_gradients(grads_and_vars)
    │
    ├─ _create_slots(var_list)
    │      ├─ add_slot(var, "rms")       # 常に作成
    │      ├─ add_slot(var, "momentum")  # momentum > 0時のみ
    │      └─ add_slot(var, "mg")        # centered=True時のみ
    │
    ├─ _prepare_local()
    │      └─ rho, one_minus_rho, epsilon, neg_lr_t, momentum
    │
    └─ _resource_apply_dense / _resource_apply_sparse
           ├─ ResourceApplyCenteredRMSProp     [momentum + centered]
           ├─ ResourceApplyRMSProp             [momentum + !centered]
           ├─ ResourceSparseApplyCenteredRMSProp [sparse + momentum + centered]
           ├─ ResourceSparseApplyRMSProp       [sparse + momentum + !centered]
           └─ 手動計算                          [!momentum]
```

### データフロー図

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

勾配 g              ───▶  RMSProp._resource_apply       ───▶  更新後 w
パラメータ w         ───▶    ├─ rms = rho*rms + (1-rho)*g^2     更新後 rms
rms (移動平均)       ───▶    ├─ mg = rho*mg + (1-rho)*g [opt]   更新後 mg [opt]
mg (勾配平均)[opt]   ───▶    ├─ mom更新 [opt]                    更新後 mom [opt]
momentum [opt]       ───▶    └─ w -= lr*g/(sqrt(denom)+eps)
rho, lr, epsilon     ───▶
```

### 関連ファイル一覧

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