edit_plans_files

本文档详细介绍了如何修改nnU-Net的计划文件以适应不同的实验需求。通过改变patch大小和batch size,作者展示了两种变体,并在任务120上进行训练,比较了结果。尽管改进的差异较小,但强调了调整计划文件作为优化nnU-Net性能的强大工具的重要性。此外,还提醒读者注意修改3D计划文件时的注意事项。
摘要由CSDN通过智能技术生成

Changing the plans files grants you a lot of flexibility: You can depart from nnU-Net’s default configuration and play
with different U-Net topologies, batch sizes and patch sizes. It is a powerful tool!
To better understand the components describing the network topology in our plans files, please read section 6.2
in the supplementary information
(page 13) of our paper!

The goal of this tutorial is to demonstrate how to read and modify plans files and how to use them in your
experiments. The file used here works with Task120 and requires you to have downloaded the dataset, run
nnunet.dataset_conversion.Task120_Massachusetts_RoadSegm.py and then run nnUNet_plan_and_preprocess for it.

Note that this task is 2D only, but the same principles we use here can be easily extended to 3D and other tasks as well.

The output of nnUNet_plan_and_preprocess for this task looks like this:

[{'batch_size': 2, 
'num_pool_per_axis': [8, 8], 
'patch_size': array([1280, 1024]), 
'median_patient_size_in_voxels': array([   1, 1500, 1500]), 
'current_spacing': array([999.,   1.,   1.]), 
'original_spacing': array([999.,   1.,   1.]), 
'pool_op_kernel_sizes': [[2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2]], 
'conv_kernel_sizes': [[3, 3], [3, 3], [3, 3], [3, 3], [3, 3], [3, 3], [3, 3], [3, 3], [3, 3]], 
'do_dummy_2D_data_aug': False}]

This is also essentially what is saved in the plans file under the key ‘plans_per_stage’

For this task, nnU-Net intends to use a patch size of 1280x1024 and a U-Net architecture with 8 pooling
operations per axis. Due to GPU memory constraints, the batch size is just 2.

Knowing the dataset we could hypothesize that a different approach might produce better results: The decision
of whether a pixel belongs to ‘road’ or not does not depend on the large contextual information that the large
patch size (and U-Net architecture) offer and could instead be made with more local information. Training with
a batch size of just 2 in a dataset with 800 training cases means that each batch contains only limited variability.
So one possible conclusion could be that smaller patches but larger patch sizes might result in a better
segmentation outcome. Let’s investigate (using the same GPU memory constraint, determined manually with trial
and error!):

Variant 1: patch size 512x512, batch size 12
The following snippet makes the necessary adaptations to the plans file

from batchgenerators.utilities.file_and_folder_operations import *
import numpy as np
from nnunet.paths import preprocessing_output_dir
task_name = 'Task120_MassRoadsSeg'

# if it breaks upon loading the plans file, make sure to run the Task120 dataset conversion and
# nnUNet_plan_and_preprocess first!
plans_fname = join(preprocessing_output_dir, task_name, 'nnUNetPlansv2.1_plans_2D.pkl')
plans = load_pickle(plans_fname)
plans['plans_per_stage'][0]['batch_size'] = 12
plans['plans_per_stage'][0]['patch_size'] = np.array((512, 512))
plans['plans_per_stage'][0]['num_pool_per_axis'] = [7, 7]
# because we changed the num_pool_per_axis, we need to change conv_kernel_sizes and pool_op_kernel_sizes as well!
plans['plans_per_stage'][0]['pool_op_kernel_sizes'] = [[2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2]]
plans['plans_per_stage'][0]['conv_kernel_sizes'] = [[3, 3], [3, 3], [3, 3], [3, 3], [3, 3], [3, 3], [3, 3], [3, 3]]
# for a network with num_pool_per_axis [7,7] the correct length of pool kernel sizes is 7 and the length of conv
# kernel sizes is 8! Note that you can also change these numbers if you believe it makes sense. A pool kernel size
# of 1 will result in no pooling along that axis, a kernel size of 3 will reduce the size of the feature map
# representations by factor 3 instead of 2.

# save the plans under a new plans name. Note that the new plans file must end with _plans_2D.pkl!
save_pickle(plans, join(preprocessing_output_dir, task_name, 'nnUNetPlansv2.1_ps512_bs12_plans_2D.pkl'))

Variant 2: patch size 256x256, batch size 60

from batchgenerators.utilities.file_and_folder_operations import *
import numpy as np
from nnunet.paths import preprocessing_output_dir
task_name = 'Task120_MassRoadsSeg'
plans_fname = join(preprocessing_output_dir, task_name, 'nnUNetPlansv2.1_plans_2D.pkl')
plans = load_pickle(plans_fname)
plans['plans_per_stage'][0]['batch_size'] = 60
plans['plans_per_stage'][0]['patch_size'] = np.array((256, 256))
plans['plans_per_stage'][0]['num_pool_per_axis'] = [6, 6]
plans['plans_per_stage'][0]['pool_op_kernel_sizes'] = [[2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2]]
plans['plans_per_stage'][0]['conv_kernel_sizes'] = [[3, 3], [3, 3], [3, 3], [3, 3], [3, 3], [3, 3], [3, 3]]
save_pickle(plans, join(preprocessing_output_dir, task_name, 'nnUNetPlansv2.1_ps256_bs60_plans_2D.pkl'))

You can now use these custom plans files to train the networks and compare the results! Remeber that all nnUNet_*
commands have the -h argument to display their arguments. nnUNet_train supports custom plans via the -p argument.
Custom plans must be the prefix, so here this is everything except ‘_plans_2D.pkl’:

Variant 1:

nnUNet_train 2d nnUNetTrainerV2 120 FOLD -p nnUNetPlansv2.1_ps512_bs12

Variant 2:

nnUNet_train 2d nnUNetTrainerV2 120 FOLD -p nnUNetPlansv2.1_ps256_bs60

Let all 5 folds run for each plans file (original and the two variants). To compare the results, you can make use of
nnUNet_determine_postprocessing to get the necessary metrics, for example:

nnUNet_determine_postprocessing -t 120 -tr nnUNetTrainerV2 -p nnUNetPlansv2.1_ps512_bs12 -m 2d

This will create a cv_niftis_raw and cv_niftis_postprocessed subfolder in the training output directory. In each
of these folders is a summary.json file that you can open with a regular text editor. In this file, there are metrics
for each training example in the dataset representing the outcome of the 5-fold cross-validation. At the very bottom
of the file, the metrics are aggregated through averaging (field “mean”) and this is what you should be using to
compare the experiments. I recommend using the non-postprocessed summary.json (located in cv_niftis_raw) for this
because determining the postprocessing may actually overfit to the training dataset. Here are the results I obtained:

Vanilla nnU-Net: 0.7720
Variant 1: 0.7724
Variant 2: 0.7734

The results are remarkable similar and I would not necessarily conclude that such a small improvement in Dice is a
significant outcome. Nonetheless it was worth a try 😃

Despite the results shown here I would like to emphasize that modifying the plans file can be an extremely powerful
tool to improve the performance of nnU-Net on some datasets. You never know until you try it.

ADDITIONAL INFORMATION (READ THIS!)

  • when working with 3d plans (‘nnUNetPlansv2.1_plans_3D.pkl’) the 3d_lowres and 3d_fullres stage will be encoded
    in the same plans file. If len(plans[‘plans_per_stage’]) == 2, then [0] is the 3d_lowres and [1] is the
    3d_fullres variant. If len(plans[‘plans_per_stage’]) == 1 then [0] will be 3d_fullres and 3d_cascade_fullres
    (they use the same plans).

  • ‘pool_op_kernel_sizes’ together with determines ‘patch_size’ determines the size of the feature map
    representations at the bottleneck. For Variant 1 & 2 presented here, the size of the feature map representation is

    print(plans['plans_per_stage'][0]['patch_size'] / np.prod(plans['plans_per_stage'][0]['pool_op_kernel_sizes'], 0))

    [4., 4.]

    If you see a non-integer number here, your model will crash! Make sure these are always integers!
    nnU-Net will never create smaller bottlenecks than 4!

  • do not change the ‘current_spacing’ in the plans file! This will not work properly. To change the target spacing,
    have a look at the custom spacing tutorial.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值