一、写在前面

重要!!!
各位读者有时间请务必到我第十七篇博客查看更多的细节,包括如何使用nnUNet的残差网络、如何选择模型其中一个去训练等。更多的细节会慢慢更新,建议直接把那篇收藏了。


1.更新于8.02,添加“如何训练自己的数据集”部分。
2.更新于9.07,修改恶心的apex部分,新更新的torch1.6支持混合精度训练,即你不用再安装apex啦!!!
3.更新于9.09,修改五折交叉验证理解!以及在整理好训练的数据集以后如何自动化地生成对应的json文件。
3.更新于11.05,添加如何在Windows上使用nnUNet。windows的使用仍然面临很多问题,预处理是可以跑的,但是在推理或者训练的时候就会出现torch的一些环境和兼容问题,现在仍未解决,也不是目前的工作重心,有时间有能力的读者可以自己挖掘一下,非常的不好意思。
4.更新于21.04.20,解决windows平台无法使用nnUNet问题。

  • 1.笔者对nnUNet的使用也才一个多月,真正进入医疗影像领域也才三个月。对于nnUNet的理解肯定还停留在表层,希望大家在使用的时候能抱着一种纠错的态度,我会很感谢大家的指点!
  • 2.nnUNet是德国癌症研究中心的工程师编写的框架,迄今为止依旧在维护和更新,希望大家共勉,“抄”出自己的水平的同时,协助框架的维护,也是在帮助中国医疗行业(手动狗头)。
  • 3.此框架仅在Ubuntu18.04上进行过安装,win上需要键入参数运行,框架作者的建议也是在linux系统。作者建议不在conda的环境下,但我的框架在两个服务器三台主机上都未遇到什么conda的问题。1.5.1+cu10.1
  • 4.本篇博客的目的是为了让大家在迅速上手的同时更深入的研究,如此有魅力的框架,希望大家别玩玩就浪费,好好看看原论文及代码(作者代码中已经给出了相当详细的安装教程),或者我之前的博客(有很多错误的地方,但我一有时间就会更新理解,望海涵!)
  • 5.这个教程是在本地主机进行,服务器上的操作就是对服务器进行接下来的所有操作。教程不需要修改源码中的任何成分,我会在之后的博客中对源码如何调参做说明,刚接触的铁子们先完全按照步骤走。如果服务器是看不到图形界面的,需要用ssh进入服务器进行接下来的所有操作。
  • 有点啰嗦,开始吧!有问题请添加私人微信号JoeVaen3

二、nnUNet框架如何安装?

1. 你应该配置哪些环境?

  • ① anaconda + pytorch1.5.1 + cuda10.1:
           pytorch和anaconda的安装应该不用多说,这里着重说一下,安装torch时装上的cuda10.1为阉割版,会不利于我们接下来安装Apex,所以请安装完整版的,B乎的这个还可以cuda10.1安装
           当我后面想玩一下TensorRT的时候,发现TensorRT7不支持cuda10.1,所以有其他需求的,装cuda10.2也ok。
  • 因为支持新更新的nnunet使用了最近更新的
    pytorch1.6,所以可以使用混合精度训练而不必再使用APEX,这一步我删除了,安装变得更简单了,直接下一步。

    * ② 安装NVIDIA-Apex:
           这是英伟达的一个用于混合精度训练的插件,请不要直接pip,跟着下面的操作来:
           第一步:打开Apex所在项目网站,往下拉便可以看到QuickStart,已经很详细。
           第二步:在你用来安装环境的目录下打开终端,git clone https://github.com/NVIDIA/apex
           第三步:cd apex 进入你刚才下载下来的apex文件夹里面
           第四步:pip install -v --no-cache-dir --global-option="--cpp_ext" --global-option="--cuda_ext" ./【这步出现问题尝试使用 python setup.py install --cuda_ext --cpp_ext ,更多问题参考这里
           当你在安装好cuda的情况下完成这四步时,应该不会有问题,我用阉割版的cuda就会出现安装失败的问题。如果有问题请在下方评论反馈。
  • ② 安装hiddenlayer(用来生成什么网络拓扑图?管他呢,装吧)
    pip install --upgrade git+https://github.com/nanohanno/hiddenlayer.git@bugfix/get_trace_graph#egg=hiddenlayer(没有换行,这是一行代码)
  • ③ 安装心爱的nnUNet
           第一步:在home下创建nnUNetFrame文件夹,在这个文件夹内打开终端git clone https://github.com/MIC-DKFZ/nnUNet.git
           第二步:cd nnUNet
           第三步:pip install -e .(兄弟们和集美们别忘了加 . )
           当你安装完成这些以后,你的每一次对nnUNet的操作,都会在命令行里以nnUNet_开头,代表着你的nnUNet开始工作的指令。

2. 整理你的数据!

① nnUNet需要你把你要训练的数据做一个好好的整理,初学者请务必按照我的做法,等你熟练掌握以后再考虑新的姿势(有些文件夹的创建时多余的,但是你还是跟着我这样做最好):

       第一步:进入你之前创建的nnUNetFrame文件夹里面,创建一个名为DATASET的文件夹,现在你的nnUNetFrame文件夹下有两个文件夹,nnUNet是代码源,另一个DATASET就是我们接下来用来放数据的地方;
       第二步:进入创建好的DATASET文件夹下面,创建下面三个文件夹1
       第二个用来存放原始的你要训练的数据,第一个用来存放原始数据预处理之后的数据,第三个用来存放训练的结果。
       第三步:进入上面第二个文件夹nnUNet_raw,创建下面两个,右边为原始数据,左边为crop以后的数据。
在这里插入图片描述

       第四步:进入右边文件夹nnUNet_raw_data,创建一个名为Task08_HepaticVessel的文件夹(解释:这个Task08_HepaticVessel是nnUNet的作者参加的一个十项全能竞赛的子任务名,你可以对这个任务的数字ID进行任意的命名,比如你要分割心脏,你可以起名为Task01_Heart,比如你要分割肾脏,你可以起名为Task02_Kidney,前提是必须按照这种格式
       第五步:将下载好的公开数据集或者自己的数据集放在上面创建好的任务文件夹下,下面还以作者参加的Task08_HepaticVessel竞赛为例,解释下数据应该怎么存放和编辑:

  • A. 进入这个网站下载对应的数据集(<–网上学科议建<–),取代上面你自己创建的Task08_HepaticVessel文件夹。
  • B. 你会发现目录是这个样子的:json文件是对三个文件夹内容的字典呈现(关乎你的训练),imagesTr是你的训练数据集,打开后你会发现很多的有序的nii.gz的训练文件,而labelsTr里时对应这个imagesTr的标签文件,同样为nii.gz。目前只能是nii.gz文件,nii文件都不行。训练阶段的imageTs文件夹先不管,其实这个文件夹出现在任何位置都可以。(解释:nnUNet使用的是五折交叉验证,并没有验证集
    2

3.设置nnUNet读取文件的路径

       nnUNet是如何知道你的文件存放在哪儿呢,当然要在环境中创建一个路径,按照我的步骤,别做更改,因为到现在为止,你的路径和我的路径是一致的。
       第一步:在home目录下按ctrl + h,显示隐藏文件;
       第二步:找到.bashrc文件,打开(vim当然可以,但是毕竟教给我奶奶用的);
       第三步:在文档末尾添加下面三行,右上角保存文件,观察下面保存成功后关闭。

export nnUNet_raw_data_base="/home/qiao/nnUNetFrame/DATASET/nnUNet_raw"
export nnUNet_preprocessed="/home/qiao/nnUNetFrame/DATASET/nnUNet_preprocessed"
export RESULTS_FOLDER="/home/qiao/nnUNetFrame/DATASET/nnUNet_trained_models"

       第四步:在home下打开终端,输入source .bashrc来更新该文档。
       nnUNet已经知道怎么读取你的文件了。


三、在Task08_HepaticVessel上进行训练!

1. 转换一下你的数据集,让它可以被nnUNet识别

nnUNet_convert_decathlon_task -i /home/qiao/nnUNetFrame/DATASET/nnUNet_raw/nnUNet_raw_data/Task08_HepaticVessel
转换之后会发现,在这个Task08_HepaticVessel文件夹旁边多了一个Task008_HepaticVessel,对的,这说明框架已经安装成功了,之后的操作要在这个文件夹上进行。
让我们看一下这两个文件夹里面的训练文件有什么不同:
① Task08的imagesTr和labelsTr内:
在这里插入图片描述

② Task008的imagesTr和labelsTr内:
在这里插入图片描述
可以看出文件末尾多了_0000,是的,这就是你的数据格式是否正确的标志。不仅训练需要这个格式,之后你在推理的时候,也应当把你的文件名设置为这样,后面我会详细的说。
③ jason文件的解释:
json文件中包含着你的训练数据信息和任务信息:
在这里插入图片描述
尤其注意上图中的labels,里面有0 、1 、2三个标签,这是因为Task08的任务是分割出肝血管和肝血管瘤,三分类自然有三个标签。可以看到这个任务的训练集为303个,测试集为140个(用来进行模型训练好以后的推理测试,而不是验证!)自然,如果你需要做2分类,请自行去掉2这个标签,nnUNet会自动识别你应该做什么几分类。
建议将数据集都下下来进行观察,有些的模态也不一样。

2. 预处理

nnUNet_plan_and_preprocess -t 8
因为你的任务ID为8,所以参数t为8。这个过程会消耗很多的时间,速度慢的原因在于对要进行插值等各种操作。预处理要求你一定一定一定要在SSD【固态硬盘】上进行,Task08预处理后的数据会占据大约100多个g,请保证自己的SSD足够大,空间不够请自己筛选一部分的训练文件,不要200多套全拿来训练。

3.开始训练

nnUNet_train 3d_fullres nnUNetTrainerV2 8 4
8代表你的任务ID,4代表五折交叉验证中的第4折(0代表分成五折后的第一折)。所有的任务都应当在“4”的情况下,也就是五折交叉验证中的第一折数据集下进行。具体的参数和作用,我会在详谈训练的新博客中进行解释。迄今为止,我共用3d_fullres + nnUNetTrainerV2的方式训练了十个分割模型,除了本身在论文中表现就较差的模型外,大多数的分割效果都较为理想,请相信你手中的工具。
如果出现训练终端,你要继续训练的情况请在这行命令之后加上:
-c

4.简单说下配置

最少需要8g显存,一轮的时间很慢,在11g2080ti上时间一轮为550s,作者训练1000轮为一个实验结果,时间很慢,需要付出多一点耐心。

5.至于调参

在这个框架里,调参侠是没有尊严的,你引以为傲的各种trick,在这里并没有太大作用,这就是为什么我奶奶都能用的原因。你只需要这三行命令,然后等待1000轮结束,请在训练的时候翻翻我之前的博客,毫无疑问那才是nnUNet的魅力所在。

5.关于预训练模型

这里是预训练模型的下载地址,使用方法参见下一篇博客。


四、怎么在自己的训练集上训练?

8.02更新:
所有的步骤,都是在上面训练步骤的基础上展开的,我仍然建议您对上面的训练步骤做详细的理解:

  • 第一步:创建一个属于这个任务的文件夹,我们假设这个任务是要分割心脏,那么我们给这个任务赋予一个数字ID: 58(炮哥对不起),这个任务名就为Task58_Heart。在/home/你的主机用户名/nnUNetFrame/DATASET/nnUNet_raw下创建这个文件夹,并在其下添加如下三个文件夹,json文件的操作在下面解释:
    3

  • 第二步:整理你训练集数据和训练集标签:请整合为下图的格式并使数据和标签进行对应(heart代替pancreas,数据和标签名字均为如此)。
    2
    整合完成以后,训练集数据放在你刚刚创建的imagesTr文件夹下,训练集标签放在你刚刚创建的labelsTs文件夹下。imagesTs是我习惯存放测试集的位置(可以看下篇)。

  • 第三步:制作你的json文件,让训练器知道你要干些什么:
    笔者的做法有些笨,因为还没在源码中找到脚本,也没自己去写生成json的脚本,数据集少的情况下,可以这样做。batchgenerators.utilities.file_and_folder_operations里的save_json()函数可以生成对应你数据集的json文件

    • 首先,将原来Task08中的json文件拷贝到Task58中对应的位置,也就是上面那个图中的json文件;
    • 然后,打开文件进行修改并保存,json文件中是一个字典,也就是字典键值对应的你要修改成自己需要的形式,请参考我针对自己的Task03_TVessel任务进行的修改(上面有Task08的图):
      3
      两个地方是一定要注意的
             ① labels内的值:根据分类任务进行修改;
             ② training内文件名及其数目:训练集及标签的数目、文件名都要对应正确。
  • 第四步:将你的Task58转换成Task058,正如前面所说,nnUNet只认识得到这样文件夹和以_0000结尾的文件,执行命令
    nnUNet_convert_decathlon_task -i /home/你的主机用户名/nnUNetFrame/DATASET/nnUNet_raw/nnUNet_raw_data/Task58_Heart

  • 第五步:预处理文件,执行命令,等待预处理完成
    nnUNet_plan_and_preprocess -t 58

  • 第六步:开始训练。

    • 单卡训练:执行nnUNet_train 3d_fullres nnUNetTrainerV2 58 4
      注意:默认在第一块gpu(索引为0)上进行训练,如果想指定某个gpu,请先执行:
      export CUDA_VISIBLE_DEVICES=X,X为你指定的gpu索引。再执行上面的命令。
    • 多卡训练:比如我现在要在0和1两张卡上执行训练:
      • 先执行 export CUDA_VISIBLE_DEVICES=0,1
      • 再执行nnUNet_train_DP 3d_fullres nnUNetTrainerV2_DP 58 4 -gpus 2

    实验证明多卡训练速度和单卡训练速度的差别不大,只是为了减少每张卡的使用显存来弥补单卡显存不足的情况(这里感谢张同学的测试)。


五、怎么在Windows系统上使用nnUNet?

2021.4.20更新:
直接到这个项目,用上述同样方法在win上进行安装,无需再进行繁琐的多线程修正。

Logo

秉承“创新、开放、协作、共享”的开源价值观,致力于为大规模开源开放协同创新助力赋能,打造创新成果孵化和新时代开发者培养的开源创新生态!支持公有云使用、私有化部署以及软硬一体化私有部署。

更多推荐