(二:2020.07.08)nnUNet方法解析(7.27更新认识)

医学图像深度学习分割方法的自动设计(二)(nnUNet /2020.04)《Automated Design of Deep Learning Methods for Biomedical Image Segmentation》


写在前面(更新于07.27,由于最近在对推理部分进行加速,更新的有点慢,今天添加一些最近的新理解。紫色字体为更新的认识)

1.本文是对该论文涉及的Methods进行解读和理解,参考上一篇的解读论文主体解读
2.红色是理解困难部分,正在进行结合附录、第一版nnunet论文、源码进行理解
3.绿色是提到附录的部分
4.橙色是本文关键字
5.蓝色是抛出的问题


Methods (该部分提到的设计规则可以在附录B中查看)


  • 1.“数据指纹”
    • ① 整个训练的第一步是将即将要训练的数据集的前景给抠出来(作者在这里说这个操作对于他们实验的数据来说没有影响,这可能是我在进行预处理时看到前后的图像尺寸没有变化的原因);
    • ② nnUNet根据这个得到的crop,来抓取它的相关参数和属性,来组成这个数据指纹,这些参数和属性包括:
      • Ⅰ. image_size: 每个空间维度上的体素的个数;
      • Ⅱ. image_spacing:每个体素的物理体积大小;
      • Ⅲ. 模态:头文件获取到的信息;
      • Ⅳ. 类别数:比如我是做单纯的二分类还多分类;
      • Ⅴ. 此外,还包括在所有训练案例上计算得到平均值、标准差以及属于任何标签的体素的强度值的99.5%和0.5%

  • 2.“管道指纹”
    • nnUNet将所有应该进行设计的参数缩减到必要的那几个,并且使用启发性规则对这些参数进行推理,该规则集成了很多行业内专业的知识,同时对上面提到的“数据指纹”和本地的硬件约束都能起到作用。
    • 这些得到的推理参数被两种参数所完善:
      • 第一种:蓝图参数,具有数据独立性,不同数据的该参数不同;
      • 第二种:经验参数,训练期间被优化

  • 3.“蓝图(计划)参数”
    • 一、结构模板
      • nnUNet配置的这几个不同的网络结构都来自于相同的网络模板,这个模板和原始的UNet及其3D版本十分的相近。我们的理论认为,一个配置完好的nnUNet仍然很难被打败,我们提出的网络架构没有使用任何最近十分流行的网络结构,只是进行了一点相对前者那种大刀阔斧的改动来说的多的改变。为了适应更大的patch_size,nnUNet把网络的batch_size设计的更小。事实上,大多数3D-Unet的batch_size都只有2(参见附录E.1a)。Batch_normalization是用来干什么的呢?BN是用来加速训练同时保持训练稳定的,小的batch_size往往无法体现BN的价值。针对这种情况,我们所有的nnUNet的架构都使用了instance_normalization。更进一步的,我们用Leaky_Relu代替Relu(负轴上斜率为0.01)
    • 二、深监督训练
      • 1.网络结构的一些改变:.除了解码阶段的最底下两层,我们给解码器的每一层都加了额外的损失,这样使得梯度信息能够更深层的注入网络,同时促进网络中所有层的训练。所有的Unet网络在同一个像素层次上,都用的一样的操作,无论时编码区还是在解码区(都是一个卷积 + 一个instance_normalization + Leaky_Relu)。下采样是一个具有步幅长度的卷积,上采样是一次卷积的转置操作。为了平衡训练效果和显存消耗,最初的feature_map的大小被设定为32,如果要做一次下采样那么这个大小缩小一半,如果做上采样则会变成原来的两倍。为了限制最终生成的模型的大小,feature_map的数量也被做了一定的限制,比如,3D_Unet被限制在320而2D_Unet被限制在512。
      • 2.训练时间表
        • Ⅰ.根据以往的一些经验,同时为了增加训练的时效性,我们用一轮大于 250的mini_batch,来把网络训练1000轮。随机梯度下降的方法采用μ = 0.99的nesterov的梯度下降,同时初始学习率为0.01.学习率的衰减遵循poly原则,即
          ( 1 e p o c h / e p o c h m a x ) 0.9 , (1-epoch/epoch_{max})^{0.9},
          设计的损失函数是(交叉熵损失和 + dice_loss)
          为了得到每一个深度监督的输出,它对应的每一次分割后mask的ground_truth都用来计算损失,训练的对象就是这每一层的损失的和:
          L = w 1 L 1 w 2 L 2 w 3 L 3 . . . , L=w_1*L_1|w_2*L_2|w_3*L_3|...,
          根据这种方式,在每一次分辨率降低(下采样)时权重减半,就会使得:
          w 2 = ( 1 / 2 ) w 1 ; w 3 = ( 1 / 4 ) w 1 , . . . w_2=(1/2)*w_1;w_3=(1/4)*w_1,...
          同时将这些权重归一化到和为1。
        • Ⅱ. mini_batch的样本都是从训练案例之中随机选择的,通过采用过采样的方式来控制样本不均衡的带来的稳定性问题:Oversampling is implemented to ensure robust handling of class imbalances: 66.7% of samples are from random locations within the selected training case while 33.3% of patches are guaranteed to contain one of the foreground classes that are present in the selected training sample (randomly selected ).The number of foreground patches is rounded with a forced minimum of 1 (resulting in 1 random and 1 foreground patch with batch size 2).
        • Ⅲ.在训练的运行过程中其实是用到了很多的数据增强的方法,详情参照附录D
          • ① 旋转
          • ② 缩放
          • ③ 高斯加噪
          • ④ 高斯模糊
          • ⑤ 亮度处理
          • ⑥ 对比度处理
          • 低分辨率仿真
          • Gamma(灰度系数)
      • 3.推理部分
        图像的推理预测是通过滑动窗口进行的,而窗口的大小等于训练时的patch_size,相邻的patch尺寸的预测(即滑动一次的两个块)具有一半的重叠比例。分割的准确率随着窗口边界的增大而降低。为了抑制拼接伪影,减少靠近边界位置的影响,采用高斯重要度加权,增加softmax聚合中中心体素的权重。通过沿所有轴进行镜像来增加测试时间

  • 4.“推理参数”
    • 1.色彩强度归一化
      nnUNet支持两种色彩强度归一化的方式:
      * ① 对于除了CT之外的其他所有模态的归一化方法是z-scoring:在训练和推理过程中,先对每幅图像分别进行减去他们的强度平均值,同时除以他们的标准差来进行归一化。If cropping resulted inan average size decrease of 25% or more, a mask for central non-zero voxels is created and the normalization is applied within that mask only, ignoring the surrounding zero voxels(如果裁剪导致平均尺寸减少25%或更多,则创建中心体素不是0的mask(mask的大小?),并只在该掩模内应用标准化,忽略周围的零体素)
      * ② 那么对于CT图的计算,就换用了另外一种方法:因为CT图的每一层各个像素的灰度值是一个定量并且反映的是该切片上的一些物理属性,因此这种有利于使用全局归一化的方式,来应用到所有的图片上面。To this end, nnU-Net uses the 0.5 and 99.5 percentiles of the foreground voxels for clipping as well as the global foreground mean a standard deviation for normalization on all images.

    • 2.重采样
             在一些数据集中,尤其是医学图像中,voxel_spacing(体素块间距)是一个非常重要的属性,而且这个属性通常是很多样的(有些厚有些薄)。但是我们卷积处理图像的时候是在处理一个数组或者tensor,是没有这个voxel_spacing的信息的,为了适应这种spacing很多样的特征,就需要用到一些插值算法,比如说三阶样条插值、线性插值、临近插值等。对于具备各向异性的图片(spacing最大的那个轴的spacing / spacing最小的那个轴的spacing 是大于3的)来说,平面内(x轴, y轴)的插值采用的是三阶样条插值,而平面外(z轴)的插值用的是最邻近插值。对z轴进行不同的插值方法会抑制重采样的伪影,比如如果voxel_spacing很大,那两个相邻切片的边缘的变化就通常很大。
             对于分割图像的重采样其实是通过将他们转换成独热编码。每一个通道都要用一次线性插值,然后再用argmax对分割图片进行恢复。再者,对于各项异性图片来说,是在低分辨率的那几层进行最邻近插值

      • 2.1 谈一下推理部分的重采样到底是如何进行的,结合第三篇的B.2的4
               以我自己训练的50套CT数据为例,这些CT原来的spacing有些一样,有些不一样。我将训练生成的plan.pkl文件进行了具体的查看,里面汇总了训练数据集所有的相关属性,包括他们的模态、尺寸、三个方向上的spacing等。我选取了一个尺寸为( 122, 512, 512),spacing为([3. , 0.64999998, 0.64999998])的数据进行推理测试。推理时,我将采样后的结果打印,为{‘spacing’: ([1.25 , 0.74121118, 0.74121118]), 'data.shape : ( 293, 449, 449)}。
               按照作者对该算法的描述,因为3 > 0.64x3,所以这个数据属于各向异性的数据,那么z轴的插值应当取排列后的10%的数。我对此进行了计算,50个数据中,spacing为1.25的有11个,其余都比1.25大,显然我的target_spacing就应该是1.25(作者诚不欺我)。而当我计算x轴和y轴上的target_spacing时,发现并不是10%的那个值,反而是中位数。说明一点,无论我待测的CT是各向同性还是各向异性的,x,y轴上的target_spacing应当是所有排列以后的中位数(median),而z轴的target_spacing则因性而异,各向同性则为中位数,各项异性则为10%的那个数。
               因为仍然怀疑正确性,我找了另一个各向同性的CT来进行测试。但是我发现,target_spacing仍然和上面一样,于是我检查代码,发现在推理的时候,target_spacing是从训练时生成的plan.pkl中读取的,也就是一个固定的值,无关异性还是同性。这个问题我会在github上做一个提问。
               让我做一下思考:
               ①我的推理结果和我的训练数据息息相关,假如我的训练数据的spacing都相等,那么我的推理数据也会以同样的spacing进行插值。
               ②我的待推理数据与他自身属性之间的关系,反而没有它和训练数据属性之间的关系大?无论你原来什么样子,你的spacing终究会和输进网络训练的那个东西的spacing一样。这是否意味着,训练集的质量相当重要?如果我的训练数据的源头一致,那么这个源头产生的测试集,也会具有更好的精准度?
               ③z轴越大插值时间越久,CT的原spacing越小需要插值的次数就越多。
    • 3.Target-Spacing(看上面部分)
             目标间距:选择的目标间距是一个关键参数。更大的间隔导致更小的图像,从而丢失细节,而更小的间隔导致更大的图像,阻止网络积累足够的上下文信息,因为patch的大小受到给定GPU内存预算的限制。虽然3D U-Net级联部分解决了这个问题,但仍然需要合理的目标间距来实现低分辨率和全分辨率。对于3D全分辨率U-Net, nnU-Net使用每个轴独立计算的训练用例中间隔的中值作为默认目标间距。对于各向异性数据集,这种默认会导致严重的插值伪影,或者由于训练数据在分辨率上的巨大差异而导致大量信息丢失。因此,当体素和间距各向异性(即最低间距轴与最高间距轴之比)均大于3时,在训练案例中,选择最低分辨率轴的目标间距为间距的第10个百分位。对于2D U-Net, nnU-Net通常在分辨率最高的两个轴上运行。如果三个轴都是各向同性的,则利用两个后向轴进行切片提取。目标间距是训练案例的中值间距(每个轴独立计算)。对于基于切片的处理,不需要沿面外轴重新采样。

    • 4.网络拓扑、patch_size、batch_size的自适应性

      • ① 寻找一个合适网络拓扑结构对于得到一个优秀的分割表现相当的重要。在一定的GPU显存的限制下,nnUNet优先选择一个大的patch_size,更大的patch_size会获取到更多的上下文的信息,这显然能提高模型的表现。但是,相对应的代价就是要减小batch_size(同时很大肯定占显存),而减小batch_size就会使反向传播的梯度下降变得不稳定(有时候学的好有时候学的坏,因为输入的不同batch的数据差距大)。为了提高训练的稳定性,我们提出一个值为2的mini_batch同时在网络训练时加入一个大的动量项(蓝图参数里有)。
      • ② 图像的spacing也被作为自适应的一部分去考虑:
        下采样的操作很可能只在某个特定的轴上进行操作,3D_Unet的卷积核可能对特定的平面进行操作(伪2D)。所有U-Net配置的网络拓扑都是根据重新采样后图像尺寸的中值以及重新采样到的目标间距来选择的。附录E.1有一个流程图展示了这个自适应的流程。接下来会探讨更多的网络结构模板的自适应的细节,通常都不会以昂贵的计算力为代价。因为GPU的内存消耗估计是基于feature_map的大小,而这个适应过程和feature_map的关系很小,所以不需要GPU参与这个进程。
    • 5.初始化
             patch_size被初始化成重采样以后的图像尺寸的中位数,如果这个patch_size不能被 2 n d 2^{n_d}(下采样的次数) 整除,那么将会对图像进行填充。

    • 6.拓扑结构

      • ① 网络结构通过确定每根轴上的下采样次数,而这个下采样的次数,又取决于patch_size的大小和voxel_spacing的大小。
      • ② 下采样会一直进行,除非上一个下采样会把feature_map的尺寸减小到4个体素以下,或者特征图的spacing是各向异性的。
      • ③ 下采样策略是被体素间隔(voxel_spacing)来确定的,high resolution axes are downsampled separately until their resolution is within factor 2 of the lower resolution axis(高分辨率轴分别向下采样,直到它们的分辨率在低分辨率轴的2倍之内?)【低分辨率是如何设计好的?】,随后所有的轴同时进行下采样。所有轴的下采样是分别中止的,分别终止于他们的特征图的尺寸达到某个它们各自的限制条件。
      • ④ 3D_Unet和2D_Unet默认的卷积核的大小分别是3x3x3和3x3。If there is an initial resolution discrepancy between axes (defined as a spacing ratio larger than 2), the kernel size for the out-of-plane axis is set to 1 until the resolutions are within a factor of 2. Note that the convolutional kernel size then remains at 3 for all axes. 【这里的轴到到底是什么意思?通道上也采样?卷积核为1尺寸不是不变化?】
    • 7.对GPU内存限制的自适应
             patch_size的大小是根据GPU 的大小尽可能大的进行设定的。由于在重新采样后,patch_size的大小被初始化为图像尺寸的中值大小,所以对于大多数数据集来说,patch_size最初太大了,无法适应GPU。nnU-Net根据网络feature_map的大小来估计给定架构的内存消耗,并将其与已知内存消耗的参考值进行比较。然后在迭代过程中减少patch_size的大小,同时在每个步骤中相应地更新架构配置,直到达到所需的预算(参见附录E.1)。缩小patch_size的大小总是应用在数据相对于图像中值形状的最大轴上。 The reduction in one step amounts to 2^(n_d) voxels of that axis, where nd is the number of downsampling operations.

    • 8.batch_size
             最后一步是配置batch_size。如果执行了减少patch_size大小的操作,则批大小设置为2。否则,剩余的GPU内存空间将会用来增加batch_size,直到GPU被充分利用为止。为了防止过拟合,对batch_size进行了限制,使mini_batch中的体素总数不超过所有训练案例体素总数的5%。附录C1&C2给出了生成U-Net架构的例子。

    • 9.3D_Unet_cascade是如何配置的

      • ① 在下采样数据上进行模型分割增大了与图像相关的patch_size,这样可以使网络获取更多的上下文信息,但这是以牺牲模型在一些细节或者纹理上的分割表现为代价的。假设有一个显存无穷大的GPU,那么最好的patch_size应当覆盖整个图像大小。

      • ② 3D_UNet_cascade是如何模拟patch_size无穷大这个过程:

        • Ⅰ 先用3D_Unet在下采样数据集上跑一个模型;
        • Ⅱ 再用一个全像素的3D_Unet来修正前者的分割效果;

        利用这种方法,低分辨率下采样层会获得更大的上下文信息,以此来生成它的分割输出,这个输出作为一个新的通道加入到下一个模块的输入中。

      • ③ 这个级联什么时候会被使用:

        • Ⅰ仅仅当3d_full_resolution的patch_size小于图像尺寸中值的12.5%使会使用级联,如果这个事件发生了,那么下采样数据的target_spacing和低分辨率部分的网络架构将会再一个迭代过程中被共同配置。
        • Ⅱ 这个迭代过程是这样的:初始化的target_spacing是全像素的target_spacing,为了让patch_size占据整个图的合适的一部分,在更新网络结构的过程中,逐渐每次增加1%的target_spacing,直到网络拓扑的patch_size超过目前图像尺寸中值的25%,如果目前的spacing是各向异性的( factor 2 difference between lowest and highest resolution axis【究竟医学图像的各向异性如何解释?】,那就只有更高分辨率的轴的spacing会被增大。
        • Ⅲ 第二个3D_Unet的配置和独立的3D_Unet的上面的配置是一样的,除了第一个UNet的上采样的分割图与它的输入是condatenated。附录E.1b就是这个优化过程的描述。

  • 5.“经验参数”
    • 推理模式
             nnUNet会在推理时根据训练集中的验证dice表现来自动选择配置——是选择单个推理方式还是选择一起推理方式。
             四种单个推理模式:2D、3D_full resolution、3Dliangl_lower resolution &the full resolution of the cascade。
             合作推理模式:四个模式中两两进行组合来实现合作推理。
             通过平均sofmax概率对模型进行综合。
    • 后处理
             Connected Components算法(连通分支算法)在医学图像领域非常常用,尤其是在器官分割中,经常用于去除最大的连接组件,从而来消除假阳性。nnU-Net同样用到这个方法,并自动对交叉验证中抑制较小组件的效果进行测试:首先所有的前景会被当做一个组件(多类别的1、2、3都被当做1),如果对除最大区域以外的所有分支的抑制提高了前景的平均dice而没有减小任何类别的dice,这一步将会被选择作为第一步的后处理步骤。最终,nnUNet会依靠这个步骤的表现来衡量要不要把相同的步骤用于不同的类别上。

猜你喜欢

转载自blog.csdn.net/weixin_42061636/article/details/107160735