Anatomic-kinetic fusion network for pituitary gland and microadenoma segmentation in multi-phase DCE-MRI 复现报告
1. 报告摘要
本报告围绕论文《Anatomic-kinetic fusion network for pituitary gland and microadenoma segmentation in multi-phase DCE-MRI》对应开源项目 AKF-Net,主要记录于 H200 服务器上的源码获取、环境适配、依赖安装、硬编码修复、合成数据构造、训练链路验证与推理链路验证全过程。
本次工作已经完成以下目标:
- 成功在 H200 服务器上部署 AKF-Net 运行环境
- 解决源码下载、依赖兼容、GPU 选择、显存冲突等实际工程问题
- 在无真实数据的前提下,自行构造 NIfTI 格式合成数据集
- 成功跑通训练、验证、checkpoint 保存、推理与指标计算全链路
- 得到可复现的训练日志与推理结果
注:本次结果属于工程级复现与冒烟测试,不等同于论文指标复现。由于缺少论文所使用的真实私有 DCE-MRI 数据集,因此当前结果不能用于证明论文性能结论,但可以证明该方法在目标硬件环境上具备可运行性与后续实验基础。
2. 项目背景
AKF-Net 是针对多期动态增强磁共振成像(DCE-MRI)中垂体及垂体微腺瘤分割任务提出的网络。项目仓库提供了训练脚本、测试脚本、模型结构和部分工具函数,但整体属于典型科研代码风格,并非可直接部署的工程化项目。
在实际部署前,代码中存在以下问题:
config.py 中写死了作者本地数据路径
main_train.py 和 main_test.py 中写死了 CUDA_VISIBLE_DEVICES
requirements.txt 中依赖版本较老
推理脚本使用了 matplotlib,但依赖文件中未声明
代码中存在 np.bool 等对新版本 numpy 不友好的写法
模型推理输出为 pkl,并非直接面向医学图像分析系统的 nii.gz
3. 复现目标
3.1 链路打通
成功获取源码
成功安装环境
成功在 H200 上启动训练
成功输出 checkpoint
成功运行推理与指标计算
3.2 后续正式实验准备
为未来接入真实 DCE-MRI 数据建立标准流程
给导师或后续成员提供可复用的部署依据
为真实数据上的论文复现、性能对比和改进实验打基础
4. 实验环境
4.1 硬件环境
GPU:NVIDIA H200
服务器环境:Linux
4.2 软件环境
本人最终采用的关键软件栈如下:
Python 3.10
PyTorch 2.4.1
torchvision 0.19.1
CUDA 12.4 对应 PyTorch 轮子
MONAI 1.3.1
SimpleITK 2.3.1
batchgenerators 0.25
numpy 1.23.5
scipy 1.13.1
scikit-learn 1.5.0
tensorboard 2.17.0
tqdm 4.66.4
matplotlib 3.8.4
说明:仓库原始依赖中写的是 torch==1.12.1,这一版本更适合 CUDA 11.x 时代环境,不适合作为 H200 上的部署方案,因此实际部署时采用了新版 PyTorch 。
5. 代码修复
5.1 去除硬编码
原始代码中:
main_train.py 写死使用某一块 GPU
main_test.py 也写死使用某一块 GPU
这在多人共享服务器上非常不方便,因此删除了这两处 CUDA_VISIBLE_DEVICES 硬编码,改为在命令行启动时指定 GPU,例如:
bash
CUDA_VISIBLE_DEVICES=1 python main_train.py
CUDA_VISIBLE_DEVICES=1 python main_test.py
5.2 处理缺失依赖
推理脚本实际使用了 matplotlib,但原始依赖文件中未包含,部署时已补装。
5.3 采用适合 H200 的 PyTorch 版本
为了兼容 H200 与较新的 CUDA 环境,未直接沿用仓库原始的 torch==1.12.1,而是采用了:
bash
pip install torch==2.4.1 torchvision==0.19.1 --index-url https://download.pytorch.org/whl/cu124
6. 无真实数据条件下的解决方案
由于当前无法获得论文使用的真实私有 DCE-MRI 数据集,且仓库主分支也未实际提供可直接运行的 dataset/sample_data,因此为了验证训练链路与推理链路,本人采用了"构造最小合成数据集"的方式进行冒烟测试。
目前如下:
验证代码是否能真正从输入走到输出
验证数据组织格式是否正确
验证模型能否完成前向传播、反向传播和参数更新
验证推理脚本、checkpoint 加载与指标计算是否可用
7. 合成数据的构造思路与生成步骤
7.1 数据组织格式
合成数据严格仿照 AKF-Net 源码要求组织为:
text
/home/akf_synth_data/
├── train.txt
├── test.txt
├── image/
│ ├── 001/
│ │ └── cor.nii.gz
│ ├── 002/
│ │ └── cor.nii.gz
│ ├── 003/
│ │ └── cor.nii.gz
│ └── 004/
│ └── cor.nii.gz
└── label/
├── 001.nii.gz
├── 002.nii.gz
├── 003.nii.gz
└── 004.nii.gz
其中:
001/002/003 作为训练样本
004 作为测试样本
7.2 数据形状设计
为了兼容源码处理流程,合成数据设计成:
图像张量形状:(7, 7, 320, 320)
标签张量形状:(7, 320, 320)
这里的含义是:7 个 DCE 相位、7 个切片、每张切片大小为 320 x 320
该设置与源码中的:
frame_num = 7
patch_size = [5, 128, 128]
crop_size = [128, 128]
能够较好兼容。
7.3 结构模拟方式
在每个切片中,人工构造了两个区域:
-
垂体区域
用一个较大的椭圆区域表示
标签值记为
1 -
微腺瘤区域
在垂体附近构造一个较小的椭圆区域
标签值记为
2
图像强度方面:
背景添加少量高斯噪声
垂体区域在各期增强中呈现中等增强
微腺瘤区域在多期中呈现更明显的强度变化
上述目的是尽量模拟"多期动态增强"的基本特征。
7.4 合成数据生成代码
核心生成脚本如下:
python
import os
import numpy as np
import SimpleITK as sitk
root = "/home/duanyx/akf_synth_data"
cases = ["001", "002", "003", "004"]
H, W = 320, 320
phases = 7
slices = 7
yy, xx = np.mgrid[0:H, 0:W]
for i, case in enumerate(cases):
img = np.zeros((phases, slices, H, W), dtype=np.float32)
lab = np.zeros((slices, H, W), dtype=np.uint8)
cx = 160 + (i - 1) * 6
cy = 160 - (i - 1) * 4
for z in range(slices):
gland = (((xx - cx) / (30 + z * 0.3)) ** 2 + ((yy - cy) / (26 + z * 0.2)) ** 2) <= 1.0
adenoma = (((xx - (cx + 8)) / 11) ** 2 + ((yy - (cy - 6)) / 9) ** 2) <= 1.0
lab[z][gland] = 1
lab[z][adenoma] = 2
base = np.random.normal(0.03, 0.01, size=(H, W)).astype(np.float32)
for p in range(phases):
phase_gain = 0.05 + 0.03 * p
img[p, z] = (
base
+ gland.astype(np.float32) * (0.18 + phase_gain)
+ adenoma.astype(np.float32) * (0.28 + 1.8 * phase_gain)
)
case_dir = os.path.join(root, "image", case)
os.makedirs(case_dir, exist_ok=True)
sitk.WriteImage(sitk.GetImageFromArray(img), os.path.join(case_dir, "dyn_cor.nii.gz"))
sitk.WriteImage(sitk.GetImageFromArray(lab), os.path.join(root, "label", f"{case}.nii.gz"))
with open(os.path.join(root, "train.txt"), "w") as f:
f.write("001\n002\n003\n")
with open(os.path.join(root, "test.txt"), "w") as f:
f.write("004\n")
8. 训练前配置调整
在冒烟测试阶段,为了尽快看到结果,对 config.py 做了小规模调整:
dataset_path 指向 /home/duanyx/akf_synth_data
batch_size 设为 1
n_epoch 设为 2
save_step 设为 1
这样设置的目的为快速验证训练逻辑、checkpoint 逻辑与验证逻辑。
9. 训练阶段结果展示
9.1 实际训练日志
训练在 H200 上完成了 2 个 epoch 的冒烟测试,核心日志如下:
text
Apr 03-19:41:04 LR epoch Loss DSC_BG DSC_MP DSC_MA
Apr 03-19:41:06 0.001000 0 1.13507 0.88262 0.33940 0.02335
Apr 03-19:41:11 0.001000 1 1.08119 0.98274 0.90721 0.00000
9.2 训练结果分析
训练流程成功执行完毕
验证阶段成功输出 Dice 指标
模型成功完成参数更新
checkpoint 保存逻辑能够触发
由于当前只训练了 2 个 epoch,且数据为人工构造的小规模合成数据,因此数值本身不具备医学意义,但其工程意义上训练链路是通的。
10. 推理阶段结果展示
10.1 推理日志
在训练完成后,将生成的最佳 checkpoint 写入 config.py 中,随后执行推理:
bash
CUDA_VISIBLE_DEVICES=1 python main_test.py
推理阶段的关键输出如下:
text
Apr 03-19:43:33 start load checkpoint: runs/Apr03_19-40-59_zhenglab-h200/best_checkpoint_1.pt
Apr 03-19:43:33 load checkpoints succeed!
Apr 03-19:43:34 0th/1 004 volume data:
DSC: 0.75572, 0.00000 ||
RVD: 0.29310, 0.99769 ||
Jaccard: 0.60736, 0.00000 ||
ASD: 1.16239, 10.36967 ||
HD95: 3.00000, 20.63977 ||
PRE: 0.91239, 0.00000 ||
REC: 0.64497, 0.00000
Apr 03-19:43:34 All test data:
DSC: 0.75572, 0.00000 ||
RVD: 0.29310, 0.99769 ||
Jaccard: 0.60736, 0.00000 ||
ASD: 1.16239, 10.36967 ||
HD95: 3.00000, 20.63977 ||
PRE: 0.91239, 0.00000 ||
REC: 0.64497, 0.00000
10.2 推理结果解读
上述结果说明:
checkpoint 可以被正确加载
模型推理过程执行成功
测试集遍历逻辑执行成功
指标计算函数(Dice、RVD、Jaccard、ASD、HD95、Precision、Recall)均可用
对于本次冒烟测试而言证明了:
- 训练输出不只是形式上存在,而是真能用于后续推理
- 模型从输入数据到评估结果的完整闭环已经建立
- 现有代码具备接入真实数据继续实验的基础
11. 实验评价
本次复现工作已经实现以下成果:
成功在 H200 环境中部署 AKF-Net
成功完成源码适配和依赖兼容
成功构造符合论文代码输入要求的合成 DCE-MRI 样例
成功跑通训练、验证、checkpoint 保存、推理和评估全链路
成功形成一套可重复的复现流程
12. 后续优化
如果后续能够获得真实 DCE-MRI 数据,优化工作如下:
- 将真实数据整理为 AKF-Net 要求的目录结构
- 恢复正式训练超参数,例如
n_epoch=800 - 在空闲 GPU 上运行完整训练
- 保存 checkpoint 并执行推理
- 统计论文中的核心指标
- 对比论文结果与本地结果差异
- 分析数据差异、预处理差异和训练设置差异
13. 结论
本次工作完成了 AKF-Net 在 H200 服务器上的工程级复现,验证了源码从数据输入、训练、验证、保存模型到推理评估的完整可运行性。在缺乏真实私有数据的情况下,通过人工构造多期 NIfTI 合成数据,成功实现了训练与推理闭环,证明该项目具备进一步开展真实数据实验的基础。