本仓库基于原始 MedCLIP 项目进行课程迁移实践:保留原 PyTorch 代码,同时新增一套 MindSpore 版本实现,用于复现 MedCLIP 的医学图文对比学习主链路。
原论文:
Wang, Zifeng; Wu, Zhenbang; Agarwal, Dinesh; Sun, Jimeng. MedCLIP: Contrastive Learning from Unpaired Medical Images and Texts. EMNLP 2022.
论文链接:MedCLIP paper
MedCLIP 的核心任务是学习胸部 X 光图像与放射报告/疾病提示语之间的共享语义表示,用于零样本疾病识别、图文检索、少样本迁移和后续医学影像分析。相比普通 CLIP,MedCLIP 需要处理医学场景中的几个特殊问题:
- 医学图像与报告常常不是完整一一配对数据。
- 胸片疾病标签是多标签、多病灶、多不确定性监督。
- 不同患者可能具有相同影像发现,普通 InfoNCE 容易制造伪负样本。
- 报告文本含否定、不确定性、历史比较和专业医学术语。
本项目的迁移重点不是简单替换 API,而是尽可能保留原 MedCLIP 的数据处理、图文编码、语义匹配损失、训练、评估、checkpoint 和最终验收逻辑。
.
├── medclip/ # 原始 PyTorch MedCLIP 代码,保留用于对照
├── medclip_ms/ # 新增 MindSpore 迁移实现
│ ├── constants.py # CheXpert 标签、图像尺寸、默认权重名等常量
│ ├── dataset.py # 图文训练集、zero-shot 验证集、collator、batch loader
│ ├── evaluator.py # binary / multiclass / multilabel 指标评估
│ ├── image_processing.py # X-ray 图像读取、灰度化、padding、resize、归一化
│ ├── losses.py # hard CLIP loss 与 MedCLIP soft semantic matching loss
│ ├── modeling_medclip.py # MindSpore 双塔模型、prompt classifier
│ ├── prompts.py # CheXpert 疾病 prompt 构造
│ ├── tokenization.py # simple tokenizer 与 MindNLP tokenizer 适配
│ ├── trainer.py # MindSpore value_and_grad 训练循环
│ └── utils.py # context、seed、Tensor 转换等工具
├── examples/
│ ├── run_medclip_pretrain.py # 原始 PyTorch 训练入口
│ ├── run_medclip_ms_pretrain.py # MindSpore 训练/评估入口
│ └── run_medclip_torch_baseline.py# PyTorch baseline 指标导出入口
├── tools/
│ ├── prepare_medclip_data.py # 官方 CheXpert/MIMIC 数据准备与 metadata 校验
│ ├── preflight_migration_run.py # 云端运行前环境/数据/依赖预检
│ ├── convert_torch_medclip_to_mindspore.py # PyTorch 权重到 MindSpore ckpt 转换
│ ├── export_torch_checkpoint_to_npz.py # PyTorch 权重导出为 npz 桥接格式
│ ├── run_migration_acceptance_pipeline.py # PyTorch-vs-MindSpore 验收流水线
│ ├── audit_migration_acceptance.py # 最终指标/manifest/转换报告审计
│ ├── verify_evaluator_parity.py # 指标口径一致性验证
│ └── verify_mindspore_migration.py # 静态迁移校验
├── requirements.txt # 原始 PyTorch 依赖
├── requirements_ms.txt # MindSpore 迁移版依赖
├── MINDSPORE_MIGRATION.md # MindSpore 快速说明
└── MINDSPORE_CODE_GUIDE.md # 迁移代码详细说明
MindSpore 版本采用并行包设计:medclip/ 保留原 PyTorch 实现,medclip_ms/ 实现 MindSpore 复现链路。这样既方便逐文件对照,也避免破坏原仓库结构。
整体数据流如下:
official CSV / images / reports
-> ImageTextContrastiveDataset / ZeroShotImageDataset
-> ImageTextContrastiveCollator / ZeroShotImageCollator
-> NumPy batch
-> tree_to_tensor
-> MindSpore Tensor batch
-> MedCLIPModel
-> ImageTextContrastiveLoss
-> Trainer.value_and_grad
-> optimizer update
-> Evaluator
-> metrics + manifest + checkpoint
medclip_ms/dataset.py 对齐原 MedCLIP metadata 约定,训练 metadata 需要包含:
imgpathreport- CheXpert 14 个标签列
训练样本输出:
image: float32, shape (1, 224, 224)
report: str
img_label: float32, shape (14,)
text_label: float32, shape (14,)
图像预处理位于 medclip_ms/image_processing.py:
image path / PIL image
-> grayscale
-> pad to square
-> resize to 224 x 224
-> center crop / train augmentation
-> normalize
-> output shape (1, 224, 224)
文本处理位于 medclip_ms/tokenization.py。正式可比实验使用 --backbone mindnlp,加载 MindNLP 的 BioClinicalBERT/Swin 等资产;simple 后端只保留为开发调试路径,不作为最终提交说明中的性能复现方案。
medclip_ms/modeling_medclip.py 实现 MindSpore 版本 MedCLIPModel:
pixel_values -> vision encoder -> projection -> L2 normalize -> img_embeds
input_ids -> text encoder -> projection -> L2 normalize -> text_embeds
img_embeds x text_embeds -> logits_per_image
返回字段与原 CLIP/MedCLIP 风格保持一致:
img_embeds
text_embeds
logits
loss_value
logits_per_text
medclip_ms/losses.py 中的 ImageTextContrastiveLoss 支持两种模式:
hard CLIP:
image_i <-> text_i
soft MedCLIP:
label_sim = img_labels @ text_labels.T
target = softmax(label_sim)
loss = bidirectional soft cross entropy(logits, target)
第二种模式对应 MedCLIP 的关键思想:不是简单把非配对样本全部当负样本,而是根据疾病标签语义构造软目标,从而缓解医学图文对比学习中的伪负样本问题。
medclip_ms/trainer.py 使用 MindSpore 原生训练方式:
forward_fn
-> mindspore.value_and_grad
-> clip_by_global_norm
-> optimizer(grads)
-> periodic evaluation
-> save mindspore_model.ckpt
训练结束后会再次运行 evaluator,并将最终评估结果写入 metrics_json。这比只记录训练中间日志更适合做 PyTorch-vs-MindSpore 最终验收。
medclip_ms/evaluator.py 支持:
binarymulticlassmultilabel
MindSpore 入口可以输出:
eval_scores.jsonrun_manifest.jsonmindspore_model.ckpt
run_manifest.json 会记录 framework、backbone、device、数据列表、初始化方式和 metrics 来源,用于最终审计比较。
如果只运行原始 MedCLIP:
pip install -r requirements.txt原始 PyTorch 代码中部分路径依赖 CUDA,建议在 NVIDIA GPU 环境运行 PyTorch baseline。
先安装与目标运行环境匹配的 MindSpore。不同硬件需要匹配不同 wheel、CANN 或 CUDA 版本,建议以 MindSpore 官方安装选择器为准:
https://www.mindspore.cn/install
随后安装本项目 MindSpore 依赖:
pip install -r requirements_ms.txt如需正式可比训练的 --backbone mindnlp:
pip install mindnlp该脚本用于检查源码结构、关键 API 和数据契约,提交前可作为静态质量检查:
python tools/verify_mindspore_migration.py在正式训练前,先检查 MindSpore、MindNLP、metadata 和图像路径是否齐全:
python tools/preflight_migration_run.py \
--check_mindspore \
--require_mindnlp \
--check_mindnlp_assets \
--data_root ./local_data \
--sample_images 20 \
--report_json ./migration_acceptance/preflight_mindspore_report.json用于确认 MindSpore evaluator 的 acc、precision、recall、F1 等计算口径与 PyTorch-style 公式一致:
python tools/verify_evaluator_parity.py本仓库不包含真实 CheXpert/MIMIC-CXR 图像和报告。需要先按官方要求申请授权并下载数据:
- CheXpert: Stanford AIMI / CheXpert 官方入口
- MIMIC-CXR-JPG 与 MIMIC-CXR reports: PhysioNet credentialed access
查看数据准备说明:
python tools/prepare_medclip_data.py instructionspython tools/prepare_medclip_data.py build-chexpert-meta \
--chexpert_csv /path/to/CheXpert-v1.0-small/train.csv \
--chexpert_root /path/to/CheXpert-v1.0-small \
--absolute_imgpaths \
--data_root ./local_data \
--report_json ./local_data/chexpert_meta_report.jsonpython tools/prepare_medclip_data.py build-mimic-meta \
--mimic_jpg_root /path/to/mimic-cxr-jpg/2.1.0 \
--mimic_report_root /path/to/mimic-cxr/2.1.0 \
--data_root ./local_data \
--frontal_only \
--absolute_imgpaths \
--report_json ./local_data/mimic_meta_report.jsonpython tools/prepare_medclip_data.py validate-medclip-metadata \
--data_root ./local_data \
--sample_images 20 \
--report_json ./local_data/metadata_validation_report.json如果 CSV 中 imgpath 是相对路径,增加:
--image_root /path/to/dataset-root使用已授权真实数据,并启用 MindNLP backbone:
python examples/run_medclip_ms_pretrain.py \
--device_target Ascend \
--mode pynative \
--backbone mindnlp \
--vision_model vit \
--data_root ./local_data \
--train_data chexpert-train mimic-cxr-train \
--eval_data chexpert-5x200-val \
--batch_size 100 \
--eval_batch_size 256 \
--epochs 10 \
--lr 2e-5 \
--weight_decay 1e-4 \
--warmup 0.1 \
--eval_steps 1000 \
--save_steps 1000 \
--n_prompts 10 \
--save_best_model \
--load_best_model_at_last \
--output_path ./checkpoints_ms/vision_text_pretrain \
--metrics_json ./checkpoints_ms/vision_text_pretrain/eval_scores.json \
--manifest_json ./checkpoints_ms/vision_text_pretrain/run_manifest.json如果在 NVIDIA GPU 的 MindSpore 环境:
--device_target GPU已有 MindSpore checkpoint 时,可以直接评估:
python examples/run_medclip_ms_pretrain.py \
--device_target Ascend \
--mode pynative \
--backbone mindnlp \
--vision_model vit \
--data_root ./local_data \
--eval_only \
--checkpoint ./checkpoints_ms/vision_text_pretrain/mindspore_model.ckpt \
--eval_batch_size 256 \
--n_prompts 10 \
--metrics_json ./checkpoints_ms/eval_only/eval_scores.json \
--manifest_json ./checkpoints_ms/eval_only/run_manifest.json \
--output_path ./checkpoints_ms/eval_only为了证明迁移质量,需要在同一数据、同一超参和同一初始化策略下跑 PyTorch baseline。入口如下:
python examples/run_medclip_torch_baseline.py \
--device cuda:0 \
--vision_model vit \
--data_root ./local_data \
--train_data chexpert-train mimic-cxr-train \
--eval_data chexpert-5x200-val \
--batch_size 100 \
--eval_batch_size 256 \
--epochs 10 \
--lr 2e-5 \
--weight_decay 1e-4 \
--warmup 0.1 \
--eval_steps 1000 \
--save_steps 1000 \
--n_prompts 10 \
--output_path ./migration_acceptance/torch \
--metrics_json ./migration_acceptance/torch/eval_scores.json \
--manifest_json ./migration_acceptance/torch/run_manifest.json为了保证 PyTorch 与 MindSpore 使用同一初始化来源,可以先把 PyTorch checkpoint 导出为 npz,再转成 MindSpore .ckpt。
python tools/export_torch_checkpoint_to_npz.py \
--torch_checkpoint ./migration_acceptance/torch/initial_pytorch_model.bin \
--output_npz ./migration_acceptance/torch/pytorch_model.npz \
--report_json ./migration_acceptance/torch/pytorch_model.npz.report.jsonpython tools/convert_torch_medclip_to_mindspore.py \
--torch_checkpoint ./migration_acceptance/torch/pytorch_model.npz \
--output_ckpt ./migration_acceptance/mindspore/converted_from_torch.ckpt \
--vision_model vit \
--backbone mindnlp \
--validate_load \
--report_json ./migration_acceptance/mindspore/converted_from_torch.report.json转换报告会记录:
- 源参数数量
- 目标 MindSpore 参数数量
- 成功映射数量
- 未匹配参数
- 歧义参数
match_ratiovalidate_load_result
这一步用于防止静默错映射。
tools/run_migration_acceptance_pipeline.py 会按同一配置生成 PyTorch 与 MindSpore 的完整验收命令。默认先预览命令;确认无误后加 --run 才会执行。
python tools/run_migration_acceptance_pipeline.py \
--data_root ./local_data \
--work_dir ./migration_acceptance \
--convert_checkpoint \
--use_npz_bridge \
--check_mindnlp_assets \
--torch_python /path/to/torch-env/bin/python \
--mindspore_python /path/to/mindspore-env/bin/python \
--converter_python /path/to/mindspore-env/bin/python \
--checkpoint_exporter_python /path/to/torch-env/bin/python \
--audit_python /path/to/base-env/bin/python确认后执行:
python tools/run_migration_acceptance_pipeline.py \
--run \
--data_root ./local_data \
--work_dir ./migration_acceptance \
--convert_checkpoint \
--use_npz_bridge \
--check_mindnlp_assets \
--torch_python /path/to/torch-env/bin/python \
--mindspore_python /path/to/mindspore-env/bin/python \
--converter_python /path/to/mindspore-env/bin/python \
--checkpoint_exporter_python /path/to/torch-env/bin/python \
--audit_python /path/to/base-env/bin/python最终审计命令:
python tools/audit_migration_acceptance.py \
--data_root ./local_data \
--torch_metrics ./migration_acceptance/torch/eval_scores.json \
--mindspore_metrics ./migration_acceptance/mindspore/eval_scores.json \
--torch_manifest ./migration_acceptance/torch/run_manifest.json \
--mindspore_manifest ./migration_acceptance/mindspore/run_manifest.json \
--conversion_report ./migration_acceptance/mindspore/converted_from_torch.report.json \
--min_conversion_match_ratio 0.95 \
--metric_tolerance 0.0 \
--report_json ./migration_acceptance/audit_report.json审计工具会检查:
- metadata 是否齐全
- 采样图像路径是否可解析
- PyTorch/MindSpore metrics 是否存在
- 两侧 manifest 是否同协议
- 初始化来源是否一致
- metrics 来源是否为训练后评估
- checkpoint 转换报告是否达标
- MindSpore 指标是否达到比较要求
如果 metadata 中 imgpath 是相对路径,使用:
--image_root /path/to/dataset-root数据加载器会尝试多个候选路径,并在失败时给出清晰错误。
优先检查:
- 是否安装
mindnlp - 是否能访问模型权重
- 云端缓存中是否已有 BioClinicalBERT / Swin 权重
- MindSpore、MindNLP、CANN/CUDA 版本是否匹配
正式训练前建议运行:
python tools/preflight_migration_run.py \
--check_mindspore \
--require_mindnlp \
--check_mindnlp_assets \
--data_root ./local_data \
--report_json ./migration_acceptance/preflight_mindspore_report.json通常优先检查:
local_data/sentence-label.csv是否存在- 训练 metadata 是否有
report列 - 是否包含 CheXpert 14 个标签列
imgpath是否可通过--image_root定位- 云端是否有真实图像文件和报告文件
作业仓库只应提交源码、配置和面向真实数据的说明文档,不应提交真实医学数据、临时 checkpoint、运行缓存、报告渲染中间文件、本机运行截图、合成/伪造数据产物,或只服务于个人机器临时验证的脚本。
已在 .gitignore 中排除:
local_data
synthetic_medclip/
checkpoints_ms*/
migration_acceptance*/
report_assets/
report_rendered_pages*/
report.docx
report.pdf
tools/verify_mindspore_runtime.py
*.ckpt
*.bin
本 README 中的训练和验收命令均面向授权真实数据及云端可复现实验,不包含合成数据生成、伪造数据构造或仅能在本机自证的运行流程。
- MedCLIP paper: https://arxiv.org/pdf/2210.10163.pdf
- Original MedCLIP repository: https://github.com/RyanWangZf/MedCLIP
- MindSpore install guide: https://www.mindspore.cn/install