Patch-Based 3D Unet for Head and Neck Tumor Segmentation with an Ensemble of Conventional and Dilate

Patch-Based 3D Unet for Head and Neck Tumor Segmentation with an Ensemble of Conventional and Dilated Convolutions
总结: 普通的3D Unet通过超参数(patch size、loss、convolution)的调整,创建了五个模型(也就是使用不同超参数的五个3D Unet),将总体训练数据集划分为训练集(121个病例)和验证集(80个病例),五个模型在训练集和验证集上进行训练,选择出效果最好的两个模型。这两个模型在整个训练数据集(201个病例)上训练,并用于最终的集成建模。(什么是集成建模?我自己理解的是,用这两个模型对测试数据集进行预测——采用滑动窗口法,然后将两个模型的预测概率求平均,对平均后的预测概率使用阈值处理得到最后的分割标签)。

Abstract

肿瘤消除问题的自动分割与医学图像中ROI区域的人工注释有关,例如重要的人工努力以及观察者内部的可变性。精确的头颈癌肿瘤分割对于癌症(尤其是口咽癌)的放射治疗计划有巨大的潜能,并且也可以提高病人护理。近期,深度学习模型的发展已经十分有效,并且在一些语义分割和医学图像分割中能精确地完成分割任务。在这篇文章中,我们提出了一个基于patch的深度学习模型来处理3D图像网络训练过程中的内存问题。 并且,使用了传统卷积和扩张卷积的组合来充分利用两种方法的优点:传统卷积的小感受野能够捕捉到更好的细节,而扩张卷积的大感受野能够捕捉到更好的全局信息。使用带有传统卷积和扩张卷积的基于patch的3D Unet能够产生不错的结果,最终的dice分数为0.6911。

Introduction

口咽癌是一种在口咽组织中形成恶性细胞或癌症细胞的疾病。口咽部由舌根、软腭、扁桃体、喉部侧壁和后壁组成,是头颈癌最常见的部位之一。从医学图像中准确地分割出头颈部肿瘤,可以在确定肿瘤确切位置的基础上,更好地制定放射治疗计划,优化患者护理。近年来,深度学习模型的发展已经能够有效和准确地执行医学图像分割任务,同时消除了与人工标注感兴趣区域(ROI)相关的问题,例如大量的人力和观察者之间的可变性。
为了比较和评估不同的自动分割算法,利用FDG-PET和头颈部原发肿瘤的CT扫描,组织了医学图像计算和计算机辅助干预(MICCAI)2020挑战赛。更具体地说,本次挑战中使用的数据集包括多机构临床获取的双峰扫描(FDG-PET和CT),重点是口咽癌。针对三维图像姿势记忆问题训练深度学习模型的问题,本研究采用基于patch的方法。此外,还对常规卷积网络和扩张卷积网络进行了集成。传统卷积较小的接受野可以捕捉到细微的细节,而扩张卷积的较大接受野可以捕捉到更好的全局信息,而集成方法则可以同时利用这两种方法。同样,与单个模型相比,集成建模技术也降低了泛化误差,有助于提高预测性能。

Methods

对于头颈癌肿瘤任务的自动分割,我们提出的方法的步骤为图像预处理,提取patch,训练多个模型(模型使用带有不同超参数的普通的3D UNet架构),充分利用每个模型进行预测,最终的模型评估和图像后处理。具体的细节在下面的不同部分进行描述。

Image Pre-processing

PET能够评估人体组织中细胞的新陈代谢活动,CT图像关注组织的形态特征。融合PET和CT两种模态的信息是图像预处理的主要任务之一。CT扫描用HU表示,因为我们的数据集中的CT扫描包括头颈区域,所以采用—1024HU到1024HU的窗口。每一个3D CT图像通过除以窗口范围值(2048?)来归一化到0-1。因为数据集提供了bounding box,每一个3D CT图像都使用病人信息中提供的bounding boxes坐标进行裁剪。为了进行裁剪,bounding boxes 坐标首先需要转换到他们对应的索引值。类似的,每一个3D PET图像也使用bounding boxes进行裁剪并且使用线性插值方法将图像大小重采样到对应的3D CT图像大小。然后,对于每一个subject,3D CT和3D PET在最后一个维度进行融合来使得输入图像有两个通道。因为PET图像没有标准的像素强度值,为了减少不同物体的影响,每一个3D图像都通过减去它们整体的平均值再除以整体像素强度值的标准差来进行归一化。

Patch Extraction

在3D Unet模型架构中,使用大输入尺寸或者整张图像会带来几个挑战。这些挑战中包含内存问题,训练时间长以及类别不平衡问题。因为中等的GPU内存大约是11GB或者12GB,所以网络需要大幅减少特征图或者层的数量来才能使模型适合GPU。有时,减少特征图或者层的数量会导致网络性能的下降。同样,训练时间也会大幅增加,因为有更多的体素参与每个步骤的梯度计算,并且在优化期间步数不可能成比例地减少。由于图像中含有肿瘤的部分通常占整个图像的比例相对较小,因此会出现类别不平衡的问题。因此,如果训练使用固定的损失函数,类别不平衡会导致模型关注非肿瘤体素,或者如果训练使用更偏向肿瘤体素的加权损失容易导致假阳性。因此,为了更有效地利用训练数据,基于patch的分割方法也会提供一个更自然的方式来进行数据增强,因为我们可以以不同的方式提取patch。在训练过程中patch size也是一个可以调整的超参数。然而更大的patch size可以从医学图像中提取更多的全局信息,但它也有内存问题和更长的训练时间。为了实现,在每一个epoch中以固定的概率从每一个subject中随机地提取patch。数据增强是在patch提取后进行随机左右翻转。使用随机左右翻转是因为头部和颈部区域沿左右方向在解剖学上是对称的。

Network Structure and Training

采用具有3个编码块和3个解码块的3D U-net网络结构,如图1所示。对于每个编码块,使用具有两个连续的3D卷积层的类VGG网络,核大小为3。紧随其后的是RELU激活函数。最后,使用batch normalization。在第一个编码块中使用了大量的特征图,以提高网络的表现力。为了防止过拟合,在最后一个编码块之后添加了0.5的dropout。损失函数采用加权交叉熵和Dice损失,其中值1.0用于非肿瘤体素,值2.0用于肿瘤体素。与传统的U-net结构类似,在每个编码块中,空间维度减少了一半,而特征数量增加了一倍。对于解码块,对称块与来自相应编码块的跳跃连接一起使用。将特征连接到反卷积输出,并将输入patch的分割图扩展到二分类(肿瘤和非肿瘤/背景)的ground truth 标签。
图1超参数调整用于模型选择,使用可调整的参数创建多个模型,可调整的模型参数有1)patch size 2)loss type 3)卷积的类型。在超参数调整过程中采用交叉验证,其中60%的训练数据用作训练集,其余40%用作验证集。虽然较大的patch可以显著增加训练时间,但也有可能显著提高模型的性能。同样,使用扩张卷积可以使网络具有更大的接受范围,并可能导致提取更好的全局信息。表1示出了用于训练五个不同模型的参数,其中N表示输入大小,Loss Type表示使用的损失函数,Convolution表示网络中使用的是常规卷积还是扩张卷积。在模型选择过程中,基于训练集和验证集,用Dice得分和loss值来评价各模型的性能。最终选择了两个性能最好的模型进行集成建模:采用常规卷积的模型(模型4)和采用扩张卷积的模型(模型5)。
表1
训练时间(包括训练两个用于部署的最终模型)约为每个模型11小时,训练在内存为11 GB的NVIDIA GeForce GTX 1080 Ti GPU上执行。使用TensorFlow框架创建和训练模型。每个模型使用600个epochs进行训练。Adam优化器以0.0005的恒定学习率使用。类似地,batch size为1并且layers为3。第一层使用的输入特征图数量为48个。在每个epoch的训练过程中,为每个受试者提取一个随机patch,其中受试者的顺序被随机排列(不太懂什么意思?)。最后,在测试过程中执行instance normalization,其中每个特征地图都使用其平均值和标准差进行归一化。

Prediction Using Each Model

正如前面部分所讨论的,使用较大的输入大小或整个图像会在训练期间带来内存问题的挑战,因此实现了基于patch的训练方法。在部署过程中也面临着同样的挑战,整个映像无法装入GPU内存。为了解决这个问题,使用滑动窗口的方法来获得每个测试对象的输出。然而,滑动窗口方法在没有重叠的情况下在整个图像上滑动窗口时会产生预测不稳定的问题。当重叠时,与没有重叠的相比,预测时间增加了8倍,因为它必须在体素的每个维度上重叠。在部署时,步长为4,并对输出概率进行平均(在部署时也就是在测试集上预测时?)对于每个窗口,都预测了原始图像和左右翻转的图像,并将翻转输入的输出再翻转后的平均概率用作输出。由于在使用每个模型进行预测之后执行集成建模,因此将每个模型的原始概率输出保存到磁盘,而不是将在对概率输出进行阈值处理之后产生的最终标签保存到磁盘。

Ensemble Modeling

与单个模型相比,集成方法往往具有更好的预测性能。因此,基于两个不同模型的预测,执行集成建模过程以产生最终的标签或二进制掩模。对所选的两个模型的原始概率图进行平均。通过将平均概率大于0.5的体素分类为肿瘤来获得最终预测。由于存在两个类别,0代表非肿瘤,1代表肿瘤,最终的分割产生了用于肿瘤分割的二值掩模。

Image Post-processing

最终提交前的最后一步是图像后处理。在后处理过程中,每个最终分割标签(二进制mask)在使用边界框坐标裁剪后,基于原始CT 3D图像,使用正确的像素间距和原点重新采样。像素间距和原点是用于重采样的主要组件,因为在图像预处理步骤中已经使用边界框对图像进行了裁剪。执行后处理是因为挑战中对提交的要求,其中输出需要使用原始的CT分辨率,并使用各自的边界框进行裁剪。

Results

最终模型的训练采用201例或受试者的全部训练数据集。在初步训练期间,训练数据集被分成121个训练对象和80个验证对象。训练数据由来自四个不同中心的医学图像(CT和FDG-PET扫描)组成。对于模型的选择,进行了超参数调整,并使用Dice得分和损失得分来评估不同模型的性能。基于表1中描述的5个模型,表2显示了在模型选择过程中使用的结果(训练Dice得分、训练损失和验证Dice得分)。
选择性能最好的两个模型,并在整个训练数据集上对其进行训练,并将其用于最终的集成建模。表2
根据它们的模型性能,选择模型4和模型5进行集成建模,集成后验证分割的Dice得分为0.7268。最后,对来自不同中心的53名受试者的测试数据进行分割。提交后,MICCAI 2020(HECKTOR)挑战赛组织者计算了测试集的平均Dice相似系数(DSC)、准确率和召回率,Dice为0.6911,查准率为0.7525,召回率为0.6928。

Discussion and Conclusions

本文提出了一种基于3D Unet集成的头颈部肿瘤自动分割方法。虽然分割算法是为头颈部肿瘤开发的,但有可能将知识转移到其他类型的肿瘤/癌症和其他类似的研究中。在预处理过程中融合FDG-PET和CT模式的信息,以实现准确的分割。在模型选择过程中,以不同的patch大小、损失类型和卷积类型作为超参数对5个模型进行训练。初步结果表明,patch大小越大,验证Dice得分越高,64x64x64的验证Dice得分为0.4588,64x96x96的验证Dice得分为0.7229。当Dice损失与交叉熵损失相加时,验证Dice得分从0.6647增加到0.7229,也显示出改善。同样,在交叉验证期间,与两个单独模型的性能相比,集成建模的性能更好。此外,在测试过程中,滑动窗口重叠的步长越大,交叉验证时的性能就越好。因此,在部署期间,在测试集中使用stride=4进行预测。
在模型选择过程中,由于计算时间的限制,只有5个模型进行了超参数调整训练。通过进一步的超参数调整,可以提高性能。选择性能最好的两个模型,在整个训练数据集上进行训练,并用于最终的集成建模(前面的五个模型在划分出的训练数据集和验证数据集上进行训练,训练后选择效果最好的两个模型,在整个训练数据集(201例病人)上进行训练,并用于最终的集成建模)。对两种方式(FDG-PET和CT)进行晚期融合的实验也可以表明,与早期融合相比,是否会对性能和/或训练时间产生显著影响。类似地,具有更多模型的集成建模也可以进一步提高性能。总之,我们开发了一种基于patch的3D UNET,用于头颈部肿瘤的分割,包括常规卷积和扩张卷积,以及两种模式(FDG-PET和CT)的早期融合。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
05-30
以下是一个简单的 3D Unet 模型的代码示例: ```python import tensorflow as tf from tensorflow.keras.layers import Input, Conv3D, MaxPooling3D, Dropout, concatenate, UpSampling3D def unet_3d(input_size=(128, 128, 128, 1)): inputs = Input(input_size) # 左边部分 conv1 = Conv3D(32, 3, activation='relu', padding='same', kernel_initializer='he_normal')(inputs) conv1 = Conv3D(32, 3, activation='relu', padding='same', kernel_initializer='he_normal')(conv1) pool1 = MaxPooling3D(pool_size=(2, 2, 2))(conv1) conv2 = Conv3D(64, 3, activation='relu', padding='same', kernel_initializer='he_normal')(pool1) conv2 = Conv3D(64, 3, activation='relu', padding='same', kernel_initializer='he_normal')(conv2) pool2 = MaxPooling3D(pool_size=(2, 2, 2))(conv2) conv3 = Conv3D(128, 3, activation='relu', padding='same', kernel_initializer='he_normal')(pool2) conv3 = Conv3D(128, 3, activation='relu', padding='same', kernel_initializer='he_normal')(conv3) pool3 = MaxPooling3D(pool_size=(2, 2, 2))(conv3) conv4 = Conv3D(256, 3, activation='relu', padding='same', kernel_initializer='he_normal')(pool3) conv4 = Conv3D(256, 3, activation='relu', padding='same', kernel_initializer='he_normal')(conv4) drop4 = Dropout(0.5)(conv4) pool4 = MaxPooling3D(pool_size=(2, 2, 2))(drop4) # 右边部分 conv5 = Conv3D(512, 3, activation='relu', padding='same', kernel_initializer='he_normal')(pool4) conv5 = Conv3D(512, 3, activation='relu', padding='same', kernel_initializer='he_normal')(conv5) drop5 = Dropout(0.5)(conv5) up6 = Conv3D(256, 2, activation='relu', padding='same', kernel_initializer='he_normal')(UpSampling3D(size=(2, 2, 2))(drop5)) merge6 = concatenate([drop4, up6], axis=4) conv6 = Conv3D(256, 3, activation='relu', padding='same', kernel_initializer='he_normal')(merge6) conv6 = Conv3D(256, 3, activation='relu', padding='same', kernel_initializer='he_normal')(conv6) up7 = Conv3D(128, 2, activation='relu', padding='same', kernel_initializer='he_normal')(UpSampling3D(size=(2, 2, 2))(conv6)) merge7 = concatenate([conv3, up7], axis=4) conv7 = Conv3D(128, 3, activation='relu', padding='same', kernel_initializer='he_normal')(merge7) conv7 = Conv3D(128, 3, activation='relu', padding='same', kernel_initializer='he_normal')(conv7) up8 = Conv3D(64, 2, activation='relu', padding='same', kernel_initializer='he_normal')(UpSampling3D(size=(2, 2, 2))(conv7)) merge8 = concatenate([conv2, up8], axis=4) conv8 = Conv3D(64, 3, activation='relu', padding='same', kernel_initializer='he_normal')(merge8) conv8 = Conv3D(64, 3, activation='relu', padding='same', kernel_initializer='he_normal')(conv8) up9 = Conv3D(32, 2, activation='relu', padding='same', kernel_initializer='he_normal')(UpSampling3D(size=(2, 2, 2))(conv8)) merge9 = concatenate([conv1, up9], axis=4) conv9 = Conv3D(32, 3, activation='relu', padding='same', kernel_initializer='he_normal')(merge9) conv9 = Conv3D(32, 3, activation='relu', padding='same', kernel_initializer='he_normal')(conv9) conv9 = Conv3D(2, 3, activation='relu', padding='same', kernel_initializer='he_normal')(conv9) # 输出 outputs = Conv3D(1, 1, activation='sigmoid')(conv9) model = tf.keras.Model(inputs=inputs, outputs=outputs) return model ``` 这是一个常见的 3D Unet 模型,与 2D Unet 模型类似,包括左边的下采样部分和右边的上采样部分。不同的是,在 3D Unet 中,我们使用了 3D 卷积层和 3D 池化层来逐渐减小特征图的大小,在上采样部分,我们使用了 3D 反卷积层和跳跃连接来逐渐增大特征图的大小,并将下采样部分相应的特征图与上采样部分的特征图进行拼接。最后,我们使用一个 3D 卷积层将 2 个通道的特征图转换为 1 个通道的输出。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值