# 学習・評価仕様 (Training & Evaluation)

## 前処理 (Preprocessing)

| 項目 | 方針 |
| --- | --- |
| リサイズ | アスペクト比を保って 224×224 に収め，余白は黒で埋める（元画像は幅 449〜900・高さ 279〜1025 でばらつく） |
| 正規化 | ImageNet の mean / std（事前学習の統計に合わせる） |
| マスク外領域 | **黒 (0, 0, 0)**（実データで確認済み．[TEST_01](../06_TEST/TEST_01_データセット構成調査.md)）．リサイズ時のパディングも黒で統一する |

## データ拡張 (Augmentation)

**色を変える拡張は既定で無効にする．** 舌の色そのものが正解ラベルであり，color jitter・彩度変更・ホワイトバランス変更はラベルを壊す．

| 使う | 使わない（既定） |
| --- | --- |
| 左右反転・微小回転・微小スケール・ランダムクロップ | 色相・彩度・明度ジッタ・グレースケール化・強い正規化 |

※ 撮影条件差の吸収のために色系の拡張を試す場合は，**独立した実験**として効果を測る．

## モデル (Model)

| 項目 | 初期設定 |
| --- | --- |
| アーキテクチャ | ConvNeXt-Tiny（timm・ImageNet 事前学習） |
| 出力 | 5 クラス |
| 学習方式 | 全層ファインチューニング（データが少ないと判断した場合は段階的凍結を試す） |
| 最適化 | AdamW ＋ cosine annealing（warmup 付き） |
| 早期終了 | 検証セットの macro F1 を基準にする |

まず 1 本を通すことを優先し，比較は timm での差し替えで後から行う．

## データ分割 (Data Split)

**すべての分割は患者単位で行う．** 同一患者の画像が複数の分割に跨ってはならない．

現在のデータセットは **1 患者 1 枚**であることを確認済みのため（2026-09-27．[TEST_01](../06_TEST/TEST_01_データセット構成調査.md)），画像単位の分割が患者単位の分割と一致する．ただし実装は常に `patient_id` 単位で分割し，将来同一患者の複数枚が追加されても正しく動くようにする．

| 局面 | 方式 |
| --- | --- |
| 日常の試行 | 患者単位の単一分割（train / val / test）．クラス分布を層化する |
| 結論を出すとき | 患者単位の 5-fold 交差検証 |

- 分割は `patient_id` と seed から決定的に生成し，`config.yaml` に記録する
- **test セットはモデル選択に使わない**（val で選び，test は最後に一度だけ見る）
- **層化は「クラス × 程度」（`<label>_<severity>` の 9 グループ）で行う**．「ややあり除外」の条件で mild を抜いた後も，各分割のクラス比が保たれるようにするため（下記「程度（ややあり）の扱い」）．最小のグループは 51 枚で，比率 0.15 なら各分割に 8 枚程度入る
  - 患者の層化グループは，その患者の `label` と `severity` で決める．同じ患者に複数の `severity` がある場合（将来の複数枚）は，最も強いもの（`strong` > `mild` > `normal`）を使う
- 分割後にグループごとの件数を記録し，偏りを確認する
- **実装方式**: 1 患者は 1 つの label しか持たない（manifest の検証で保証）ため，患者の一覧を層化グループで分ければ「患者単位」と「層化」が同時に成り立つ
  - 単一分割: 層化グループごとに患者を seed で並べ替え，「患者数 × 比率」の四捨五入で test・val の人数を取り，残りを train とする．train に患者が残らないグループがあれば停止する
  - K-fold: 患者の一覧に scikit-learn の `StratifiedKFold`（shuffle あり・seed 指定．層化ラベルは層化グループ）を使う．評価側を `held_out` と呼ぶ（fold 内でさらに val を取るかは Step 4・5 で決める）．患者数が fold 数に満たないグループがあれば停止する
  - どちらも最初に患者 ID を並べ替えるため，manifest の行順に依存しない
- 分割結果（各分割の患者 ID）は**個票に当たるため手元へ回収しない**（サーバ上の `runs/` にのみ保存する．[SPEC_01](SPEC_01_アーキテクチャ設計.md)「回収ホワイトリスト」）

## 程度（ややあり）の扱い (Severity Handling)

**「ややあり」（`mild`）は，臨床上は淡紅（正常）と判断されることが多い境界例である**（2026-09-27 ユーザー確認）．学習に入れるか否かで結果が変わりうるため，**入れる場合と入れない場合の両方で実験する**．

### 実験条件 (Conditions)

設定 `data.severities`（[SPEC_01](SPEC_01_アーキテクチャ設計.md)「設定ファイル」）で使う程度を選ぶ．

| 条件 | `data.severities` | 使う画像 | 枚数 |
| --- | --- | --- | --- |
| ややあり込み | `[strong, mild, normal]`（既定） | すべて | 1085 |
| ややあり除外 | `[strong, normal]` | 「あり」と淡紅（正常） | 754 |

- どちらの条件でも `label` は元のまま（5 クラス）．「ややあり」を淡紅に付け替える扱いは行わない
- 「ややあり除外」でも 5 クラスすべてが残る（淡紅は `normal` のみ，他の 4 クラスは `strong` が残るため）

### 分割との関係 (Split)

- **分割は `data.severities` に関わらず，manifest 全体（1085 枚）で 1 回だけ行う**．条件ごとの除外は，分割の**後**に各分割（train / val / test）から該当する画像を取り除いて適用する
- これにより，「ややあり除外」の各分割は「ややあり込み」の各分割の部分集合になり，**2 つの条件のモデルを同じ患者の test で比較できる**（条件ごとに分割し直すと test の患者が入れ替わり，差が条件によるものか分割によるものか切り分けられない）
- 同じ seed なら，どちらの条件でも同じ分割結果になる

### 評価 (Evaluation)

| 評価 | 対象 | 目的 |
| --- | --- | --- |
| 条件間の比較 | test のうち `strong` と `normal`（両条件に共通する部分） | 同じデータで 2 つの条件のモデルを比べる |
| ややあり込みモデルの層別評価 | test 全体と，`mild` の部分 | 境界例でどれだけ誤るか（「評価指標」の層別評価） |
| **ややあり除外モデルに mild を推論させる** | test のうち `mild` | mild の画像が **淡紅と予測される割合**と**元のクラスと予測される割合**を出す．臨床で淡紅と判断されやすいという知見がデータ上でも成り立つかを確かめる |

- `mild` の画像に対して淡紅と予測することを「誤り」と断定しない．上表の割合として報告し，解釈は人間が行う

## クラス不均衡 (Class Imbalance)

実データのクラス分布は最大 / 最小 = 380 / 104 ≒ **3.7 倍**（[TEST_01](../06_TEST/TEST_01_データセット構成調査.md)）．中程度の不均衡であり，初回は対策を入れずに素の結果を見る．混同行列でどのクラスが落ちているかを確認してから，クラス重み付き損失等を**独立した実験**として追加し，効果を切り分けて評価する．

程度ラベル（`severity`）を含めた 9 クラス分類は採らない（最小クラス 51 枚・不均衡 6.6 倍となり学習が不安定になる．目的は TIASjudge の 5 分類の置き換えであるため）．

## 評価指標 (Metrics)

| 指標 | 役割 |
| --- | --- |
| **macro F1** | 主指標（クラス不均衡下で少数クラスを無視できないため） |
| accuracy | 参考（クラス分布に引っ張られる） |
| クラス別 precision / recall | どのクラスが弱いかの特定 |
| 混同行列 | 誤りの方向（隣接クラスとの混同か，飛んだ誤りか）の確認 |

- 舌色が順序尺度として扱える（淡白 → 淡紅 → 紅 → 暗赤紅 → 紫 のような並び）なら，**quadratic weighted kappa** を追加する．順序の妥当性は TIASjudge の定義と医学的な解釈を確認してから決める（未確定）
- **程度別の層別評価**: `severity` ごと（`strong` / `mild`）にクラス別 recall を出す．「ややあり」（`mild`）は境界例であり誤りが集中すると予想されるため，全体の指標だけでは改善の効果が見えない
- 医師ラベルの評価者間一致率が分かる場合は，モデル性能の上限の目安として併記する

## ベースライン (Baseline)

既存 TIASjudge のルールベース診断を同一テストセットで実行し，同じ指標で並べる．実装の取り込み方（移植 / 別リポジトリ参照）は未定とし，ベースライン実装に着手する時点で決める．

## 再現性 (Reproducibility)

- seed を設定ファイルで固定し，`config.yaml` に git コミットハッシュとともに記録する
- 完全なビット再現性（`torch.use_deterministic_algorithms`）は速度とのトレードオフのため求めない．代わりに**同一設定で複数 seed を回して振れ幅を確認する**
- 共用サーバのため，使用する GPU は明示的に指定する

## 未確定事項 (Open Items)

- 舌色 5 分類を順序尺度として扱えるか（quadratic weighted kappa の採用可否）
- 入力解像度 224 で足りるか（元画像は平均 675×614 で，約 1/3 に縮小することになる）
- 黒背景が面積の大半を占めるため，正規化・統計を画像全体で取るか舌領域内のみで取るか
- 「ややあり」を含めるか否かの結論（両条件の実験結果を見て決める）
- ルールベース診断の取り込み方
- 医師ラベルの評価者間一致率（分かれば性能の上限の目安になる）
