simoyaman/Ct_anomaly_detector
0
CT画像 正常逸脱度検出ツール
CT断面画像(MedMNIST OrganAMNIST)の正常画像のみでConvolutional Autoencoderを学習し、 入力画像がどの程度その分布から逸脱しているか(再構成誤差)を可視化する Gradio アプリです。 ポートフォリオ4本目として、1〜3本目の医療軸の集大成の位置づけで、放射線技師向けの 「読影優先順位付け」支援デモを目的としています(収益化は目的としていません)。
重要な前提・免責事項
- 本ツールは診断ツールではありません。 「診断する」のではなく「見直し優先度を判断する」 補助を想定した情報提供・学習目的のデモです。
- 正常画像のみで学習したオートエンコーダの再構成誤差を「正常データからの統計的な逸脱度」として 表示しています。「異常度が高い」ことは病気の存在を意味しません。 単に学習データの分布から 外れているだけの可能性もあります。
- 実際の画像診断は必ず医師・専門の医療従事者が行ってください。
- 実在の患者データは使用していません。 MedMNIST由来の匿名化・公開済みデータのみを使用しています。
- 上記の免責文は、結果表示の直下に常時表示しています。
データセット・出典
- MedMNIST v2(
pip install medmnist)の OrganAMNIST - 元データは肝臓腫瘍セグメンテーションベンチマーク LiTS の3D CT画像から、11種類の腹部臓器を軸位断面で2Dスライスとして切り出し、匿名化・公開されたもの
- MedMNISTは学術・研究・教育目的での利用を想定した公開データセットです
- MedMNISTには「異常/正常」を区別するラベルは存在しません。本デモでは以下の方針を採っています。
- 学習: OrganAMNISTのtrain分割の画像(臓器の種類を問わず、すべて「正常な腹部CT断面」として扱う) のみでオートエンコーダを学習
- 校正: val分割の画像に対する再構成誤差(MSE)の分布から、逸脱度スコアの基準値 (99パーセンタイル)を算出
- デモ用「異常」サンプル: test分割の画像に対して、ノイズ付加・構造的アーチファクト (チェッカーボードパターン)・部分的な欠損(オクルージョン)を人工的に加えたものを
samples/に用意し、逸脱度スコアが実際に上がることを実演
手法
- モデル: Convolutional Autoencoder(PyTorch)。入力: 28×28 グレースケール1ch (OrganAMNISTの標準サイズ。64×64版はダウンロードが大きく不安定だったため不採用)
- Encoder: Conv2d ×3(stride=2)→ Flatten → Linear(潜在次元16)
- Decoder: Linear → Reshape → ConvTranspose2d ×3(stride=2)→ Sigmoid
- ボトルネック(潜在次元)は意図的に小さく絞っています。潜在次元を大きくすると オートエンコーダが汎用的な「ぼかし関数」を学習してしまい、コントラスト反転のような 大域的な異常も違和感なく再構成できてしまう(=逸脱度が上がらない)ことが実験で 分かったため、正常画像の分布によりシビアに適合するよう調整しています。
- 学習: OrganAMNISTのtrain分割(34,561枚・正常画像)のみ、MSE損失、Adam最適化、25epoch (CPU環境で約9分)
- 逸脱度スコア: テスト画像の再構成誤差(MSE)を、学習時に算出した正常データ(val分割)の 99パーセンタイル値で正規化し、0〜100(超えると100超)のスコアとして表示
- スコア ≦ 100 の目安: 学習データ中の正常画像として典型的な範囲内 → 「正常範囲内」
- スコア > 100 の目安: 学習時に見た正常画像の分布からは外れている → 「要確認」
- 可視化: 元画像・再構成画像・画素ごとの絶対誤差ヒートマップ(matplotlib)を並べて表示
- 動作確認結果(
samples/の12枚で検証): 正常画像の平均スコア 63.5 に対し、 人工異常画像の平均スコア 128.3。特にノイズ付加・構造的アーチファクトは全サンプルで 閾値(100)を明確に上回り、逸脱度スコアが意図通り機能することを確認済み。
MVPに含めていない機能(将来の拡張候補)
- 部位(臓器)ごとの個別モデル(まずは全臓器混合の単一モデルで様子を見る)
- 実際の異常症例データでの検証(データ取得のハードルが高いため)
- リアルタイムでの3Dボリューム対応
ディレクトリ構成
ct-anomaly-detector-app/
├── app.py # Gradio UI
├── model_def.py # オートエンコーダのモデル定義(app.py / train_autoencoder.py 共通)
├── train_autoencoder.py # OrganAMNIST正常画像のみで学習するスクリプト
├── generate_anomaly_samples.py # デモ用サンプル(正常・人工異常)の生成スクリプト
├── model/
│ ├── autoencoder.pth # 学習済み重み
│ └── autoencoder_meta.json # 画像サイズ・潜在次元・スコア校正値などのメタデータ
├── samples/ # デモ用サンプル画像(正常・人工異常)
├── requirements.txt
└── README.mdセットアップ・使い方
1. 依存パッケージのインストール
python -m venv .venv
source .venv/bin/activate # Windowsは .venv\Scripts\activate
pip install -r requirements.txt2. モデルの学習(重みが同梱されていない場合)
python train_autoencoder.py --epochs 15初回実行時に medmnist パッケージが OrganAMNIST データセットを自動ダウンロードします。 学習が完了すると model/autoencoder.pth(重み)と model/autoencoder_meta.json (スコア校正用メタデータ)が生成されます。
動作確認だけ手早く行いたい場合は、画像数を制限して高速に実行できます。
python train_autoencoder.py --limit-samples 2000 --epochs 23. デモ用サンプル画像の生成
python generate_anomaly_samples.pysamples/ に正常画像(normal_*.png)と人工的に異常を加えた画像(anomaly_*.png)が生成されます。
4. アプリの起動
python app.pyブラウザで表示されるURL(既定では http://localhost:7860)を開くと利用できます。 画像をアップロードするか、サンプル画像を選択して「逸脱度を計算する」を押すと、 元画像・再構成画像・差分ヒートマップと逸脱度スコアが表示されます。
Hugging Face Spaces へのデプロイ
- Space を新規作成し、SDK は Gradio を選択
- 本ディレクトリの内容一式(
app.py/model_def.py/model//samples//requirements.txtなど)をそのまま push model/autoencoder.pthはバイナリファイルのため Git LFS での管理を推奨します (git lfs track "*.pth")- 追加設定不要で
app.pyが自動的に起動します
