model-scaffold について
model-scaffoldは、医用画像研究向けのPyTorch学習リポジトリを生成するスキルです。6種類のタスクに対応し、患者単位の分割、乱数シード固定、学習コードの検査を組み込みます。
主な機能
- 016種類の医用画像タスク雛形
- 02患者単位の決定的な分割
- 03シード固定済みの学習・評価コード
- 04画像QCレポートの引き継ぎ
- 05学習コードの衛生状態検査
活用シーン
- 01患者ID付きマニフェストからモデルを開始
- 02臨床データで事前学習済みバックボーンを微調整
- 03生成コードの再現性対策を検査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ aperivue/ medsci-skills --skill model-scaffoldインストール後、Claude Code で/model-scaffoldを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
skill.ymlreferences/finetuning_guide.mdmlops_guide.mdtraining_guide.mdscripts/check_training_hygiene.pyscaffold.pyscripts/scaffold_challenge/problem.mdverify.shscripts/scaffold_challenge/expected/split_assignment.csvscripts/scaffold_challenge/fixture/manifest.csvtests/test_imaging_qc_handoff.shtest_training_hygiene.shtests/fixtures/bad_evaluate.pybad_train.pytests/fixtures/finetune_no_provenance/train.py詳細
Model-Scaffold Skill
目的
医用画像タスク向けの実行可能な PyTorch 学習リポジトリを生成するスキルです。--task
で segmentation(U-Net)、classification(CNN/timm バックボーン)、detection(torchvision Faster
R-CNN/FPN)、synthesis(Pix2Pix ジェネレーター+PatchGAN)、ssl(SimCLR エンコーダー)、または finetune
(凍結から凍結解除へと進むスケジュールと出自記録を含む、事前学習済みバックボーンの転移学習)を指定します。
再現性を構造上あらかじめ組み込むことで、最初のエポックを実行する前から、データリークを防ぎ再現可能なビルドを実現します。統計コードを実行可能な形で生成する /analyze-stats と同様、画像処理向けの仕組みです。ジェネレーターがリポジトリを作成し、GPU/Colab で学習を実行すると、レーンの決定論的なゲートがネットワーク不要の部分を検証します。
これはレーンに欠けていた中間リンクです。/model-selection(選択)→ model-scaffold(構築)
→ /model-assessment(分割/設計の検証、指標の計算)→ /analyze-stats
→ /write-paper + /check-reporting(公開)。MONAI/nnU-Net/TorchIO を(生成される requirements.txt で参照して)統合します。これらを再実装するものではありません。
使用する場合
- データマニフェスト(画像ごとに 1 行、患者/被験者 ID を含む)があり、セグメンテーション、分類、検出、合成、または自己教師ありモデル向けに、再現可能でデータリークを防ぐ出発点となるリポジトリが必要な場合。
- 事前学習済みバックボーンをファインチューニングする場合(転移学習 — 臨床医によくあるワークフロー:
収集した臨床データに合わせて
timm/MONAI/MedSAM のチェックポイントを適応させる)。凍結スケジュール、差別化学習率、事前学習済み重みの出自を記録できます(--task finetune)。
使用しない場合
- 学習済みモデルの検証設計を監査する場合 →
/model-assessment。 - ホールドアウト指標/キャリブレーション/ブートストラップ信頼区間を求める場合 →
/model-assessment、続いて/analyze-stats。 - 研究課題に適したアーキテクチャを選ぶ場合 →
/model-selection。 - MONAI/nnU-Net を再実装する場合 → 対象外です(このスキャフォールドはそれらを統合します)。
- LLM/MLLM を評価する場合 →
/mllm-eval。
ワークフロー
フェーズ 1 — マニフェストを準備する
画像ごとに 1 行の CSV を用意します。患者/被験者 ID の列(patient_id/subject_id/
case_id)に加え、画像とラベルのパスを示す列を含めます。ID 列は分割の基準となる重要な列です。この列に基づき、患者単位でデータを分割します。分割時も、生成される dataset.py でも、ID の前後の空白を取り除いて比較します(P01 と
P01 は同一の患者として扱われます)。
フェーズ 2 — リポジトリを生成する
python3 ${CLAUDE_SKILL_DIR}/scripts/scaffold.py \
--manifest <manifest.csv> --task segmentation --out model_repo --seed 42 \
--in-channels 1 --out-channels 1
# --task = segmentation | classification | detection | synthesis | ssl | finetune
# (out-channels = num classes for classification/finetune, target channels for synthesis;
# finetune uses a softmax CrossEntropy head, so it refuses --out-channels < 2 — binary = 2)
# fine-tuning a pretrained backbone (transfer learning) on collected clinical data:
python3 ${CLAUDE_SKILL_DIR}/scripts/scaffold.py \
--manifest <manifest.csv> --task finetune --out model_repo --seed 42 \
--out-channels <num_classes> --from-pretrained timm:resnet50.a1_in1k
# emits PRETRAINED.md (provenance) + a frozen→unfrozen train.py with discriminative LRs;
# record the exact pretrained source so the fine-tune is reproducible. build_model(pretrained=True)
# raises if timm is missing (never a silent random-init stand-in); best.pt records backbone_class.
# reuse the split /imaging-data's preprocessing gate checked (do not draw a new one):
python3 ${CLAUDE_SKILL_DIR}/scripts/scaffold.py \
--manifest <manifest.csv> --preprocessing-manifest preprocessing_manifest.json --out model_repo
# copies its split_assignment + split_seed into splits/, reading rows with the gate's own rules
# (patient key patient_id/subject_id/patient/id; split synonyms such as training/validation/holdout);
# exits 2 if a manifest patient has no split there, a patient sits in two splits, a split does not
# map to train/val/test, or split_seed is absent.
画像データの QC の引き継ぎは、推奨ではなく必須です。 --preprocessing-manifest を指定すると、スキャフォールドは /imaging-data のゲートレポート(check_dataset_profile、check_preprocessing_leakage、check_normalizer_domain の JSON)も <manifest dir>/qc/ と <manifest dir>/../qc/ から読み取ります(最初にマニフェストのパスを解決します)。--imaging-qc <file|dir>(複数回指定可能)はこの検索を置き換えます。空のディレクトリを指定した場合、すべてのゲートが NOT ASSESSED として記録されます。漏洩レポートがスキップされるのは、記録されたマニフェストのファイル名が異なり、そのパスが既存のファイルに解決され、かつ候補パスのどれにもスキャフォールドが生成したマニフェストとバイト単位で同一のコピーがない場合に限ります(理由も表示されます)。それ以外の場合、コピーされたプロジェクトや、別の場所にある同名のマニフェストも読み取られます。
- Major の指摘、または明らかに Minor/Flag ではない重大度の指摘、あるいは
summary.n_majorが列挙された Major の数を上回るレポートがある場合、処理は拒否されます。終了コードは 1 で、何も書き込まれず、各コードとレポートが一覧表示されます。上流で解決してゲートを再実行するか、コードごとに--ack-qc CODE='reason'を一度指定してください。 - Minor/Flag の指摘は処理をブロックしません。警告として引き継がれます。
- 読み取り可能なレポートがないゲートは NOT ASSESSED になります。
qc/内の解析不能なファイルや形式が異なるファイルは UNREADABLE として一覧表示され(stderr と記録に出力)、除外されません。
すべての情報は model_repo/IMAGING_QC.md に反映され、config.yaml(imaging_qc:)と REPRODUCIBILITY.md から参照されるため、トレーニング、評価、Methods で /imaging-data の検出内容を確認できます。ユーザーが指定していない --ack-qc の理由は決して書き込まないでください。どちらのフラグも指定しない場合、出力は変わりません。
これにより、config.yaml、model.py(タスクのモデル — U-Net/CNN/Faster R-CNN/Pix2Pix/SimCLR エンコーダー)、dataset.py(固定された分割を読み込みます)、losses.py(タスクに適した損失関数)、train.py、evaluate.py、requirements.txt、REPRODUCIBILITY.md、methods_stub.md(画像データの出力が指定されている場合は IMAGING_QC.md も含みます)、そして重要な成果物である splits/split_assignment.csv と splits/split_seed.txt を含む model_repo/ が書き出されます。分割は構造上、患者単位で重複しないように作成され(決定論的なグループ分割)、生成されるコードはすべての RNG にシードを設定し、cuDNN を決定論的にし、train 分割のみからトレーニングローダーを構築し、model.eval() と torch.no_grad() を使って推論します。
フェーズ 3 — ビルドを検証する(ネットワーク不要)
# this skill's own training-hygiene gate
python3 ${CLAUDE_SKILL_DIR}/scripts/check_training_hygiene.py --repo model_repo --strict
# the split-leakage gate (proves patient disjointness) — owned by /model-assessment
生成された splits/split_assignment.csv を /model-assessment に渡して(check_split_leakage.py --splits model_repo/splits/split_assignment.csv --strict)、患者単位で分割が重複していないことを検証します。また、必要に応じて torch をインストールしたローカル環境で bash ${CLAUDE_SKILL_DIR}/scripts/scaffold_challenge/verify.sh を実行し、フォワードパスをスモークテストします。
フェーズ 4 — データを組み込んでトレーニングする
dataset.py の _load_image/_load_label を、使用するモダリティに合わせて実装します(DICOM/NIfTI/TIFF。nibabel/pydicom/tifffile/TorchIO/MONAI transforms を使用)。本番環境では、model.py を MONAI の UNet/SegResNet または nnU-Net のプランに置き換えます(${CLAUDE_SKILL_DIR}/references/training_guide.md を参照)。ファインチューニング用リポジトリ(--task finetune)では、PRETRAINED.md を記入し、凍結スケジュールと識別的学習率を設定します(MedSAM/SAM の適応とトレーニングデータのみを使った拡散データ拡張についても説明する ${CLAUDE_SKILL_DIR}/references/finetuning_guide.md を参照)。python train.py を実行します(最良のモデルは val 分割で選択されます)。続いて python evaluate.py を実行します(test 分割で予測を行い、一度だけ使用します)。
フェーズ 5 — 検証、評価、公開
/model-assessment(検証ティア + 比較対象 + 指標選択の監査。信頼区間付き Dice +
HD95/NSD)+ /analyze-stats、/make-figures、/write-paper
(methods_stub.md の [VERIFY] プレースホルダーを埋めます)+ /check-reporting(CLAIM 2024 / TRIPOD+AI)に引き継ぎます。実験追跡(W&B / MLflow)、設定 / データ / 環境のバージョン管理、MLOps 報告チェックリストを再現性を損なわずに接続する方法については、${CLAUDE_SKILL_DIR}/references/mlops_guide.md を参照してください(接続と報告のリファレンスです。フレームワークへの案内を目的としており、フレームワークの代わりにはなりません)。
実行可能性 — 誠実な取り決め
生成されたリポジトリは実行可能ですが、実行可能性はCI で保証されるものではありません。既定のゲートでは、生成されたアーティファクトを解析して、ネットワークに依存しない特性(出力された分割が患者単位で重複せず、シードが固定されていること、および出力されたトレーニングコードが適切であること)を確認します。torch は実行されません。torch のフォワードパスのスモークテスト(build + forward shape + gradients flow + reproducible loss)は、チャレンジの verify.sh における条件付きスキップティアであり、ローカル実行用のコマンドとして文書化されています。実行可能性を CI でカバーしているものとして数えることはありません。
ハルシネーションの防止
- トレーニングや評価の指標を決して捏造しないでください。 スキャフォールドは
[VERIFY]プレースホルダーを出力します。すべての数値は、ユーザーが実行した結果と/model-assessment+/analyze-statsに基づく必要があります。 - 患者単位で重複している分割や、シードが固定されていない分割を決して出力しないでください。 ジェネレーターはそのような分割を生成しない設計になっています。重複を生じさせたり、シードを削除したりするために、分割テーブルを手作業で編集しないでください。
- 生成されたリポジトリをトレーニング済みである、または成果を達成したと決して主張しないでください。 これはユーザーが実行するための出発点です。
- ライブラリ API、既定値、またはアーキテクチャの詳細が不確かな場合は、推測せずに
[VERIFY]として示し、確認してください。
決定論的なゲート
scripts/scaffold.py— ジェネレーター(stdlib + numpy。マニフェストとシードが同じであれば決定論的)。画像データの QC 引き継ぎ(tests/test_imaging_qc_handoff.sh)も行います。scripts/check_training_hygiene.py— AST リンター:すべての RNG にシードが設定されていること、cuDNN が決定論的であること、推論でeval()+no_grad()を使うこと、トレーニング用ではない分割でトレーニングしないこと、および(ファインチューニング時に)事前学習済み重みを読み込む場合、その出自が記録されていること(PRETRAINED_PROVENANCE_MISSING)。scripts/scaffold_challenge/verify.sh— ビルド → 検証のチェーン。ネットワークに依存しません(torch ティアは条件付きでスキップされます)。
check_training_hygiene.py の既知の制限
- シード設定 / cuDNN /
eval()/no_grad()のチェック対象は、スクリプトのインポート時の文から実行されるコードに限られます。インポート時に自身の関数を呼び出さないファイルの場合、参照されていないすべての公開トップレベル関数を経由して処理が入るため、呼び出されていない公開seed_everythingもカウントされます。デコレートされた関数やメソッド(click/typer コマンド、ルート、@staticmethod)もすべてエントリーポイントとなるため、呼び出されていないデコレート済みのシード設定ヘルパーもカウントされます。 - 文の順序はチェックしません。同じ関数内で推論を
model.eval()より前に行っていても検出されません。 train.py/evaluate.pyがない状態で--repoを指定すると、該当するチェックは NOT CHECKED と報告されます。--strictを指定した場合、それらを問題なしとせず、終了コード 2 で終了します。- データセット変数は、ファイル全体に対する単一の名前と分割のマップで解決されます(関数をまたいでソース順の最後の代入が優先されます)。train と val のみを組み合わせるシャッフル済みローダー(train+val による再フィット)は検出されません。
境界
model-selection (choose)
└─ model-scaffold (this skill: generate the reproducible repo)
├─ check_training_hygiene.py (training-code hygiene)
├─ model-assessment -> analyze-stats (split-leakage proof, validation design, metrics + CIs)
└─ write-paper + check-reporting (Methods stub -> compliant manuscript)