# 帳票設計書 13-混同行列（Confusion Matrix）

## 概要

本ドキュメントは、TensorFlowの`tf.math.confusion_matrix()`関数を用いた混同行列（Confusion Matrix）の生成に関する設計を記述する。分類タスクの予測結果と正解ラベルから混同行列を計算し、モデルの分類精度を評価するための帳票仕様を定義する。

### 本帳票の処理概要

本帳票は、分類タスクにおける予測ラベルと正解ラベルから混同行列（Confusion Matrix）をTensor形式で生成する。音声コマンド認識タスク（speech_commands）では、学習中のバリデーション・テスト評価時にバッチ単位で混同行列を生成・累積し、モデルの分類性能を評価する。

**業務上の目的・背景**：分類モデルの性能を正確に評価するためには、単純な精度（accuracy）だけでなく、クラスごとの誤分類パターンを把握する必要がある。混同行列は各クラスの真陽性・偽陽性・偽陰性を一目で把握できる形式であり、モデルの弱点分析やクラス不均衡の影響評価に不可欠である。

**帳票の利用シーン**：モデルの学習中のバリデーション評価（eval_step_intervalごと）、学習完了後の最終テスト評価、特定クラスの誤分類パターン分析、モデルの改善効果の比較評価などで利用される。

**主要な出力内容**：
1. n x n の混同行列（nはクラス数）：行が正解ラベル、列が予測ラベルに対応
2. バッチ単位の混同行列の累積結果
3. ログ出力による混同行列のテキスト表現

**帳票の出力タイミング**：speech_commandsの例では、eval_step_interval（デフォルト400ステップ）ごとのバリデーション評価時、および学習完了後の最終テスト評価時に出力される。`tf.math.confusion_matrix()`はTensorFlow演算として即時評価可能。

**帳票の利用者**：機械学習エンジニア、データサイエンティスト、モデル評価担当者

## 帳票種別

集計表 / 評価行列

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | CLIログ出力 | - | tf.compat.v1.logging.info/warnで標準ログに出力 |
| - | TensorBoard | localhost:6006 | summary.scalar経由でaccuracyと併せて記録 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | TensorFlow Tensor（numpy ndarray）/ ログ出力（テキスト） |
| 用紙サイズ | N/A（電子データ） |
| 向き | N/A |
| ファイル名 | N/A（ログ出力またはTensor内データ） |
| 出力方法 | ログ出力（tf.compat.v1.logging）/ sess.run評価結果 |
| 文字コード | UTF-8（ログ出力時） |

### PDF固有設定

該当なし

### Excel固有設定

該当なし

## 帳票レイアウト

### レイアウト概要

混同行列は正方行列として出力される。行が正解ラベル（labels）、列が予測ラベル（predictions）に対応し、各セルは対応する（正解, 予測）ペアの出現回数を表す。

```
┌─────────────────────────────────────┐
│           予測ラベル                  │
│     cls_0  cls_1  cls_2 ... cls_n   │
├─────────────────────────────────────┤
│ 正  cls_0 [ 45     2     1  ...  0] │
│ 解  cls_1 [  3    40     0  ...  1] │
│ ラ  cls_2 [  0     1    43  ...  0] │
│ ベ  ...   [ ...   ...   ... ...  .] │
│ ル  cls_n [  1     0     2  ... 42] │
└─────────────────────────────────────┘
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | クラスラベル列ヘッダー | 予測ラベルの各クラス名 | num_classes（0〜n-1） | 整数インデックス |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | matrix[i][j] | 正解がクラスi、予測がクラスjのサンプル数 | scatter_nd(indices, updates, shape) | 整数 | 可変 |

### フッター部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | 精度（accuracy） | 全体の分類精度（正解数/全体数） | evaluation_step（tf.reduce_mean） | 浮動小数点（%.1f%%） |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| labels | 正解ラベルの1次元Tensor（int64） | Yes |
| predictions | 予測ラベルの1次元Tensor（int64） | Yes |
| num_classes | クラス数（Noneの場合はlabelsとpredictionsの最大値+1） | No |
| weights | 重み付きTensor（Noneの場合は等重み） | No |
| dtype | 出力データ型（デフォルト: int32） | No |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | クラスインデックス（行・列とも） | 昇順（0〜n-1） |

### 改ページ条件

該当なし

## データベース参照仕様

### 参照テーブル一覧

本帳票はデータベースを参照しない。TensorFlowの計算グラフ内で演算として実行される。

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| N/A | N/A | N/A |

### テーブル別参照項目詳細

該当なし

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| num_classes（自動計算時） | max(max(predictions), max(labels)) + 1 | なし | num_classesがNoneの場合に適用（confusion_matrix.py行170-171） |
| indices | stack([labels, predictions], axis=1) | なし | scatter_ndの入力インデックス（行190） |
| values | ones_like(predictions, dtype)（weightsがNoneの場合） | なし | 各サンプルの寄与値（行191-192） |
| matrix | scatter_nd(indices, values, [num_classes, num_classes]) | なし | 最終的な混同行列（行193-196） |
| total_conf_matrix | バッチ間の混同行列の要素和 | なし | train.pyで累積（行278-280） |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[labels, predictionsの取得] --> B[入力検証]
    B --> C{num_classesが指定?}
    C -->|No| D[max labels,predictions + 1 で自動計算]
    C -->|Yes| E[指定値を使用・範囲検証]
    D --> F[labelsとpredictionsをint64にキャスト]
    E --> F
    F --> G[非負チェック assert_non_negative]
    G --> H[indices = stack labels, predictions axis=1]
    H --> I[values = ones_like or weights]
    I --> J[scatter_nd indices, values, shape]
    J --> K[n x n 混同行列テンソルを返却]
    K --> L[バッチ間で累積加算 train.py]
    L --> M[ログ出力 tf.logging.info/warn]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| ValueError | labelsとpredictionsの形状不一致 | 形状不一致エラー | 同一形状の1次元Tensorを入力する |
| InvalidArgumentError | labelsに負の値が含まれる | "`labels` contains negative values" | ラベルは0以上の整数を使用する |
| InvalidArgumentError | predictionsに負の値が含まれる | "`predictions` contains negative values" | 予測値は0以上の整数を使用する |
| InvalidArgumentError | labelsがnum_classes以上 | "`labels` out of bound" | num_classesを正しく設定する |
| InvalidArgumentError | predictionsがnum_classes以上 | "`predictions` out of bound" | num_classesを正しく設定する |
| ValueError | weightsの形状がpredictionsと不一致 | 形状不一致エラー | weightsをpredictionsと同一形状にする |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | バッチサイズ分のサンプル数（デフォルト100）x クラス数（デフォルト12） |
| 目標出力時間 | ミリ秒単位（scatter_ndによる高速演算） |
| 同時出力数上限 | 制限なし（TensorFlowの演算として並列実行可能） |

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

- 混同行列自体にはモデルのアーキテクチャ情報は含まれないが、クラス分布やモデルの弱点が露呈するため、評価結果の外部公開には注意が必要
- speech_commandsの例ではログ出力されるため、ログファイルのアクセス権限を適切に設定する

## 備考

- speech_commandsの例では、wanted_words（デフォルト: yes, no, up, down, left, right, on, off, stop, go）に silence, unknown を加えた12クラスの分類タスク
- バリデーション評価時（eval_step_interval=400ごと）にtotal_conf_matrixとして累積出力される（train.py行260-281）
- テスト評価時にも同様に累積し、最終結果をwarnレベルでログ出力（train.py行294-316）
- tf.math.confusion_matrixはTensorFlow 2.xのAPIとして公開（@tf_export('math.confusion_matrix')）
- v1互換APIはtf.math.confusion_matrixおよびtf.confusion_matrixとして公開

---

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

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

### 推奨読解順序

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

混同行列の入出力データの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | confusion_matrix.py | `tensorflow/python/ops/confusion_matrix.py` | confusion_matrix()関数（行92-196）の引数定義。labels（1-D Tensor）、predictions（1-D Tensor）、num_classes（int or None）、weights（optional Tensor）、dtype（デフォルトint32）を受け取り、[n, n]のTensorを返す |

**読解のコツ**: `@tf_export('math.confusion_matrix', v1=[])` デコレータにより`tf.math.confusion_matrix`として公開される。v1互換版のconfusion_matrix_v1（行199-259）は引数順序が異なるだけで内部はconfusion_matrixを呼び出す。

#### Step 2: エントリーポイントを理解する（利用側）

speech_commandsの学習スクリプトにおける混同行列の利用箇所を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | train.py | `tensorflow/examples/speech_commands/train.py` | 混同行列の定義（行177-179）：tf.math.confusion_matrixをground_truth_inputとpredicted_indicesから生成 |
| 2-2 | train.py | `tensorflow/examples/speech_commands/train.py` | バリデーション評価ループ（行261-281）：バッチ単位でsess.runし、total_conf_matrixに累積加算 |
| 2-3 | train.py | `tensorflow/examples/speech_commands/train.py` | テスト評価ループ（行294-316）：同様に累積し、最終結果をログ出力 |

**主要処理フロー**:
1. **行129**: logits, dropout_rateをmodels.create_modelで生成
2. **行175**: predicted_indices = tf.argmax(logits, axis=1)
3. **行176**: correct_prediction = tf.equal(predicted_indices, ground_truth_input)
4. **行177-179**: confusion_matrix = tf.math.confusion_matrix(labels=ground_truth_input, predictions=predicted_indices, num_classes=label_count)
5. **行267-268**: sess.run([..., confusion_matrix], feed_dict=...)でバッチ単位の混同行列取得
6. **行277-280**: total_conf_matrix += conf_matrix で累積
7. **行281**: tf.compat.v1.logging.info('Confusion Matrix:\n %s' % (total_conf_matrix))

#### Step 3: 混同行列の計算実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | confusion_matrix.py | `tensorflow/python/ops/confusion_matrix.py` | remove_squeezable_dimensions()（行30-89）：labelsとpredictionsのランク差が1の場合に最終次元をsqueezeして形状を揃える |
| 3-2 | confusion_matrix.py | `tensorflow/python/ops/confusion_matrix.py` | confusion_matrix()本体（行150-196）：labels/predictionsをint64にキャスト、非負チェック、num_classes自動計算、scatter_ndで行列構築 |

**主要処理フロー**:
- **行152-155**: remove_squeezable_dimensionsで入力形状を正規化
- **行156-157**: int64へのキャスト
- **行160-167**: 非負アサーション（assert_non_negative）
- **行169-182**: num_classes計算（Noneの場合はmax+1、指定時は範囲チェック）
- **行189**: shape = stack([num_classes, num_classes])
- **行190**: indices = stack([labels, predictions], axis=1)
- **行191-192**: values = ones_like(predictions) or weights
- **行193-196**: scatter_nd(indices, values, shape)で混同行列を構築

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

```
train.py main()  [行82]
    |
    +-- tf.math.confusion_matrix(labels, predictions, num_classes)  [行177]
    |       |
    |       +-- confusion_matrix.confusion_matrix()  [行94]
    |               +-- remove_squeezable_dimensions()  [行30]
    |               +-- math_ops.cast(predictions, int64)
    |               +-- math_ops.cast(labels, int64)
    |               +-- check_ops.assert_non_negative(labels)
    |               +-- check_ops.assert_non_negative(predictions)
    |               +-- array_ops_stack.stack([labels, predictions], axis=1)
    |               +-- array_ops.scatter_nd(indices, values, shape)
    |
    +-- sess.run([..., confusion_matrix], feed_dict=...)  [行267]
    |
    +-- total_conf_matrix += conf_matrix  [行280]
    |
    +-- tf.compat.v1.logging.info('Confusion Matrix:\n %s')  [行281]
```

### データフロー図

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

ground_truth_input     ------>  confusion_matrix()           ---->
(int64, 1-D Tensor)             labels/predictions正規化
                                int64キャスト
predicted_indices      ------>  非負チェック                  ---->
(int64, 1-D Tensor)             indices構築
                                scatter_nd                   ---->  conf_matrix
                                                                    (int32, [n,n] Tensor)
label_count            ------>  num_classes設定

                                バッチループ内:
conf_matrix (batch)    ------>  total_conf_matrix += batch   ---->  total_conf_matrix
                                                                    (累積numpy ndarray)

total_conf_matrix      ------>  tf.logging.info/warn         ---->  ログ出力
                                                                    (テキスト表現)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| confusion_matrix.py | `tensorflow/python/ops/confusion_matrix.py` | ソース | tf.math.confusion_matrixの実装。remove_squeezable_dimensions, confusion_matrix, confusion_matrix_v1を定義 |
| train.py | `tensorflow/examples/speech_commands/train.py` | ソース | 音声コマンド認識の学習スクリプト。混同行列の利用例として、バリデーション・テスト評価時に生成・累積・ログ出力 |
| models.py | `tensorflow/examples/speech_commands/models.py` | ソース | モデルアーキテクチャの定義。create_modelとprepare_model_settingsを提供 |
| input_data.py | `tensorflow/examples/speech_commands/input_data.py` | ソース | AudioProcessorクラスによる音声データの読み込み・前処理 |
