Ubuntu下使用nnUNet 训练自己的数据集(只管实现,不讲原理,通俗易懂)

方便日后跑通nnUNet进行对比实验,写下本文。

本文只管如何在自己的数据集上跑通nnUNet,不讲解原理,因为我也是参考别人博文来做的,详情可参看Tina的四篇博文

一、什么是nnUNet?

nnU-Net是由德国癌症研究中心、海德堡大学以及海德堡大学医院研究人员(Fabian Isensee, Jens Petersen, Andre Klein)提出来的一个自适应任何新数据集的医学影像分割框架,该框架能根据给定数据集的属性自动调整所有超参数,整个过程无需人工干预。通过对数据的自适应处理,能在多个挑战赛中取得第一名,足以见得这个框架是有多么优秀。时至今日,nnUNet仍能凭借最为简单的U-Net结构在六个得到公认的分割挑战中实现了最先进的性能,在多个医学图像分割比赛中长期处于霸榜地位。

二、下载并配置nnUNet环境

1、下载,直接通过下面命令下载即可

pip install nnunet

下载好之后能看到根目录下多了一个文件夹,如下:

该目录下长这样的:

2、配置环境变量

在主目录中的.bashrc文件中设置路径,有部分朋友找不到该文件的可以在文件管理器里面按Ctrl + H 即可显示.bashrc文件。

随后直接对.bashrc文件进行编辑,在文件底部加入一下内容(有的在安装nnUNet时就自动生成了)

export nnUNet_raw_data_base="/home/gigabyte/nnUNetYV/DATASET/nnUNet_raw"
export nnUNet_preprocessed="/home/gigabyte/nnUNetYV/DATASET/nnUNet_preprocessed"
export RESULTS_FOLDER="/home/gigabyte/nnUNetYV/DATASET/nnUNet_trained_models"

之后nnUNet在运行是会自动找到这三个路径进行相关的读写操作。

三、将自己的数据集处理成nnUNet能识别的格式

1、文件夹结构安排

nnUNet需要结构化格式的数据集,并将原始数据存放在nnUNet_raw_data_base/nnUNet_raw_data文件夹下。其中,文件夹一定要命名为(“Task”“ID”_“任务名称”), “ID”是三位数的整, 任务名称可以是数据集的简写。

任务的文件夹名称如下,下面分别是5个分割任务:(引用自Tina)

再比如本人的分割任务: Task676_NPC,以’NPC’作为任务名称任务ID为676。

其中,每个文件(夹)的含义如下:

  • imagesTr: 训练图像。
  • imagesTs(可选,上图中我的就没有测试集): 测试图像
  • labelTr: 训练集标签。
  • dataset.json : 包含数据集的元数据, 如任务名字,模态,标签含义,训练集包含的图像地址

2、图像文件的命名要求

使用nnUNet时,对图像的名称是有要求的!图像和标签的名字具有一定的关联性,所有图像(包括标签)必须是3D nifti文件(.nii.gz)!

图像的统一命名格式case_identifier_XXXX.nii.gz, 标签的统一命名格式case_identifier.nii.gz

XXXX是模态标识符, 四位整数。

此命名方案将导致以下文件夹结构,必须严格将其数据转换为这种格式,参考Tina的博文如下:

 最后,附上本人任务(Task676_NPC)的文件夹示例:

 3、Json文件内容解读

一个合格的Json文件应该包含如下信息:

name: 数据集名字
dexcription: 对数据集的描述
modality: 模态,可以是CT或者MRI数据,nnU-Net会根据不同模态进行不同的预处理
labels: label中,不同的数值代表的类别
numTraining: 训练集数量
numTest: 测试集数量
training: 训练集的image 和 label 地址对
test: 只包含测试集的image. 这里跟Training不一样

引用自Tina的图片:

 本人任务(Task676_NPC)的数据集对应的Json文件如下:

 现在我们知道长什么样了,那么怎么把我们的数据准备成这个样子呢。最简单的方法就是copy别人的代码,在前人的基础上修改一下。如: dataset_conversion

—————————————————2022.09.04 更新开始————————————————

再次需要用nnUNet跑LiTS数据集,附上本人生成json文件的代码如下:

#    Copyright 2020 Division of Medical Image Computing, German Cancer Research Center (DKFZ), Heidelberg, Germany
from collections import OrderedDict

import json
import os

if __name__ == "__main__":

    train_dir = r"D:\Doctor_Li_Brest_Data\LITS17\LiTS_nnUNet_dataset\labelsTr"
    test_dir =r'D:\Doctor_Li_Brest_Data\LITS17\LiTS_nnUNet_dataset\imagesTs'
    output_folder = r"D:\Doctor_Li_Brest_Data\LITS17\LiTS_nnUNet_dataset"

    json_dict = OrderedDict()
    json_dict['name'] = "LiTS"
    json_dict['description'] = "LiTS"
    json_dict['tensorImageSize'] = "3D"
    json_dict['reference'] = "see challenge website"
    json_dict['licence'] = "see challenge website"
    json_dict['release'] = "0.0"
    json_dict['modality'] = {
        "0": "CT"
        # "0": "MR"
    }

    json_dict['labels'] = {
        "0": "background",
        # "1": "liver",
        "1": "tumor"
    }

    file_name_list = os.listdir(train_dir)
    file_id_list = []
    for name in file_name_list:
        file_id_list.append(name.split('.nii.gz')[0])

    file_name_list = os.listdir(test_dir)
    file_name_test_ids = []
    for name in file_name_list:
        file_name_test_ids.append(name.split('_')[0])


    json_dict['numTraining'] = len(file_id_list)
    json_dict['training'] = [{'image': "./imagesTr/%s.nii.gz" % i, "label": "./labelsTr/%s.nii.gz" % i} for i in file_id_list]
    json_dict['numTest'] = 0
    json_dict['test'] = []
    # json_dict['numTest'] = len(file_name_test_ids)  ##有测试集就解开注释
    # json_dict['test'] = ["./imagesTs/%s.nii.gz" % i for i in file_name_test_ids]  ##有测试集就解开注释

    with open(os.path.join(output_folder, "dataset.json"), 'w') as f:
        json.dump(json_dict, f, indent=4, sort_keys=True)

—————————————————2022.09.04 更新结束————————————————

至此,数据集配置完成。

四、nnUNet模型跑起来

1、nnUNet框架对数据进行自适应地预处理

首先,当然是激活nnUNet的环境啦!

conda activate nnUNet***environmental

使用命令: nnUNet_plan_and_preprocess

nnUNet_plan_and_preprocess -t XXX --verify_dataset_integrity

作用: 它会自动读取 数据集的属性,例如图像大小、体素间距、强度信息等。并转换成模型需要的格式。

XXX是与您的任务名称相关联的整数标识符TaskXXX_XXX(如本人的任务Task676_NPC, 就可以写676

即XXX是任务号码,如676.

–verify_dataset_integrity 对数据集执行一些检查以确保它与 nnU-Net 兼容。如果此检查已通过一次,则可以在以后的运行中省略。

 Task676_NPC任务预处理完成后的结果保存如下文件夹:

—————————————————2022.09.04 更新开始————————————————

LiTS的处理过程截图如下:

LiTS预处理后的结果保存如下:

 —————————————————2022.09.04 更新结束————————————————

2、模型训练

使用命令 nnUNet_train

该命令参数很多,可以使用nnUNet_train -h查看参数的含义

该命令的一般结构为:

nnUNet_train CONFIGURATION TRAINER_CLASS_NAME TASK_NAME_OR_ID FOLD (additional options)

CONFIGURATION: 模型架构,三种Unet: 2D U-Net, 3D U-Net and a U-Net Cascade(U-Net级联)。
TRAINER_CLASS_NAME: 使用的model trainer. 默认为nnUNetTrainerV2就可以
TASK_NAME_OR_ID: 任务全名TaskXXX_MYTASK或者是ID号,如Task676_NPC或676
FOLD: 第几折交叉验证,可选 [0, 1, 2, 3, 4],一共五折。

举例一: 2D U-Net 训练第三折

nnUNet_train 2d nnUNetTrainerV2 676 3

举例二: 3D full resolution U-Net 训练第二折

nnUNet_train 3d_fullres nnUNetTrainerV2 676 2

训练过程中,终端会输出以下信息:大致包括使用的模型,数据信息,损失函数,网络架构,每个epoch的输出。

每次训练都会获得一个自动生成的输出文件夹名称:

 其中,你想要查看的信息都在日志文件training_log文件中;

debug.json:包含用于训练此模型的蓝图和推断参数的摘要。不容易阅读,但对调试非常有用;
model_best.model / model_best.model.pkl:训练期间确定的最佳模型的检查点文件。
model_final_checkpoint.model / model_final_checkpoint.model.pkl:最终模型的检查点文件,用于验证和推理的内容。
progress.png:训练过程中的训练(蓝色)和验证(红色)损失图。还显示了评估指标的近似值(绿色)。这个近似值是前景类的平均 Dice 分数。

—————————————————2022.09.04 更新开始————————————————

五、修改训练的Epoch

由于nnUNet默认的epoch=1000,训练是在太久了,可用以下方式修改训练的epoch的默认值

1、在nnUNet的源码目录中找到nnUNetTrainerV2.py,该文件的位置如下:

2、直接将原来的self.max_num_epochs=1000 改为 自己想要的值,如改为23

部分细节没写到位,有疑问可以私信,尽量回复。

码字不易,有参考意义就给个赞呗,谢谢~~

  • 22
    点赞
  • 111
    收藏
    觉得还不错? 一键收藏
  • 28
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 28
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值