# 機能設計書 25-CTC損失（CTC Operations）

## 概要

本ドキュメントは、TensorFlowにおけるConnectionist Temporal Classification（CTC）損失計算およびデコード機能の設計を記述する。入力シーケンスと出力ラベルのアライメントが不明な場合の学習・推論を可能にする。

### 本機能の処理概要

**業務上の目的・背景**：音声認識や手書き文字認識では、入力フレーム列と出力文字列の正確な対応関係（アライメント）が事前に分かっていないことが多い。CTC損失は、可能な全てのアライメントの確率を周辺化することで、アライメント不要の学習を実現する。これにより、フレーム単位のラベリングなしに端対端のシーケンス認識モデルを学習できる。

**機能の利用シーン**：音声認識（ASR）、光学文字認識（OCR）、手書き認識、リップリーディングなど、入力シーケンスと出力シーケンスの長さが異なり、アライメントが不明な全てのシーケンス認識タスクで使用される。

**主要な処理内容**：
1. CTC損失計算（ctc_loss / ctc_loss_v2）: 前向き・後向きアルゴリズムによる対数確率計算
2. CTC貪欲デコード（ctc_greedy_decoder）: 最尤パスの復号
3. CTCビームサーチデコード（ctc_beam_search_decoder）: ビームサーチによる複数候補復号
4. GPU/CPU自動切替: デバイスに応じた最適な実装の選択

**関連システム・外部連携**：リカレント層（No.21）のLSTM/GRU出力をCTC損失の入力とする。cuDNN RNN（No.26）と連携してGPU上の高速学習が可能。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 4 | 音声認識画面 | 関連機能 | conv_actions_frozen.pbモデルで音声コマンド認識（CTC的なシーケンス処理） |

## 機能種別

計算処理（損失関数計算・デコード処理）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| labels | SparseTensor(int32) | Yes | 正解ラベル（スパース形式） | SparseTensorであること |
| logits / inputs | Tensor(float) | Yes | ロジット[max_time, batch, num_classes] | 3次元テンソル |
| sequence_length | Tensor(int32) | Yes | 各バッチのシーケンス長 | [batch_size] |
| preprocess_collapse_repeated | bool | No | 事前に繰り返しラベルを統合するか | デフォルト: False |
| ctc_merge_repeated | bool | No | CTC計算内で繰り返し統合するか | デフォルト: True |
| ignore_longer_outputs_than_inputs | bool | No | 出力が入力より長い場合無視するか | デフォルト: False |
| time_major | bool | No | 入力形式が[time, batch, ...]か | デフォルト: True |
| beam_width | int | No(beam) | ビームサーチの幅 | デフォルト: 100 |
| top_paths | int | No(beam) | 返す上位パス数 | デフォルト: 1 |
| blank_index | int | No(greedy) | ブランクラベルのインデックス | デフォルト: num_classes-1 |

### 入力データソース

RNNまたはCNN出力のロジットテンソル、および正解ラベルのSparseTensor。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| loss | Tensor(float) | CTC損失値 [batch_size] |
| decoded | list[SparseTensor] | デコード結果（greedy/beam） |
| log_probabilities | Tensor(float) | 対数確率 [batch_size, top_paths] |

### 出力先

損失値は最適化関数（SGD, Adam等）への入力。デコード結果は推論結果として利用。

## 処理フロー

### 処理シーケンス

```
CTC損失計算:
1. 入力検証（labelsがSparseTensorか確認）
   └─ TypeErrorをスロー
2. time_major変換
   └─ batch_majorの場合は転置 [B,T,N] → [T,B,N]
3. 型変換
   └─ float16/bfloat16の場合はfloat32にキャスト
4. CTC損失関数の選択
   └─ use_cudnn=True: gen_ctc_ops.ctc_loss_v2（blank=0）
   └─ use_cudnn=False: gen_ctc_ops.ctc_loss（blank=last）
5. 損失計算実行
   └─ 前向き・後向きアルゴリズムによる対数確率計算
6. 型の復元
   └─ 元がfloat16/bfloat16の場合にキャストバック
```

### フローチャート

```mermaid
flowchart TD
    A[入力: logits, labels, seq_len] --> B{labels is SparseTensor?}
    B -->|No| ERR[TypeError]
    B -->|Yes| C{time_major?}
    C -->|No| D[転置: B,T,N → T,B,N]
    C -->|Yes| E[そのまま]
    D --> F{dtype float16/bf16?}
    E --> F
    F -->|Yes| G[float32にキャスト]
    F -->|No| H[そのまま]
    G --> I{use_cudnn?}
    H --> I
    I -->|Yes| J[ctc_loss_v2: blank=0]
    I -->|No| K[ctc_loss: blank=last]
    J --> L[loss, gradient]
    K --> L
    L --> M{元dtype復元?}
    M -->|Yes| N[キャストバック]
    M -->|No| O[loss返却]
    N --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-25-01 | ラベルインデックス | V1: blank=num_classes-1、V2(cuDNN): blank=0 | CTC損失関数選択時 |
| BR-25-02 | シーケンス長制約 | sequence_length(b) <= max_time for all b | 損失計算時 |
| BR-25-03 | ラベル長制約 | ラベル長 <= sequence_length(b) for all b | 損失計算時 |
| BR-25-04 | 二次微分非対応 | CTC損失の二次微分は不可（prevent_gradient） | 勾配計算時 |

### 計算ロジック

- **CTC損失**: 全ての有効なアライメントパスの対数確率の負の対数尤度を計算
- **貪欲デコード**: 各タイムステップの最尤クラスを選択し、繰り返し・ブランクを除去
- **ビームサーチデコード**: ビーム幅内で確率の高いパスを探索、ブランク処理付き

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| TypeError | 入力型エラー | labelsがSparseTensorでない | SparseTensorを渡す |
| InvalidArgument | 実行時エラー | 出力がセンテンス長より長い | ignore_longer_outputs_than_inputs=Trueにする |

### リトライ仕様

該当なし。

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

該当なし。

## パフォーマンス要件

- GPU上ではcuDNN CTC損失（V2）による高速計算が可能
- float16/bfloat16入力は内部でfloat32に変換して精度を確保
- time_major=Trueが計算効率上は推奨

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

特になし。

## 備考

- CTCは Graves et al., 2006 の論文に基づく実装
- preprocess_collapse_repeated=True, ctc_merge_repeated=Trueの組合せはテスト不十分
- v2 APIではctc_loss_v2関数が推奨

---

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

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

### 推奨読解順序

#### Step 1: Op定義（C++レベル）

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ctc_ops.cc | `tensorflow/core/ops/ctc_ops.cc` | CTCLoss Op（27-63行目）の入出力定義と形状推論 |
| 1-2 | ctc_ops.cc | `tensorflow/core/ops/ctc_ops.cc` | CTCLossV2 Op（65-100行目）の差異（blank index=0） |

**読解のコツ**: V1とV2の主な違いはblankインデックスの位置。V1はlast（num_classes-1）、V2は0。

#### Step 2: Python API（損失計算）

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ctc_ops.py | `tensorflow/python/ops/ctc_ops.py` | ctc_loss関数（71-193行目）のV1 API |
| 2-2 | ctc_ops.py | `tensorflow/python/ops/ctc_ops.py` | _ctc_loss_impl（196-247行目）の内部実装 |

**主要処理フロー**:
1. **211-214行目**: SparseTensor型チェック
2. **221-222行目**: time_major=Falseの場合の転置
3. **224-226行目**: float16/bfloat16のfloat32変換
4. **230-233行目**: use_cudnnフラグによるV1/V2関数選択
5. **235-242行目**: 損失計算と勾配取得
6. **244-246行目**: 元の型への復元

#### Step 3: 勾配計算

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ctc_ops.py | `tensorflow/python/ops/ctc_ops.py` | _CTCLossGradImpl（250-264行目）のprevent_gradient使用 |
| 3-2 | ctc_ops.py | `tensorflow/python/ops/ctc_ops.py` | CTCLossGrad/CTCLossV2Grad（268-294行目） |

#### Step 4: デコード

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ctc_ops.py | `tensorflow/python/ops/ctc_ops.py` | ctc_greedy_decoder（297-377行目） |
| 4-2 | ctc_ops.py | `tensorflow/python/ops/ctc_ops.py` | ctc_beam_search_decoder（380行目以降） |

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

```
tf.nn.ctc_loss (Python API)
    │
    ├─ _ctc_loss_impl
    │      ├─ array_ops.transpose (time_major変換)
    │      ├─ math_ops.cast (dtype変換)
    │      └─ gen_ctc_ops.ctc_loss / ctc_loss_v2 (C++ Op呼出)
    │
    ├─ _CTCLossGrad / _CTCLossV2Grad
    │      └─ _CTCLossGradImpl
    │             └─ array_ops.prevent_gradient (二次微分防止)
    │
tf.nn.ctc_greedy_decoder
    └─ gen_ctc_ops.ctc_greedy_decoder (C++ Op呼出)

tf.nn.ctc_beam_search_decoder
    └─ gen_ctc_ops.ctc_beam_search_decoder (C++ Op呼出)
```

### データフロー図

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

logits [T,B,N]        ───▶  _ctc_loss_impl              ───▶  loss [B]
labels (SparseTensor) ───▶    ├─ transpose (if needed)
sequence_length [B]   ───▶    ├─ cast (if float16)
                              └─ gen_ctc_ops.ctc_loss

logits [T,B,N]        ───▶  ctc_greedy_decoder          ───▶  decoded (SparseTensor)
sequence_length [B]   ───▶    └─ gen_ctc_ops              ───▶  log_probs [B,1]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ctc_ops.py | `tensorflow/python/ops/ctc_ops.py` | ソース | CTC損失・デコードのPython API |
| ctc_ops.cc | `tensorflow/core/ops/ctc_ops.cc` | ソース | CTCLoss/CTCGreedyDecoder等のOp定義 |
| gen_ctc_ops.py | (自動生成) | ソース | C++ Opのpythonバインディング |
| nn_grad.py | `tensorflow/python/ops/nn_grad.py` | ソース | _BroadcastMul（勾配計算ユーティリティ） |
