# 機能設計書 21-リカレント層（Recurrent Layers）

## 概要

本ドキュメントは、TensorFlow/Kerasにおけるリカレントニューラルネットワーク（RNN）層の機能設計を記述する。LSTM・GRU・SimpleRNNなどの時系列データ処理に特化したレイヤーの構造と処理フローを定義する。

### 本機能の処理概要

**業務上の目的・背景**：時系列データ（自然言語、音声、株価推移など）は、過去の情報が現在の予測に影響を与える。リカレント層は、各タイムステップの入力と前の隠れ状態を組み合わせることで、系列データの時間的依存関係を学習する能力を提供する。これにより、翻訳・音声認識・時系列予測などの業務課題を解決する基盤機能となる。

**機能の利用シーン**：自然言語処理（感情分析、機械翻訳、テキスト生成）、音声認識、時系列予測（株価、気象データ）、動画解析など、時間的な順序を持つデータを扱うすべての場面で使用される。Kerasモデルの構築時に`tf.keras.layers.LSTM`、`tf.keras.layers.GRU`、`tf.keras.layers.SimpleRNN`として利用する。

**主要な処理内容**：
1. RNNセル（LSTMCell, GRUCell, SimpleRNNCell）の初期化とパラメータ設定
2. 入力シーケンスの各タイムステップに対する逐次的なセル呼び出し
3. 隠れ状態の管理（初期化・伝播・リセット）
4. マスキングによる可変長シーケンスへの対応
5. 双方向RNN（Bidirectional）ラッパーによる前方・後方処理
6. StackedRNNCellsによる多層RNNの構築

**関連システム・外部連携**：cuDNN RNN（No.26）と連携してGPU最適化実行が可能。Embedding層（No.20）と組み合わせてテキスト処理パイプラインを構築する。

**権限による制御**：特になし。モデル構築・学習・推論のすべてのフェーズで利用可能。

## 関連画面

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

## 機能種別

計算処理（テンソル演算・時系列処理）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| cell | RNNCell / list[RNNCell] | Yes | RNNセルインスタンスまたはリスト | callメソッドとstate_size属性が必須 |
| return_sequences | bool | No | 全タイムステップの出力を返すか | デフォルト: False |
| return_state | bool | No | 最終状態も返すか | デフォルト: False |
| go_backwards | bool | No | 入力を逆順に処理するか | デフォルト: False |
| stateful | bool | No | バッチ間で状態を保持するか | デフォルト: False |
| unroll | bool | No | ループをアンロールするか | デフォルト: False |
| time_major | bool | No | 入力形式が[time, batch, ...]か | デフォルト: False |
| inputs | Tensor | Yes | 入力テンソル | N-D: [batch, timesteps, ...] |
| mask | Tensor | No | マスクテンソル | [batch, timesteps] |
| initial_state | list[Tensor] | No | 初期状態テンソルリスト | セルのstate_sizeと一致 |

### 入力データソース

Kerasモデルの前段レイヤー出力、またはtf.data Datasetからの入力テンソル。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| output | Tensor | return_sequences=True: [batch, timesteps, output_size], False: [batch, output_size] |
| states | list[Tensor] | return_state=Trueの場合のみ、各状態テンソル [batch, state_size] |

### 出力先

次段のKerasレイヤーまたはモデル出力として利用。

## 処理フロー

### 処理シーケンス

```
1. 初期化（__init__）
   └─ セルの検証（call, state_sizeの存在確認）、リストの場合StackedRNNCellsでラップ
2. ビルド（build）
   └─ 入力形状からinput_spec, state_specを設定、セルのbuild呼び出し
3. 呼び出し（call）
   └─ 3.1 入力の前処理（time_majorの場合の転置）
   └─ 3.2 初期状態の取得（get_initial_state or ゼロ初期化）
   └─ 3.3 タイムステップごとのセル呼び出し（backend.rnn使用）
   └─ 3.4 マスク適用・出力形状の調整
   └─ 3.5 return_sequences/return_stateに応じた出力構成
```

### フローチャート

```mermaid
flowchart TD
    A[入力テンソル受信] --> B{time_major?}
    B -->|Yes| C[そのまま使用]
    B -->|No| D[転置: batch,time -> time,batch]
    C --> E[初期状態の準備]
    D --> E
    E --> F{initial_state指定?}
    F -->|Yes| G[指定された初期状態を使用]
    F -->|No| H[ゼロ初期化 or get_initial_state]
    G --> I[タイムステップループ]
    H --> I
    I --> J[各ステップでcell.call実行]
    J --> K{全ステップ完了?}
    K -->|No| J
    K -->|Yes| L{return_sequences?}
    L -->|Yes| M[全出力を結合]
    L -->|No| N[最終出力のみ]
    M --> O{return_state?}
    N --> O
    O -->|Yes| P[出力 + 最終状態を返す]
    O -->|No| Q[出力のみ返す]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-21-01 | セル検証 | cellにはcallメソッドとstate_size属性が必須 | RNNレイヤー初期化時 |
| BR-21-02 | 状態継続 | stateful=Trueの場合、バッチ間で状態を引き継ぐ | 学習・推論時 |
| BR-21-03 | アンロール制約 | unroll=Trueの場合、タイムステップは固定長のみ | ビルド時 |
| BR-21-04 | 分散非対応 | stateful=Trueはtf.distribute.Strategyと併用不可 | 初期化時 |

### 計算ロジック

- **SimpleRNNCell**: `h_t = activation(W_x * x_t + W_h * h_{t-1} + b)`
- **LSTMCell**: ゲート機構（forget, input, output gate）によるセル状態と隠れ状態の更新
- **GRUCell**: リセットゲートと更新ゲートによる隠れ状態の更新

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

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

該当なし（インメモリテンソル演算のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ValueError | 初期化エラー | cellにcallメソッドがない | RNNCellインターフェースを実装する |
| ValueError | 初期化エラー | cellにstate_sizeがない | state_size属性を定義する |
| ValueError | 実行時エラー | stateful=TrueかつStrategy使用 | stateful=Falseにするか分散なしで実行 |
| ValueError | ビルドエラー | unroll=Trueで可変長入力 | 固定長入力にするかunroll=Falseにする |

### リトライ仕様

該当なし。

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

該当なし（ステートレスなテンソル演算）。stateful=Trueの場合、reset_states()で状態をリセット可能。

## パフォーマンス要件

- cuDNN対応セル（LSTMCell, GRUCell）使用時はGPU上で最適化カーネルが自動選択される
- unroll=TrueはメモリとのトレードオフでCPU/GPU計算を高速化
- recurrent_dropoutを使用する場合、implementation=1が強制される

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

特になし。入力テンソルのバリデーションはフレームワーク側で実施。

## 備考

- recurrent_dropoutはimplementation=2と非互換（自動でimplementation=1にフォールバック）
- KerasのBidirectionalラッパーで双方向RNNを簡易構築可能

---

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

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

### 推奨読解順序

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

RNNセルのインターフェース（state_size, output_size, call）を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | recurrent.py | `tensorflow/python/keras/layers/recurrent.py` | StackedRNNCellsクラス（55-193行目）でセルのスタック構造を理解 |

**読解のコツ**: `state_size`プロパティ（103-105行目）がタプル形式で各セルの状態サイズを返す構造を把握すること。`reverse_state_order`は後方互換のためのフラグ。

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

RNNベースクラスが全てのリカレント層の共通基盤。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | recurrent.py | `tensorflow/python/keras/layers/recurrent.py` | RNNクラス（196-599行目）のinit, build, callメソッド |

**主要処理フロー**:
1. **388-434行目**: `__init__`でセルの検証と属性設定。リストの場合StackedRNNCellsに変換
2. **532-599行目**: `build`で入力仕様・状態仕様の設定、セルのビルド
3. **465-516行目**: `compute_output_shape`で出力形状の算出

#### Step 3: C++カーネルレベルの実装

低レベルのRNNセル演算を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | rnn_ops.cc | `tensorflow/core/ops/rnn_ops.cc` | GRUBlockCell（25-49行目）とLSTMBlockCell（85-100行目）のOp登録 |

**主要処理フロー**:
- **25-49行目**: GRUBlockCellの入出力定義（x, h_prev, w_ru, w_c, b_ru, b_c → r, u, c, h）
- **85-100行目**: LSTMBlockCellの入出力定義（x, cs_prev, h_prev, w, wci, wcf, wco, b → i, cs, f, o, ci, co, h）

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

```
tf.keras.layers.LSTM / GRU / SimpleRNN
    │
    ├─ RNN (base class)
    │      ├─ __init__: セル検証, StackedRNNCells生成
    │      ├─ build: input_spec/state_spec設定, cell.build呼出
    │      └─ call: backend.rnn → タイムステップループ
    │             └─ cell.call(input_t, states_t)
    │                    ├─ LSTMCell._resource_apply
    │                    ├─ GRUCell._resource_apply
    │                    └─ SimpleRNNCell._resource_apply
    │
    └─ StackedRNNCells
           └─ call: 各セルを順次呼び出し
```

### データフロー図

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

入力テンソル          ───▶  RNN.call                    ───▶  出力テンソル
[batch, time, feat]         ├─ 初期状態準備                   [batch, (time,) output_size]
                            ├─ for t in timesteps:
                            │    cell.call(x_t, h_{t-1})
マスクテンソル        ───▶  └─ マスク適用              ───▶  最終状態
[batch, time]                                                 [batch, state_size]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| recurrent.py | `tensorflow/python/keras/layers/recurrent.py` | ソース | RNN/StackedRNNCells/SimpleRNNCell等の定義 |
| rnn_ops.cc | `tensorflow/core/ops/rnn_ops.cc` | ソース | GRUBlockCell/LSTMBlockCellのOp定義 |
| base_layer.py | `tensorflow/python/keras/engine/base_layer.py` | ソース | Layerベースクラス |
| backend.py | `tensorflow/python/keras/backend.py` | ソース | rnn関数（タイムステップループ実装） |
| cudnn_rnn_ops.cc | `tensorflow/core/ops/cudnn_rnn_ops.cc` | ソース | cuDNN最適化RNN Op |
