Newer
Older
TIASJudgeModel / docs / 04_SPEC / SPEC_02_学習・評価仕様.md

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

前処理 (Preprocessing)

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

データ拡張 (Augmentation)

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

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

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

モデル (Model)

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

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

学習の設定 (Training Settings)

設定 YAML の model・train 節で与える(SPEC_01「設定ファイル」).既定値は次のとおり.

項目既定値備考
model.nameconvnext_tinytimm のモデル名
model.pretrainedtrueImageNet 事前学習の重み(初回はサーバがダウンロードする).合成データの試験では false
train.image_size224アスペクト比を保って長辺を合わせ,余白を黒で埋める(レターボックス)
train.batch_size32—
train.max_epochs40—
train.patience8検証の macro F1 がこのエポック数改善しなければ打ち切る
train.lr1e-4AdamW
train.weight_decay0.05AdamW
train.warmup_epochs2線形 warmup の後 cosine で減衰
train.inner_val_ratio0.15交差検証の各 fold で,学習側から早期終了用の検証データを取る割合(下記)
train.num_workers4DataLoader
train.amptrueCUDA のときだけ混合精度
  • データ拡張(学習時のみ): 左右反転(確率 0.5)・回転 ±10°・拡大縮小 0.9〜1.1 倍・平行移動わずか.はみ出した部分は黒で埋める.色を変える拡張は行わない(上記「データ拡張」)
  • 正規化: ImageNet の mean / std
  • デバイス: CUDA があれば cuda(CUDA_VISIBLE_DEVICES で割り当てられた GPU),無ければ CPU
  • 高速化のため,レターボックス済みの画像(uint8)をメモリに載せてから学習してよい(1085 枚 × 224² × 3 ≒ 160 MB)

交差検証の実行 (Cross-Validation Run)

1 つのジョブで 5 つの fold を順に学習・評価し,1 つの実験ディレクトリ runs/<実験ID>/ にまとめて書き出す.「ややあり込み」と「ややあり除外」は別のジョブ(別の実験 ID)として回す.

  1. manifest 全体で患者単位・9 グループ層化の 5-fold 分割を作る(data.severities に関わらず同じ分割.上記「程度(ややあり)の扱い」)
  2. 各 fold について
    1. 学習側(held_out 以外)から train.inner_val_ratio の患者を検証用に取る(患者単位・9 グループ層化.seed は分割と同じ設定から決める)
    2. data.severities を学習用と検証用にだけ適用する(held_out には適用しない.下記)
    3. 検証の macro F1 が最良のエポックの重みを採用する(早期終了)
    4. held_out(全程度を含む)で 1 回だけ評価する
  3. 全 fold の held_out の予測をまとめて集計する

評価の出し方 (Evaluation Output)

held_out は data.severities に関わらず全程度の画像で評価し,次の部分集合ごとに指標を出す.これで 2 つの条件のジョブを同じ土俵で比べられる.

部分集合内容用途
allheld_out の全画像ややあり込みの全体性能
commonheld_out のうち strong と normal2 条件の比較(両条件とも学習に含まれる部分)
mildheld_out のうち mild境界例の扱い
  • 各部分集合で: macro F1・accuracy・クラス別 precision / recall / F1・混同行列(common と all)
  • mild では加えて予測の内訳を出す: 淡紅と予測された割合・元のクラスと予測された割合・その他のクラスと予測された割合(クラス別と全体)
  • fold ごとの値と,fold 間の平均 ± 標準偏差を出す.混同行列は全 fold の合計も出す
  • 画像ごとの予測(個票)は predictions.csv に保存し,回収しない

出力 (Run Artifacts)

SPEC_01「実験の出力」の名前に従う.

ファイル内容回収
config.yaml解決済み設定・git ハッシュ・seedする
metrics.jsonfold ごと・fold 平均の指標(上記の部分集合ごと),各 fold の最良エポック,所要時間(下記)する
history.csvfold・エポックごとの学習損失・検証損失・検証 macro F1・学習率・そのエポックの所要秒数する
confusion_matrix.csv全 fold 合計の混同行列(common と all)する
log.txtログする
figures/*.png学習曲線・混同行列する
split.json・predictions.csv分割と個票の予測(患者 ID を含む)しない
checkpoints/fold<k>.pt各 fold の最良の重み--with-checkpoints のときだけ

所要時間の記録(2026-09-28 ユーザー要望): metrics.json に次を含める.モデル間・条件間で計算コストも比べられるようにするため.

  • 全体の所要秒数(データの読み込みから書き出しまで)と,データの読み込み(レターボックス化)にかかった秒数
  • fold ごとの学習の所要秒数・held_out の評価の所要秒数・実際に回したエポック数・1 エポックあたりの平均秒数
  • 実行環境: デバイス(GPU 名または CPU)・モデル名・パラメータ数

データ分割 (Data Split)

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

現在のデータセットは 1 患者 1 枚であることを確認済みのため(2026-09-27.TEST_01),画像単位の分割が患者単位の分割と一致する.ただし実装は常に 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「回収ホワイトリスト」)

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

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

実験条件 (Conditions)

設定 data.severities(SPEC_01「設定ファイル」)で使う程度を選ぶ.

条件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 のうち mildmild の画像が 淡紅と予測される割合と元のクラスと予測される割合を出す.臨床で淡紅と判断されやすいという知見がデータ上でも成り立つかを確かめる
  • mild の画像に対して淡紅と予測することを「誤り」と断定しない.上表の割合として報告し,解釈は人間が行う

クラス不均衡 (Class Imbalance)

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

程度ラベル(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 に縮小することになる)
  • 黒背景が面積の大半を占めるため,正規化・統計を画像全体で取るか舌領域内のみで取るか
  • 「ややあり」を含めるか否かの結論(両条件の実験結果を見て決める)
  • ルールベース診断の取り込み方
  • 医師ラベルの評価者間一致率(分かれば性能の上限の目安になる)