简介:nnUnet 是面向医学图像分割任务的主流深度学习框架,但在 Windows 下部署需自行处理大量编译与依赖问题。压缩包面向 Windows 用户提供了可直接运行的 nnUnet 编译版本,已提前完成路径修正、依赖适配等兼容性调整,适合希望绕过环境配置、直接开展 CT/MRI 图像分割实验的研究者与开发者。包内共 3 个文件,含 2 个 zip 与 1 个 Python 脚本,整体仅 1.16MB;zip 覆盖 nnUnet 主项目及 apex 混合精度加速组件,Python 脚本负责生成 nnUnet 所需的 Json 数据配置文件,可辅助快速完成数据预处理与元信息设定,包括图像尺寸、模态标签等关键参数。已有 1222 人浏览学习。通过这份资源,用户可以免去源码编译与排障环节,在 Windows 上快速搭建分割环境,利用 GPU 混合精度加速训练,将更多精力投入到数据准备、模型调优与医学影像分析研究中。
1. nnU-Net 在 Windows 上的真实门槛:不是装不上,是跑不顺
nnU-Net 在医学影像分割里算事实标准,价值在于它的自配置设计:给定数据集,它自动决定重采样、归一化、U-Net 结构和训练时长,不用逐项调参。Windows 用户从 nnUnet_windows.rar 这种打包版入手时,最常见的卡点反而不是网络本身:环境装完训练一启动就报显存不足,或者预处理阶段路径读不出来。追根溯源,问题都出在 CUDA 匹配、路径长度和多进程模型这三处。下面按我平时排查的顺序,把环境、数据、训练预测和报错对照分别讲清楚,适合用 Windows 工作站做 MRI/CT 分割验证的人。
2. 环境准备三件套:Miniconda、CUDA 匹配和 nnU-Net 环境变量
解压 nnUnet_windows.rar 后,这类打包里通常只是一些 .bat 脚本和说明文档,真正的依赖仍然要从 PyPI 和 PyTorch 官方源拉。每台机器的显卡驱动、Python 版本都不一样,直接双击脚本的成功率很低。我拿到这类包只看说明,环境一律自己重建,原因在后面三个小节的坑里都能对上。
2.1 用 Miniconda 建独立环境,先治脚本闪退
Windows 上最典型的翻车现场:双击 start.bat 黑窗口一闪而过,什么都看不到,误以为包是坏的。闪退的真实原因多半是 PATH 里的 python 指向系统自带版本或 Microsoft Store 的别名,脚本里 import 的模块一个都没有,解释器直接退出。装 Miniconda(win 版)就是为了把解释器和依赖隔离出来:
conda create -n nnunet python=3.10 -y conda activate nnunet pip install nnunetv2网络慢的话先执行pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple再装。注意包名是nnunetv2,这是 v2 的 pip 包;v1 的包名是nnunet,安装后指令和环境变量完全不同。装错版本时最常见的症状是nnUNetv2_train命令找不到,然后误以为 PATH 没配好,实际是包就装错了。闪退脚本的诊断方式也统一:不要双击,改用 Anaconda Prompt 手动执行,报错才能留在屏幕上,这是排查一切 Windows 脚本问题的起点。
2.2 用 nvidia-smi 判断 CUDA 上限,再选 PyTorch 轮子
PyTorch 的 CPU 版很容易装,但跑不了训练,这个问题通常出在驱动匹配上。驱动下载页上的版本号(比如 472.12-desktop-win10-win11-64b)只代表安装包版本,机器实际状态要看 nvidia-smi:
nvidia-smi输出右上角有一行 CUDA Version,比如 11.4 或 12.4,这个数字才是驱动能支持的最大 CUDA 运行时版本。PyTorch 的安装轮子用 cu 前缀标注编译时的 CUDA 版本,原则是驱动支持上限大于等于轮子的 CUDA 版本即可,按这个表对照:
| nvidia-smi 显示 | PyTorch 轮子 | 说明 |
|---|---|---|
| CUDA 11.x | cu111 / cu113 / cu118 | 老卡优先 cu118 |
| CUDA 12.x | cu121 / cu124 | 新驱动直接 cu121 |
| 无输出 | 不装 nnU-Net | 先装 NVIDIA 驱动 |
对应安装命令:
pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118nvidia-smi 没有输出的情况,先去设备管理器确认显卡驱动是否加载,不要直接装 PyTorch,否则后面所有 CUDA 报错都会指向错误方向。也有人在 Windows 上尝试用 docker 容器固定环境,但 GPU 透传在 Windows 容器下依赖 NVIDIA Container Toolkit,支持并不完整,绕一圈还是本地 conda 环境最实际。
2.3 设置 nnUNet_raw 等三个环境变量并验证 torch
nnU-Net v2 用三个环境变量定位数据、预处理结果和训练结果,漏一个就会在预处理或训练阶段报找不到路径。cmd 和 PowerShell 写法不同:
set nnUNet_raw=D:\nnunet_data\nnUNet_raw set nnUNet_preprocessed=D:\nnunet_data\nnUNet_preprocessed set nnUNet_results=D:\nnunet_data\nnUNet_results$env:nnUNet_raw="D:\nnunet_data\nnUNet_raw" $env:nnUNet_preprocessed="D:\nnunet_data\nnUNet_preprocessed" $env:nnUNet_results="D:\nnunet_data\nnUNet_results"三个根目录建议都先手动建好,nnU-Net 只会补建内部的数据集子目录,家长目录不存在时直接报 FileNotFoundError。环境变量只在当前终端生效,关掉就没了,写一个 set_env.bat 每次跑任务前执行。如果你装了 Windows 子系统(WSL2),也可以把训练挪到 Ubuntu 里跑,数据放在 ext4 文件系统内,路径长度和 spawn 多进程问题基本消失;代价是 /mnt 共享目录读写慢,所以代码放 Windows 侧、数据放 WSL 内部比较合适。验证环境:
python -c "import torch; print(torch.__version__, torch.cuda.is_available())" nnUNetv2_plan_and_preprocess -h第一行输出里 torch.cuda.is_available() 为 True 说明 CUDA 链路通了;第二行能打印帮助说明指令在 PATH 里。出现 module not found 时用where python看解释器路径是否指向 conda 环境。
3. nnU-Net 数据整理与预处理:dataset.json 必填字段和 Windows 路径问题
nnU-Net 要求数据先转换成分层的目录结构,再由 plan_and_preprocess 统一做重采样和归一化。这个阶段在 Windows 上最容易翻车的是路径过长和并行进程数太高,跟算法本身没关系。
3.1 nnU-Net 数据集目录结构:Dataset001_MySeg 与 imagesTr/labelsTr
在 nnUNet_raw 下,每个数据集占一个一级目录,命名必须是 Dataset 加三位数字加下划线加名字,比如 Dataset001_MySeg,编号范围 001 到 999。内部固定放三个子目录和一份 dataset.json:
nnUNet_raw\Dataset001_MySeg\ ├─ imagesTr\ # 训练图像 xxx_0000.nii.gz ├─ labelsTr\ # 对应标签 xxx.nii.gz ├─ imagesTs\ # 测试图像,可先留空 └─ dataset.json图像和标签的文件名主体必须一致,比如 CT_001.nii.gz 对应 CT_001.nii.gz;多模态输入时按通道后缀区分,第一个通道是 _0000,第二个是 _0001。这里有两个 Windows 特有问题:一是项目根目录和文件名不要出现中文和空格,Windows 下 SimpleITK 对非 ASCII 路径的兼容性问题很多,统一放 D:\nnunet 这类纯英文路径能少一半故障;二是原始 DICOM 先用 dcm2niix 转成 .nii.gz 再进目录,v2 虽然能靠自定义 reader 读 DICOM,但在 Windows 上不值得为这个功能投入调试时间。
3.2 dataset.json 必填字段与 SimpleITKIO 读图设置
json 是 v2 的硬约束,labels 的键必须是字符串、值必须是 int,numTraining 必须和 labelsTr 里的实际文件数一致。网上很多示例是 v1 格式,直接拿过来会报字段错误,一份最小可用配置:
{ "name": "Dataset001_MySeg", "description": "windows validation run", "labels": { "background": 0, "tumor": 1 }, "numTraining": 50, "file_ending": ".nii.gz", "overwrite_image_reader_writer": "SimpleITKIO" }overwrite_image_reader_writer 建议显式写 SimpleITKIO。不写的话 nnU-Net 自动探测 reader,碰到扩展名被重命名过的文件,读图后端可能按内容猜格式失败,预处理阶段抛出的异常信息又跟实际原因对不上,排查很费时间。background 的 0 不能省,labels 的 value 一旦错乱,后面评估指标全部失效,DATASET json 里的 name 也要和目录名保持一致,不一致时 nnU-Net 会按编号找数据而不是按名字。
3.3 执行 plan_and_preprocess 并核对两份产物
plan 和预处理是同一条命令完成的:
nnUNetv2_plan_and_preprocess -d 1 -c 3d_fullres -npc 2-d 1 是 Dataset001 的编号;-c 3d_fullres 指只生成 full 分辨率配置;-npc 2 限制并行进程数。预处理包含前景裁剪、各向同性重采样、z-score 归一化,是典型的 CPU 密集任务。Windows 上默认进程数会按 CPU 核心数开,内存小的机器直接爆掉,8 核机器设 2 到 4 就够。跑完在 nnUNet_preprocessed\Dataset001_MySeg 下核对两份产物:
| 文件 | 内容 | 缺失时的处理 |
|---|---|---|
| nnUNetPlans.json | patch_size、batch_size、网络结构 | 说明 plan 阶段失败 |
| splits_final.json | 5 折划分的索引 | 预处理中断,重跑同一条命令 |
nnUNetPlans.json 是后面调显存的关键文件;splits_final.json 决定训练 fold 的数据划分。这个阶段会写大量小文件,Windows Defender 的实时扫描能把耗时拉长一半以上,把 nnUNet_preprocessed 目录加进排除项能明显提速。如果数据目录用 git 管理,先执行git config --system core.longpaths true,否则 clone 和 checkout 在超长路径上会报错,这一步在 Windows 上属于常规前置配置。
注意:只改 batch_size 不必重跑预处理;改 patch_size 必须重跑 plan_and_preprocess,序列是预处理、训练、推理,改完要按顺序走一遍。
4. nnU-Net 训练与推理实战:fold 参数、worker 数量和 batch_size 取舍
预处理通过之后,训练就是重复劳动,但 Windows 下必须额外管理线程和显存这两个变量。nnU-Net 默认跑 5 折交叉验证,每折最多 1000 轮加早停,单卡工作站全量跑完是按天计算的,建议先跑通一折再决定全量。
4.1 训练命令与 checkpoint:fold 用 0 起步,-w 0 保平安
nnUNetv2_train 1 3d_fullres 0 -w 0参数从左到右依次是数据集编号、配置名、fold 序号、DataLoader worker 数。fold 0 到 4 是交叉验证划分,all 表示用全部数据训练最终模型。Windows 上 DataLoader 走 spawn 模式,每个 worker 都要重新加载环境,开多了启动慢还容易触发系统权限问题,-w 0 牺牲一点加载速度换整体可靠性,单卡场景推荐。训练过程中的最佳模型自动落在:
nnUNet_results\Dataset001_MySeg\3d_fullres\fold_0\checkpoint_best.pth不需要手动保存。训练时加上 --npz 会保留 softmax 概率文件,之后做模型 ensemble 和计算 DSC 都需要,建议加上。启动后如果前几个 epoch 的 loss 不降反升,先别停,等 50 轮左右再下结论,nnU-Net 的 poly 学习率策略前期波动是正常的;直接报显存不足的,看 4.3。
4.2 推理命令:-f all 做 ensemble,-npp 控进程
单张图像或批量目录的推理:
nnUNetv2_predict -i .\input -o .\output -d 1 -c 3d_fullres -f all -npp 1-i 放待预测的 .nii.gz,文件名主体得和训练数据一致;-f all 用 5 折模型全部参与预测然后投票,比单折结果可靠得多;-npp 1 把读图预处理进程降为 1,避免 Windows 下多进程导出时互相踩文件。推理过程会先生成临时概率文件再转成分割掩膜,输出目录里出现同名 .nii.gz 和 summary.json 才算完成。常见问题是输入图像 shape 和训练时不一致,nnU-Net 会按 plan 里的重采样参数自动处理,但如果 spacing 信息丢失(比如从 numpy 直接保存的 nii),预处理会按默认值处理,结果精度明显下降,所以输入尽量用 dcm2niix 转换的原始文件。
4.3 改显存的三处配置:batch_size、worker 和 OMP 线程
nnU-Net v2 没有命令行层面的 batch size 参数,默认值写在预处理生成的 nnUNetPlans.json 里,找到:
configurations -> 3d_fullres -> batch_size显存不够时把它从 2 改成 1。注意 batch_size 是基础值,nnU-Net 在显存允许时用 cycle 训练法自动尝试翻倍,所以显存充足时不用手动调大;只有不足时才调小。worker 数量对应训练命令的 -w 和推理的 -npp,OMP 线程用环境变量限制:
set OMP_NUM_THREADS=4PyTorch 在 Windows 上默认把物理核全开,多任务机器上各进程争抢 CPU,epoch 耗时逐渐变长。判断方法:观察训练日志,如果每个 epoch 从 30 秒慢慢涨到 60 秒以上,把 OMP_NUM_THREADS 降到 4 到 6 后回落到正常范围,就是线程竞争。三个参数汇总:
| 调节位置 | 参数 | 建议初值 | 适用场景 |
|---|---|---|---|
| nnUNetPlans.json | batch_size | 2 改 1 | 显存不足 |
| 训练命令 | -w | 0 | Windows spawn 卡顿 |
| 推理命令 | -npp | 1 | 导出阶段进程冲突 |
| 环境变量 | OMP_NUM_THREADS | 4 | epoch 变慢、CPU 争抢 |
5. Windows 上的高频报错对照与 3d_lowres 快速验证技巧
5.1 按报错现象定位原因的三分钟对照
| 报错现场 | 实际原因 | 处理 |
|---|---|---|
| CUDA out of memory | batch_size 或输入过大 | 改 plans 的 batch_size,或换 3d_lowres |
| FileNotFoundError 带一长串预处理路径 | 环境变量没生效或路径超 260 字符 | 重开终端再 set,启用 LongPathsEnabled |
| 报 NCCL 相关错误 | Windows 上多卡训练缺 NCCL | 改单卡训练 |
| 双击 .bat 闪退 | PATH 里 python 不是 conda 环境 | 用 Anaconda Prompt 手动执行,加 pause |
长路径问题还可以在注册表里放开 Windows 的 260 字符限制:
reg add "HKLM\SYSTEM\CurrentControlSet\Control\FileSystem" /v LongPathsEnabled /t REG_DWORD /d 1 /f改完需要重启资源管理器或重启机器。注意 NCCL 报错不用尝试手动装 NCCL,Windows 上 nnU-Net 的多卡训练本来就是 Linux 优先,按 4.1 用单卡跑即可。
5.2 先用 3d_lowres 验证全链路,再回 fullres 全量训练
单卡上直接开 5 折 3d_fullres,往往跑了一天半才发现标签和图像错位。我拿到新数据第一件事是验证链路:同样的数据集,先生成 lowres 配置再训练单个 fold:
nnUNetv2_plan_and_preprocess -d 1 -c 3d_lowres -npc 2 nnUNetv2_train 1 3d_lowres 0 -w 0lowres 配置的 patch_size 更小,显存占用通常不到 fullres 的一半,单位 epoch 时间也短一个量级,把预处理、训练、推理、评估四个环节完整跑通,确认 loss 下降、分割结果和标签空间对齐,再删掉 lowres 的 results 目录回 fullres。验证通过后用 find_best_configuration 生成最终训练配置:
nnUNetv2_find_best_configuration -d 1 -c 3d_fullres -f 0输出的 JSON 里会给出各配置的交叉验证指标,按它的推荐跑 5 折全量并加 --npz,最后用 nnUNetv2_evaluate_folder 对预测目录和标签目录计算 DSC 与 HD95,以这两个指标决定是否进入调参迭代。
本文还有配套的精品资源,点击获取