TIASjudge への組み込み(Issue #9)に向けて,(1) DeepTIAS 2.7 の舌セグメンテーション(検出+ResUNet)を Python で再現して正解マスク付きデータで IoU を測り,(2) 色特徴+ロジスティック回帰の最終モデルを全データで学習して書き出した結果.引き渡し仕様は SPEC_04.
| 項目 | 内容 |
| 実行日時 | 2026-09-28 23:28〜23:34(約 5 分) |
| 実行場所 | Newton の CPU(tias-remote run --cpu) |
| コマンド | tias-seg eval --config configs/seg/eval_newton.yaml |
| データ | ResUNet の開発時の正解マスク付きデータ(研究室 PC から両サーバの ~/data/TongueSegmentation/input/ に配置.ENV_03) |
| モデル | DeepTIAS 2.7 同梱の ResUNet.onnx(開発元フォルダの ONNX とハッシュが一致)と,Detection_Normal.pb を scripts/convert_detection_to_onnx.py(tf2onnx 1.17・opset 13)で変換した Detection_Normal.onnx |
| コード | 405ab01-dirty(本ブランチの実装を未コミットのまま使用) |
評価セットは,開発時に切り出し済みの画像(cropped.学習時と同じ入力条件)と,撮影画像そのもの(fullsize).fullsize では舌の枠の決め方を 3 通り比べた.
| 評価セット | 枚数 | 枠の決め方 | IoU 平均 | 中央値 | 10 % 点 | 最小 | IoU 0.8 未満 | 1 枚の秒数 |
| test(切り出し済み) | 170 | 画像全体 | 0.959 | 0.966 | 0.926 | 0.880 | 0 | 0.25 |
| test_extra(切り出し済み) | 180 | 画像全体 | 0.956 | 0.965 | 0.916 | 0.858 | 0 | 0.21 |
| train(切り出し済み.学習に使ったもの) | 382 | 画像全体 | 0.981 | 0.986 | 0.965 | 0.850 | 0 | 0.23 |
| test(撮影画像) | 170 | 検出モデル | 0.958 | 0.967 | 0.918 | 0.864 | 0 | 0.39 |
| test(撮影画像) | 170 | 正解マスクの外接矩形 | 0.947 | 0.951 | 0.914 | 0.860 | 0 | 0.23 |
| test(撮影画像) | 170 | 検出なし(画像全体) | 0.458 | 0.444 | 0.238 | 0.103 | 162 | 0.24 |
- IoU は舌(前景)の IoU.正解マスク(JPEG)は 128 以上を前景とした.小領域除去(後処理)の有無で平均は変わらなかった(後処理が働いたのは検出なしで 42 枚,それ以外は 0〜2 枚)
- 出力チャンネル 0 を舌として使うと IoU 0.96,チャンネル 1 を使うと 0.003〜0.04 で,チャンネル 0 が舌であることを確認した(DeepTIAS の C# の読み取りと一致)
- 画像ごとの IoU はサーバ上の
predictions.csv にだけ置き,回収していない(回収したのは集計値と IoU のヒストグラムのみ)
- DeepTIAS の手順を Python で再現できた.撮影画像から検出モデル → ResUNet の流れで IoU 0.958(最小 0.864).DeepTIAS の開発時の報告値(ResUNet のモデル名に付いた 0.9518)と同じ水準で,切り出し済みの評価セット(0.959)とも差が無い
- 検出は必須.検出を省いて撮影画像全体に ResUNet を掛けると IoU 0.46 に落ちる(ResUNet は切り出し後の画像で学習されているため)
- 変換した検出モデルは 170 枚すべてで舌を見つけた(スコア 0.5 超).正解マスクの外接矩形よりも IoU がやや高いのは,検出の枠に余白があり,学習時の切り出し方に近いためと考えられる
- 1 枚あたり約 0.4 秒(Newton の CPU.検出+ResUNet+後処理).TIASjudge の手元 PC でも実用的な速さと見込まれる
- DeepTIAS の細部で確かめられていない値がある(検出モデルへ渡す色の順,枠のサイズに戻したマスクの 2 値化のしきい値,輪郭の数え方の Canny のしきい値など).いずれも設定で変えられ,IoU には大きく効かないと見られるが,学習データのマスクとビット単位で一致するかは確かめていない
- 学習データ(舌色データセット)のマスクとの一致は未確認.舌色データセットはマスク適用後の画像しか無く,元の撮影画像が無いため.元画像が残っていれば,同じ画像で DeepTIAS の出力と比べられる
- OpenCV のバージョン(DeepTIAS は 3.x,本実装は 5.0)による resize・大津の 2 値化の微小な差はありうる
| 項目 | 内容 |
| 実行日時 | 2026-09-28 23:26〜23:28 |
| 実行場所 | Archimedes の CPU |
| コマンド | tias-train color-export --config configs/export/color_logistic_<with_mild \| without_mild>.yaml |
| 分類器 | 色特徴(107 次元)+ロジスティック回帰(class_weighting なし).C は全データの患者単位 5-fold(seed 42)の held_out macro F1 の平均で選ぶ |
| 設定 | 学習枚数 | 採用した C | C の候補ごとの fold 平均 macro F1(0.01 / 0.1 / 1 / 10 / 100) |
| ややあり除外 | 754(淡白 53・淡紅 337・紅 61・暗赤紅 247・紫 56) | 0.1 | 0.636 / 0.669 / 0.645 / 0.602 / 0.546 |
| ややあり込み | 1085(淡白 104・淡紅 337・紅 119・暗赤紅 380・紫 145) | 0.1 | 0.575 / 0.580 / 0.553 / 0.528 / 0.491 |
- ここでの macro F1 は C を選ぶための値で,held_out にも
data.severities を適用している(除外の設定では held_out にもややありが無い).評価指標としては TEST_05 の値(common macro F1 0.630〜0.644)を使う
- 書き出した
color_model.json(約 28 KB)には,特徴の定義・標準化の値・係数・切片・クラス・学習条件・来歴が入り,患者 ID・ファイル名・画像単位の値は含まない(テストで確認)
- NumPy だけの参照実装
src/tias_judge_model/deploy/color_model.py で読み込み,学習側と同じ予測になることを確かめた(特徴はビット一致,予測確率の差は 1e-12 以下.合成データでのテスト)
- TIASjudge 側(TIASjudge の Issue #13)で,SPEC_04 に従って判定モードを組み込む
- どちらの判定モデル(ややあり込み/除外)を使うかを決める(SPEC_04「未決事項」)
- 元の撮影画像が残っていれば,舌色データセットのマスクとの一致を確かめる
手元の runs/ に回収済み(.gitignore 対象).
ls -d runs/20260928-232850_eval_newton_405ab01-dirty runs/*_color_logistic_*_405ab01-dirty