From e8f8b269b4b5da2faef73a3467138c55f45e0c70 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Mon, 25 Apr 2022 16:30:58 +0800 Subject: [PATCH 01/11] [DLMED] draft config Signed-off-by: Nic Ma --- .../spleen_segmentation/configs/train.json | 8 +- .../configs/train_multi_gpu.json | 260 ++++++++++++++++++ 2 files changed, 264 insertions(+), 4 deletions(-) create mode 100644 modules/bundles/spleen_segmentation/configs/train_multi_gpu.json diff --git a/modules/bundles/spleen_segmentation/configs/train.json b/modules/bundles/spleen_segmentation/configs/train.json index 22ff83c1a2..6ff95a227a 100644 --- a/modules/bundles/spleen_segmentation/configs/train.json +++ b/modules/bundles/spleen_segmentation/configs/train.json @@ -7,8 +7,8 @@ "determinism": "$monai.utils.set_determinism(seed=123)", "cudnn_opt": "$setattr(torch.backends.cudnn, 'benchmark', True)", "device": "$torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')", - "ckpt_dir": "/workspace/data/tutorials/modules/bundles/spleen_segmentation/models", - "dataset_dir": "/workspace/data/Task09_Spleen", + "ckpt_dir": "/workspace/data/medical/tutorials/modules/bundles/spleen_segmentation/models", + "dataset_dir": "/workspace/data/medical/Task09_Spleen", "images": "$list(sorted(glob.glob(@dataset_dir + '/imagesTr/*.nii.gz')))", "labels": "$list(sorted(glob.glob(@dataset_dir + '/labelsTr/*.nii.gz')))", "network_def": { @@ -94,7 +94,7 @@ "_target_": "DataLoader", "dataset": "@train#dataset", "batch_size": 2, - "shuffle": false, + "shuffle": true, "num_workers": 4 }, "inferer": { @@ -143,7 +143,7 @@ }, "trainer": { "_target_": "SupervisedTrainer", - "_requires_": ["@determinism", "@cudnn_opt"], + "_requires_": ["@ddp_init", "@determinism", "@cudnn_opt"], "max_epochs": 100, "device": "@device", "train_data_loader": "@train#dataloader", diff --git a/modules/bundles/spleen_segmentation/configs/train_multi_gpu.json b/modules/bundles/spleen_segmentation/configs/train_multi_gpu.json new file mode 100644 index 0000000000..86eabbafcb --- /dev/null +++ b/modules/bundles/spleen_segmentation/configs/train_multi_gpu.json @@ -0,0 +1,260 @@ +{ + "imports": [ + "$import glob", + "$import os", + "$import ignite", + "$import torch.distributed as dist" + ], + "ddp_init": "$dist.init_process_group(backend='nccl', init_method='env://')", + "determinism": "$monai.utils.set_determinism(seed=123)", + "cudnn_opt": "$setattr(torch.backends.cudnn, 'benchmark', True)", + "device": "$torch.device(f'cuda:{dist.get_rank()}')", + "set_device": "$torch.cuda.set_device(@device)", + "ckpt_dir": "/workspace/data/medical/tutorials/modules/bundles/spleen_segmentation/models", + "dataset_dir": "/workspace/data/medical/Task09_Spleen", + "images": "$list(sorted(glob.glob(@dataset_dir + '/imagesTr/*.nii.gz')))", + "labels": "$list(sorted(glob.glob(@dataset_dir + '/labelsTr/*.nii.gz')))", + "network_def": { + "_target_": "UNet", + "spatial_dims": 3, + "in_channels": 1, + "out_channels": 2, + "channels": [16, 32, 64, 128, 256], + "strides": [2, 2, 2, 2], + "num_res_units": 2, + "norm": "batch" + }, + "gpu_net": "$@network_def.to(@device)", + "loss": { + "_target_": "DiceCELoss", + "to_onehot_y": true, + "softmax": true, + "squared_pred": true, + "batch": true + }, + "optimizer": { + "_target_": "torch.optim.Adam", + "params": "$@gpu_net.parameters()", + "lr": 1e-4 + }, + "network": { + "_target_": "torch.nn.parallel.DistributedDataParallel", + "module": "@gpu_net", + "device_ids": ["@device"] + }, + "train": { + "preprocessing": { + "_target_": "Compose", + "transforms": [ + { + "_target_": "LoadImaged", + "keys": ["image", "label"] + }, + { + "_target_": "EnsureChannelFirstd", + "keys": ["image", "label"] + }, + { + "_target_": "Orientationd", + "keys": ["image", "label"], + "axcodes": "RAS" + }, + { + "_target_": "Spacingd", + "keys": ["image", "label"], + "pixdim": [1.5, 1.5, 2.0], + "mode": ["bilinear", "nearest"] + }, + { + "_target_": "ScaleIntensityRanged", + "keys": "image", + "a_min": -57, + "a_max": 164, + "b_min": 0, + "b_max": 1, + "clip": true + }, + { + "_target_": "RandCropByPosNegLabeld", + "keys": ["image", "label"], + "label_key": "label", + "spatial_size": [96, 96, 96], + "pos": 1, + "neg": 1, + "num_samples": 4, + "image_key": "image", + "image_threshold": 0 + }, + { + "_target_": "EnsureTyped", + "keys": ["image", "label"] + } + ] + }, + "dataset": { + "_target_": "CacheDataset", + "data": "$[{'image': i, 'label': l} for i, l in zip(@images[:-9], @labels[:-9])]", + "transform": "@train#preprocessing", + "cache_rate": 1.0, + "num_workers": 4 + }, + "sampler": { + "_target_": "DistributedSampler", + "dataset": "@train#dataset", + "even_divisible": true, + "shuffle": true + }, + "dataloader": { + "_target_": "DataLoader", + "dataset": "@train#dataset", + "sampler": "@train#sampler", + "batch_size": 2, + "shuffle": false, + "num_workers": 4 + }, + "inferer": { + "_target_": "SimpleInferer" + }, + "postprocessing": { + "_target_": "Compose", + "transforms": [ + { + "_target_": "Activationsd", + "keys": "pred", + "softmax": true + }, + { + "_target_": "AsDiscreted", + "keys": ["pred", "label"], + "argmax": [true, false], + "to_onehot": 2 + } + ] + }, + "handlers": [ + { + "_target_": "ValidationHandler", + "validator": "@validate#evaluator", + "epoch_level": true, + "interval": 5 + }, + { + "_target_": "StatsHandler", + "_disabled_": "$dist.get_rank() > 0", + "tag_name": "train_loss", + "output_transform": "$monai.handlers.from_engine(['loss'], first=True)" + }, + { + "_target_": "TensorBoardStatsHandler", + "_disabled_": "$dist.get_rank() > 0", + "log_dir": "eval", + "tag_name": "train_loss", + "output_transform": "$monai.handlers.from_engine(['loss'], first=True)" + } + ], + "key_metric": { + "train_accuracy": { + "_target_": "ignite.metrics.Accuracy", + "output_transform": "$monai.handlers.from_engine(['pred', 'label'])" + } + }, + "trainer": { + "_target_": "SupervisedTrainer", + "_requires_": ["@ddp_init", "@set_device", "@determinism", "@cudnn_opt"], + "max_epochs": 100, + "device": "@device", + "train_data_loader": "@train#dataloader", + "network": "@network", + "loss_function": "@loss", + "optimizer": "@optimizer", + "inferer": "@train#inferer", + "postprocessing": "@train#postprocessing", + "key_train_metric": "@train#key_metric", + "train_handlers": "@train#handlers", + "amp": true + } + }, + "validate": { + "preprocessing": { + "_target_": "Compose", + "transforms": [ + "%train#preprocessing#transforms#0", + "%train#preprocessing#transforms#1", + "%train#preprocessing#transforms#2", + "%train#preprocessing#transforms#3", + "%train#preprocessing#transforms#4", + "%train#preprocessing#transforms#6" + ] + }, + "dataset": { + "_target_": "CacheDataset", + "data": "$[{'image': i, 'label': l} for i, l in zip(@images[-9:], @labels[-9:])]", + "transform": "@validate#preprocessing", + "cache_rate": 1.0 + }, + "sampler": { + "_target_": "DistributedSampler", + "dataset": "@validate#dataset", + "even_divisible": false, + "shuffle": false + }, + "dataloader": { + "_target_": "DataLoader", + "dataset": "@validate#dataset", + "sampler": "@validate#sampler", + "batch_size": 1, + "shuffle": false, + "num_workers": 4 + }, + "inferer": { + "_target_": "SlidingWindowInferer", + "roi_size": [96, 96, 96], + "sw_batch_size": 4, + "overlap": 0.5 + }, + "postprocessing": "%train#postprocessing", + "handlers": [ + { + "_target_": "StatsHandler", + "iteration_log": false + }, + { + "_target_": "TensorBoardStatsHandler", + "log_dir": "eval", + "iteration_log": false + }, + { + "_target_": "CheckpointSaver", + "save_dir": "@ckpt_dir", + "save_dict": {"model": "@network"}, + "save_key_metric": true, + "key_metric_filename": "model.pt" + } + ], + "key_metric": { + "val_mean_dice": { + "_target_": "MeanDice", + "include_background": false, + "output_transform": "$monai.handlers.from_engine(['pred', 'label'])" + } + }, + "additional_metrics": { + "val_accuracy": { + "_target_": "ignite.metrics.Accuracy", + "output_transform": "$monai.handlers.from_engine(['pred', 'label'])" + } + }, + "evaluator": { + "_target_": "SupervisedEvaluator", + "device": "@device", + "val_data_loader": "@validate#dataloader", + "network": "@network", + "inferer": "@validate#inferer", + "postprocessing": "@validate#postprocessing", + "key_val_metric": "@validate#key_metric", + "additional_metrics": "@validate#additional_metrics", + "val_handlers": "$@validate#handlers if dist.get_rank() > 0 else None", + "amp": true + } + } +} From 43e9c9f2ed67981ca7c2ce9dd8fd95ab1477f7c2 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Tue, 26 Apr 2022 13:56:59 +0800 Subject: [PATCH 02/11] [DLMED] update for test Signed-off-by: Nic Ma --- .../spleen_segmentation/configs/train.json | 15 +++++++++------ .../configs/train_multi_gpu.json | 19 ++++++++++++------- .../spleen_segmentation/docs/README.md | 8 +++++++- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/modules/bundles/spleen_segmentation/configs/train.json b/modules/bundles/spleen_segmentation/configs/train.json index 6ff95a227a..6c74e45db1 100644 --- a/modules/bundles/spleen_segmentation/configs/train.json +++ b/modules/bundles/spleen_segmentation/configs/train.json @@ -4,13 +4,12 @@ "$import os", "$import ignite" ], - "determinism": "$monai.utils.set_determinism(seed=123)", - "cudnn_opt": "$setattr(torch.backends.cudnn, 'benchmark', True)", - "device": "$torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')", - "ckpt_dir": "/workspace/data/medical/tutorials/modules/bundles/spleen_segmentation/models", + "bundle_root": "/workspace/data/medical/tutorials/modules/bundles/spleen_segmentation", + "ckpt_dir": "$@bundle_root + '/models'", "dataset_dir": "/workspace/data/medical/Task09_Spleen", "images": "$list(sorted(glob.glob(@dataset_dir + '/imagesTr/*.nii.gz')))", "labels": "$list(sorted(glob.glob(@dataset_dir + '/labelsTr/*.nii.gz')))", + "device": "$torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')", "network_def": { "_target_": "UNet", "spatial_dims": 3, @@ -143,7 +142,6 @@ }, "trainer": { "_target_": "SupervisedTrainer", - "_requires_": ["@ddp_init", "@determinism", "@cudnn_opt"], "max_epochs": 100, "device": "@device", "train_data_loader": "@train#dataloader", @@ -232,5 +230,10 @@ "val_handlers": "@validate#handlers", "amp": true } - } + }, + "training": [ + "$monai.utils.set_determinism(seed=123)", + "$setattr(torch.backends.cudnn, 'benchmark', True)", + "$@train#trainer.run()" + ] } diff --git a/modules/bundles/spleen_segmentation/configs/train_multi_gpu.json b/modules/bundles/spleen_segmentation/configs/train_multi_gpu.json index 86eabbafcb..d383ffa30a 100644 --- a/modules/bundles/spleen_segmentation/configs/train_multi_gpu.json +++ b/modules/bundles/spleen_segmentation/configs/train_multi_gpu.json @@ -5,12 +5,9 @@ "$import ignite", "$import torch.distributed as dist" ], - "ddp_init": "$dist.init_process_group(backend='nccl', init_method='env://')", - "determinism": "$monai.utils.set_determinism(seed=123)", - "cudnn_opt": "$setattr(torch.backends.cudnn, 'benchmark', True)", "device": "$torch.device(f'cuda:{dist.get_rank()}')", - "set_device": "$torch.cuda.set_device(@device)", - "ckpt_dir": "/workspace/data/medical/tutorials/modules/bundles/spleen_segmentation/models", + "bundle_root": "/workspace/data/medical/tutorials/modules/bundles/spleen_segmentation", + "ckpt_dir": "$@bundle_root + '/models'", "dataset_dir": "/workspace/data/medical/Task09_Spleen", "images": "$list(sorted(glob.glob(@dataset_dir + '/imagesTr/*.nii.gz')))", "labels": "$list(sorted(glob.glob(@dataset_dir + '/labelsTr/*.nii.gz')))", @@ -160,7 +157,6 @@ }, "trainer": { "_target_": "SupervisedTrainer", - "_requires_": ["@ddp_init", "@set_device", "@determinism", "@cudnn_opt"], "max_epochs": 100, "device": "@device", "train_data_loader": "@train#dataloader", @@ -176,6 +172,7 @@ }, "validate": { "preprocessing": { + "_target_": "Compose", "transforms": [ "%train#preprocessing#transforms#0", @@ -256,5 +253,13 @@ "val_handlers": "$@validate#handlers if dist.get_rank() > 0 else None", "amp": true } - } + }, + "training": [ + "$dist.init_process_group(backend='nccl', init_method='env://')", + "$torch.cuda.set_device(@device)", + "$monai.utils.set_determinism(seed=123)", + "$setattr(torch.backends.cudnn, 'benchmark', True)", + "$@train#trainer.run()", + "$dist.destroy_process_group()" + ] } diff --git a/modules/bundles/spleen_segmentation/docs/README.md b/modules/bundles/spleen_segmentation/docs/README.md index 7c5ea77991..b6a92a020c 100644 --- a/modules/bundles/spleen_segmentation/docs/README.md +++ b/modules/bundles/spleen_segmentation/docs/README.md @@ -26,7 +26,13 @@ Mean Dice = 0.96 Execute training: ``` -python -m monai.bundle run "'train#trainer'" --meta_file configs/metadata.json --config_file configs/train.json --logging_file configs/logging.conf +python -m monai.bundle run training --meta_file configs/metadata.json --config_file configs/train.json --logging_file configs/logging.conf +``` + +Execute multi-GPU training: + +``` +torchrun --nproc_per_node=2 -m monai.bundle run training --meta_file configs/metadata.json --config_file configs/train_multi_gpu.json --logging_file configs/logging.conf ``` Execute inference: From 0b30d31c3a999bea51ec55ec9afb9080636bb323 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Wed, 27 Apr 2022 00:24:29 +0800 Subject: [PATCH 03/11] [DLMED] update based on enhancement Signed-off-by: Nic Ma --- .../spleen_segmentation/configs/inference.json | 13 ++++++++----- .../bundles/spleen_segmentation/configs/train.json | 4 ++-- .../configs/train_multi_gpu.json | 8 ++++---- modules/bundles/spleen_segmentation/docs/README.md | 4 ++-- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/modules/bundles/spleen_segmentation/configs/inference.json b/modules/bundles/spleen_segmentation/configs/inference.json index 12b9d67eb9..58f4aa078d 100644 --- a/modules/bundles/spleen_segmentation/configs/inference.json +++ b/modules/bundles/spleen_segmentation/configs/inference.json @@ -3,12 +3,12 @@ "$import glob", "$import os" ], - "cudnn_opt": "$setattr(torch.backends.cudnn, 'benchmark', True)", - "device": "$torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')", - "ckpt_path": "/workspace/data/tutorials/modules/bundles/spleen_segmentation/models/model.pt", + "bundle_root": "/workspace/data/tutorials/modules/bundles/spleen_segmentation", + "ckpt_path": "$@bundle_root + '/models/model.pt'", "download_ckpt": "$monai.apps.utils.download_url('https://huggingface.co/MONAI/example_spleen_segmentation/resolve/main/model.pt', @ckpt_path)", "dataset_dir": "/workspace/data/Task09_Spleen", "datalist": "$list(sorted(glob.glob(@dataset_dir + '/imagesTs/*.nii.gz')))", + "device": "$torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')", "network_def": { "_target_": "UNet", "spatial_dims": 3, @@ -120,7 +120,6 @@ ], "evaluator": { "_target_": "SupervisedEvaluator", - "_requires_": "@cudnn_opt", "device": "@device", "val_data_loader": "@dataloader", "network": "@network", @@ -128,5 +127,9 @@ "postprocessing": "@postprocessing", "val_handlers": "@handlers", "amp": true - } + }, + "evaluating": [ + "$setattr(torch.backends.cudnn, 'benchmark', True)", + "$@evaluator.run()" + ] } diff --git a/modules/bundles/spleen_segmentation/configs/train.json b/modules/bundles/spleen_segmentation/configs/train.json index 6c74e45db1..ff5e6cab67 100644 --- a/modules/bundles/spleen_segmentation/configs/train.json +++ b/modules/bundles/spleen_segmentation/configs/train.json @@ -4,9 +4,9 @@ "$import os", "$import ignite" ], - "bundle_root": "/workspace/data/medical/tutorials/modules/bundles/spleen_segmentation", + "bundle_root": "/workspace/data/tutorials/modules/bundles/spleen_segmentation", "ckpt_dir": "$@bundle_root + '/models'", - "dataset_dir": "/workspace/data/medical/Task09_Spleen", + "dataset_dir": "/workspace/data/Task09_Spleen", "images": "$list(sorted(glob.glob(@dataset_dir + '/imagesTr/*.nii.gz')))", "labels": "$list(sorted(glob.glob(@dataset_dir + '/labelsTr/*.nii.gz')))", "device": "$torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')", diff --git a/modules/bundles/spleen_segmentation/configs/train_multi_gpu.json b/modules/bundles/spleen_segmentation/configs/train_multi_gpu.json index d383ffa30a..e5592a4c45 100644 --- a/modules/bundles/spleen_segmentation/configs/train_multi_gpu.json +++ b/modules/bundles/spleen_segmentation/configs/train_multi_gpu.json @@ -5,12 +5,12 @@ "$import ignite", "$import torch.distributed as dist" ], - "device": "$torch.device(f'cuda:{dist.get_rank()}')", - "bundle_root": "/workspace/data/medical/tutorials/modules/bundles/spleen_segmentation", + "bundle_root": "/workspace/data/tutorials/modules/bundles/spleen_segmentation", "ckpt_dir": "$@bundle_root + '/models'", - "dataset_dir": "/workspace/data/medical/Task09_Spleen", + "dataset_dir": "/workspace/data/Task09_Spleen", "images": "$list(sorted(glob.glob(@dataset_dir + '/imagesTr/*.nii.gz')))", "labels": "$list(sorted(glob.glob(@dataset_dir + '/labelsTr/*.nii.gz')))", + "device": "$torch.device(f'cuda:{dist.get_rank()}')", "network_def": { "_target_": "UNet", "spatial_dims": 3, @@ -255,7 +255,7 @@ } }, "training": [ - "$dist.init_process_group(backend='nccl', init_method='env://')", + "$dist.init_process_group(backend='nccl')", "$torch.cuda.set_device(@device)", "$monai.utils.set_determinism(seed=123)", "$setattr(torch.backends.cudnn, 'benchmark', True)", diff --git a/modules/bundles/spleen_segmentation/docs/README.md b/modules/bundles/spleen_segmentation/docs/README.md index b6a92a020c..01b6c6d3be 100644 --- a/modules/bundles/spleen_segmentation/docs/README.md +++ b/modules/bundles/spleen_segmentation/docs/README.md @@ -32,13 +32,13 @@ python -m monai.bundle run training --meta_file configs/metadata.json --config_f Execute multi-GPU training: ``` -torchrun --nproc_per_node=2 -m monai.bundle run training --meta_file configs/metadata.json --config_file configs/train_multi_gpu.json --logging_file configs/logging.conf +torchrun --standalone --nnodes=1 --nproc_per_node=2 -m monai.bundle run training --meta_file configs/metadata.json --config_file configs/train_multi_gpu.json --logging_file configs/logging.conf ``` Execute inference: ``` -python -m monai.bundle run evaluator --meta_file configs/metadata.json --config_file configs/inference.json --logging_file configs/logging.conf +python -m monai.bundle run evaluating --meta_file configs/metadata.json --config_file configs/inference.json --logging_file configs/logging.conf ``` Verify the metadata format: From d80a4da45999ec55e3ed1bb04b34ad84be5762da Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Wed, 27 Apr 2022 00:34:37 +0800 Subject: [PATCH 04/11] [DLMED] update tutorial Signed-off-by: Nic Ma --- modules/bundles/get_started.ipynb | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/modules/bundles/get_started.ipynb b/modules/bundles/get_started.ipynb index 038161bc83..66c41e40f0 100644 --- a/modules/bundles/get_started.ipynb +++ b/modules/bundles/get_started.ipynb @@ -164,8 +164,6 @@ " \"$import os\",\n", " \"$import ignite\"\n", " ],\n", - " \"determinism\": \"$monai.utils.set_determinism(seed=123)\",\n", - " \"cudnn_opt\": \"$setattr(torch.backends.cudnn, 'benchmark', True)\",\n", " \"device\": \"$torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')\",\n", " \"ckpt_path\": \"/workspace/data/models/model.pt\",\n", " \"dataset_dir\": \"/workspace/data/Task09_Spleen\",\n", @@ -513,14 +511,29 @@ "\n", "There are several predefined scripts in MONAI bundle module to help execute `regular training`, `metadata verification base on schema`, `network input / output verification`, `export to TorchScript model`, etc.\n", "\n", - "Here we leverage the `run` script and specify the ID of trainer in the config." + "Here we leverage the `run` script and specify the ID of trainer in the config.\n", + "\n", + "Just define the entry point expressions in the config to execute in order, and specify the `runner_id` in CLI script." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```json\n", + "\"training\": [\n", + " \"$monai.utils.set_determinism(seed=123)\",\n", + " \"$setattr(torch.backends.cudnn, 'benchmark', True)\",\n", + " \"$@train#trainer.run()\"\n", + "]\n", + "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "`python -m monai.bundle run \"'train#trainer'\" --config_file configs/train.json`" + "`python -m monai.bundle run training --config_file configs/train.json`" ] }, { @@ -538,7 +551,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "`python -m monai.bundle run \"'train#trainer'\" --config_file configs/train.json --device \"\\$torch.device('cuda:1')\"`" + "`python -m monai.bundle run training --config_file configs/train.json --device \"\\$torch.device('cuda:1')\"`" ] }, { @@ -552,7 +565,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "`python -m monai.bundle run \"'train#trainer'\" --config_file configs/train.json --network \"%configs/test.json#network\"`" + "`python -m monai.bundle run training --config_file configs/train.json --network \"%configs/test.json#network\"`" ] }, { From a7e0ed1a48c4d8bf8d8c50d236583d8faedc26b3 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Wed, 27 Apr 2022 19:39:29 +0800 Subject: [PATCH 05/11] [DLMED] simplify to override Signed-off-by: Nic Ma --- .../configs/multi_gpu_train.json | 34 +++++++++++++++++++ .../configs/train_multi_gpu.json | 2 +- .../spleen_segmentation/docs/README.md | 4 +-- 3 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 modules/bundles/spleen_segmentation/configs/multi_gpu_train.json diff --git a/modules/bundles/spleen_segmentation/configs/multi_gpu_train.json b/modules/bundles/spleen_segmentation/configs/multi_gpu_train.json new file mode 100644 index 0000000000..cdde7fa038 --- /dev/null +++ b/modules/bundles/spleen_segmentation/configs/multi_gpu_train.json @@ -0,0 +1,34 @@ +{ + "device": "$torch.device(f'cuda:{dist.get_rank()}')", + "network": { + "_target_": "torch.nn.parallel.DistributedDataParallel", + "module": "$@network_def.to(@device)", + "device_ids": ["@device"] + }, + "train#sampler": { + "_target_": "DistributedSampler", + "dataset": "@train#dataset", + "even_divisible": true, + "shuffle": true + }, + "train#dataloader#sampler": "@train#sampler", + "train#dataloader#shuffle": false, + "train#trainer#train_handlers": "$@train#handlers[: 1 if dist.get_rank() > 0 else None]", + "validate#sampler": { + "_target_": "DistributedSampler", + "dataset": "@validate#dataset", + "even_divisible": false, + "shuffle": false + }, + "validate#dataloader#sampler": "@validate#sampler", + "validate#evaluator#val_handlers": "$None if dist.get_rank() > 0 else @validate#handlers", + "training": [ + "$import torch.distributed as dist", + "$dist.init_process_group(backend='nccl')", + "$torch.cuda.set_device(@device)", + "$monai.utils.set_determinism(seed=123)", + "$setattr(torch.backends.cudnn, 'benchmark', True)", + "$@train#trainer.run()", + "$dist.destroy_process_group()" + ] +} diff --git a/modules/bundles/spleen_segmentation/configs/train_multi_gpu.json b/modules/bundles/spleen_segmentation/configs/train_multi_gpu.json index e5592a4c45..3c24a8befb 100644 --- a/modules/bundles/spleen_segmentation/configs/train_multi_gpu.json +++ b/modules/bundles/spleen_segmentation/configs/train_multi_gpu.json @@ -250,7 +250,7 @@ "postprocessing": "@validate#postprocessing", "key_val_metric": "@validate#key_metric", "additional_metrics": "@validate#additional_metrics", - "val_handlers": "$@validate#handlers if dist.get_rank() > 0 else None", + "val_handlers": "$None if dist.get_rank() > 0 else @validate#handlers", "amp": true } }, diff --git a/modules/bundles/spleen_segmentation/docs/README.md b/modules/bundles/spleen_segmentation/docs/README.md index 01b6c6d3be..4eb794d3d7 100644 --- a/modules/bundles/spleen_segmentation/docs/README.md +++ b/modules/bundles/spleen_segmentation/docs/README.md @@ -29,10 +29,10 @@ Execute training: python -m monai.bundle run training --meta_file configs/metadata.json --config_file configs/train.json --logging_file configs/logging.conf ``` -Execute multi-GPU training: +Override the train config to execute multi-GPU training: ``` -torchrun --standalone --nnodes=1 --nproc_per_node=2 -m monai.bundle run training --meta_file configs/metadata.json --config_file configs/train_multi_gpu.json --logging_file configs/logging.conf +torchrun --standalone --nnodes=1 --nproc_per_node=2 -m monai.bundle run training --meta_file configs/metadata.json --config_file configs/train.json --logging_file configs/logging.conf --args_file configs/multi_gpu_train.json ``` Execute inference: From f9781b25f771fb8bebaf91275c6604ce3bbc0562 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Thu, 28 Apr 2022 10:56:40 +0800 Subject: [PATCH 06/11] [DLMED] update according to comments Signed-off-by: Nic Ma --- modules/bundles/spleen_segmentation/docs/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/bundles/spleen_segmentation/docs/README.md b/modules/bundles/spleen_segmentation/docs/README.md index 4eb794d3d7..34710531e0 100644 --- a/modules/bundles/spleen_segmentation/docs/README.md +++ b/modules/bundles/spleen_segmentation/docs/README.md @@ -29,10 +29,10 @@ Execute training: python -m monai.bundle run training --meta_file configs/metadata.json --config_file configs/train.json --logging_file configs/logging.conf ``` -Override the train config to execute multi-GPU training: +Override the `train` config to execute multi-GPU training: ``` -torchrun --standalone --nnodes=1 --nproc_per_node=2 -m monai.bundle run training --meta_file configs/metadata.json --config_file configs/train.json --logging_file configs/logging.conf --args_file configs/multi_gpu_train.json +torchrun --standalone --nnodes=1 --nproc_per_node=2 -m monai.bundle run training --meta_file configs/metadata.json --config_file "['configs/train.json','configs/multi_gpu_train.json']" --logging_file configs/logging.conf ``` Execute inference: From 7734d1aac3f3c1637365ef339eb06a8ac7e129fe Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Thu, 28 Apr 2022 11:00:12 +0800 Subject: [PATCH 07/11] [DLMED] remove test file Signed-off-by: Nic Ma --- .../configs/train_multi_gpu.json | 265 ------------------ 1 file changed, 265 deletions(-) delete mode 100644 modules/bundles/spleen_segmentation/configs/train_multi_gpu.json diff --git a/modules/bundles/spleen_segmentation/configs/train_multi_gpu.json b/modules/bundles/spleen_segmentation/configs/train_multi_gpu.json deleted file mode 100644 index 3c24a8befb..0000000000 --- a/modules/bundles/spleen_segmentation/configs/train_multi_gpu.json +++ /dev/null @@ -1,265 +0,0 @@ -{ - "imports": [ - "$import glob", - "$import os", - "$import ignite", - "$import torch.distributed as dist" - ], - "bundle_root": "/workspace/data/tutorials/modules/bundles/spleen_segmentation", - "ckpt_dir": "$@bundle_root + '/models'", - "dataset_dir": "/workspace/data/Task09_Spleen", - "images": "$list(sorted(glob.glob(@dataset_dir + '/imagesTr/*.nii.gz')))", - "labels": "$list(sorted(glob.glob(@dataset_dir + '/labelsTr/*.nii.gz')))", - "device": "$torch.device(f'cuda:{dist.get_rank()}')", - "network_def": { - "_target_": "UNet", - "spatial_dims": 3, - "in_channels": 1, - "out_channels": 2, - "channels": [16, 32, 64, 128, 256], - "strides": [2, 2, 2, 2], - "num_res_units": 2, - "norm": "batch" - }, - "gpu_net": "$@network_def.to(@device)", - "loss": { - "_target_": "DiceCELoss", - "to_onehot_y": true, - "softmax": true, - "squared_pred": true, - "batch": true - }, - "optimizer": { - "_target_": "torch.optim.Adam", - "params": "$@gpu_net.parameters()", - "lr": 1e-4 - }, - "network": { - "_target_": "torch.nn.parallel.DistributedDataParallel", - "module": "@gpu_net", - "device_ids": ["@device"] - }, - "train": { - "preprocessing": { - "_target_": "Compose", - "transforms": [ - { - "_target_": "LoadImaged", - "keys": ["image", "label"] - }, - { - "_target_": "EnsureChannelFirstd", - "keys": ["image", "label"] - }, - { - "_target_": "Orientationd", - "keys": ["image", "label"], - "axcodes": "RAS" - }, - { - "_target_": "Spacingd", - "keys": ["image", "label"], - "pixdim": [1.5, 1.5, 2.0], - "mode": ["bilinear", "nearest"] - }, - { - "_target_": "ScaleIntensityRanged", - "keys": "image", - "a_min": -57, - "a_max": 164, - "b_min": 0, - "b_max": 1, - "clip": true - }, - { - "_target_": "RandCropByPosNegLabeld", - "keys": ["image", "label"], - "label_key": "label", - "spatial_size": [96, 96, 96], - "pos": 1, - "neg": 1, - "num_samples": 4, - "image_key": "image", - "image_threshold": 0 - }, - { - "_target_": "EnsureTyped", - "keys": ["image", "label"] - } - ] - }, - "dataset": { - "_target_": "CacheDataset", - "data": "$[{'image': i, 'label': l} for i, l in zip(@images[:-9], @labels[:-9])]", - "transform": "@train#preprocessing", - "cache_rate": 1.0, - "num_workers": 4 - }, - "sampler": { - "_target_": "DistributedSampler", - "dataset": "@train#dataset", - "even_divisible": true, - "shuffle": true - }, - "dataloader": { - "_target_": "DataLoader", - "dataset": "@train#dataset", - "sampler": "@train#sampler", - "batch_size": 2, - "shuffle": false, - "num_workers": 4 - }, - "inferer": { - "_target_": "SimpleInferer" - }, - "postprocessing": { - "_target_": "Compose", - "transforms": [ - { - "_target_": "Activationsd", - "keys": "pred", - "softmax": true - }, - { - "_target_": "AsDiscreted", - "keys": ["pred", "label"], - "argmax": [true, false], - "to_onehot": 2 - } - ] - }, - "handlers": [ - { - "_target_": "ValidationHandler", - "validator": "@validate#evaluator", - "epoch_level": true, - "interval": 5 - }, - { - "_target_": "StatsHandler", - "_disabled_": "$dist.get_rank() > 0", - "tag_name": "train_loss", - "output_transform": "$monai.handlers.from_engine(['loss'], first=True)" - }, - { - "_target_": "TensorBoardStatsHandler", - "_disabled_": "$dist.get_rank() > 0", - "log_dir": "eval", - "tag_name": "train_loss", - "output_transform": "$monai.handlers.from_engine(['loss'], first=True)" - } - ], - "key_metric": { - "train_accuracy": { - "_target_": "ignite.metrics.Accuracy", - "output_transform": "$monai.handlers.from_engine(['pred', 'label'])" - } - }, - "trainer": { - "_target_": "SupervisedTrainer", - "max_epochs": 100, - "device": "@device", - "train_data_loader": "@train#dataloader", - "network": "@network", - "loss_function": "@loss", - "optimizer": "@optimizer", - "inferer": "@train#inferer", - "postprocessing": "@train#postprocessing", - "key_train_metric": "@train#key_metric", - "train_handlers": "@train#handlers", - "amp": true - } - }, - "validate": { - "preprocessing": { - - "_target_": "Compose", - "transforms": [ - "%train#preprocessing#transforms#0", - "%train#preprocessing#transforms#1", - "%train#preprocessing#transforms#2", - "%train#preprocessing#transforms#3", - "%train#preprocessing#transforms#4", - "%train#preprocessing#transforms#6" - ] - }, - "dataset": { - "_target_": "CacheDataset", - "data": "$[{'image': i, 'label': l} for i, l in zip(@images[-9:], @labels[-9:])]", - "transform": "@validate#preprocessing", - "cache_rate": 1.0 - }, - "sampler": { - "_target_": "DistributedSampler", - "dataset": "@validate#dataset", - "even_divisible": false, - "shuffle": false - }, - "dataloader": { - "_target_": "DataLoader", - "dataset": "@validate#dataset", - "sampler": "@validate#sampler", - "batch_size": 1, - "shuffle": false, - "num_workers": 4 - }, - "inferer": { - "_target_": "SlidingWindowInferer", - "roi_size": [96, 96, 96], - "sw_batch_size": 4, - "overlap": 0.5 - }, - "postprocessing": "%train#postprocessing", - "handlers": [ - { - "_target_": "StatsHandler", - "iteration_log": false - }, - { - "_target_": "TensorBoardStatsHandler", - "log_dir": "eval", - "iteration_log": false - }, - { - "_target_": "CheckpointSaver", - "save_dir": "@ckpt_dir", - "save_dict": {"model": "@network"}, - "save_key_metric": true, - "key_metric_filename": "model.pt" - } - ], - "key_metric": { - "val_mean_dice": { - "_target_": "MeanDice", - "include_background": false, - "output_transform": "$monai.handlers.from_engine(['pred', 'label'])" - } - }, - "additional_metrics": { - "val_accuracy": { - "_target_": "ignite.metrics.Accuracy", - "output_transform": "$monai.handlers.from_engine(['pred', 'label'])" - } - }, - "evaluator": { - "_target_": "SupervisedEvaluator", - "device": "@device", - "val_data_loader": "@validate#dataloader", - "network": "@network", - "inferer": "@validate#inferer", - "postprocessing": "@validate#postprocessing", - "key_val_metric": "@validate#key_metric", - "additional_metrics": "@validate#additional_metrics", - "val_handlers": "$None if dist.get_rank() > 0 else @validate#handlers", - "amp": true - } - }, - "training": [ - "$dist.init_process_group(backend='nccl')", - "$torch.cuda.set_device(@device)", - "$monai.utils.set_determinism(seed=123)", - "$setattr(torch.backends.cudnn, 'benchmark', True)", - "$@train#trainer.run()", - "$dist.destroy_process_group()" - ] -} From de93f474d8272aeab8d518438a6c5409f7612ed6 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Thu, 28 Apr 2022 19:26:55 +0800 Subject: [PATCH 08/11] [DLMED] add evaluation config Signed-off-by: Nic Ma --- .../spleen_segmentation/configs/evaluate.json | 58 +++++++++++++++++++ .../spleen_segmentation/configs/train.json | 5 +- .../spleen_segmentation/docs/README.md | 6 ++ 3 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 modules/bundles/spleen_segmentation/configs/evaluate.json diff --git a/modules/bundles/spleen_segmentation/configs/evaluate.json b/modules/bundles/spleen_segmentation/configs/evaluate.json new file mode 100644 index 0000000000..27c154196b --- /dev/null +++ b/modules/bundles/spleen_segmentation/configs/evaluate.json @@ -0,0 +1,58 @@ +{ + "validate#postprocessing":{ + "_target_": "Compose", + "transforms": [ + { + "_target_": "Activationsd", + "keys": "pred", + "softmax": true + }, + { + "_target_": "Invertd", + "keys": ["pred", "label"], + "transform": "@validate#preprocessing", + "orig_keys": "image", + "meta_key_postfix": "meta_dict", + "nearest_interp": [false, true], + "to_tensor": true + }, + { + "_target_": "AsDiscreted", + "keys": ["pred", "label"], + "argmax": [true, false], + "to_onehot": 2 + }, + { + "_target_": "SaveImaged", + "keys": "pred", + "meta_keys": "pred_meta_dict", + "output_dir": "@output_dir", + "resample": false, + "squeeze_end_dims": true + } + ] + }, + "validate#handlers": [ + { + "_target_": "CheckpointLoader", + "load_path": "$@ckpt_dir + '/model.pt'", + "load_dict": {"model": "@network"} + }, + { + "_target_": "StatsHandler", + "iteration_log": false + }, + { + "_target_": "MetricsSaver", + "save_dir": "@output_dir", + "metrics": ["val_mean_dice", "val_acc"], + "metric_details": ["val_mean_dice"], + "batch_transform": "$monai.handlers.from_engine(['image_meta_dict'])", + "summary_ops": "*" + } + ], + "evaluating": [ + "$setattr(torch.backends.cudnn, 'benchmark', True)", + "$@validate#evaluator.run()" + ] +} diff --git a/modules/bundles/spleen_segmentation/configs/train.json b/modules/bundles/spleen_segmentation/configs/train.json index ff5e6cab67..250c078c08 100644 --- a/modules/bundles/spleen_segmentation/configs/train.json +++ b/modules/bundles/spleen_segmentation/configs/train.json @@ -6,6 +6,7 @@ ], "bundle_root": "/workspace/data/tutorials/modules/bundles/spleen_segmentation", "ckpt_dir": "$@bundle_root + '/models'", + "output_dir": "$@bundle_root + '/eval'", "dataset_dir": "/workspace/data/Task09_Spleen", "images": "$list(sorted(glob.glob(@dataset_dir + '/imagesTr/*.nii.gz')))", "labels": "$list(sorted(glob.glob(@dataset_dir + '/labelsTr/*.nii.gz')))", @@ -129,7 +130,7 @@ }, { "_target_": "TensorBoardStatsHandler", - "log_dir": "eval", + "log_dir": "@output_dir", "tag_name": "train_loss", "output_transform": "$monai.handlers.from_engine(['loss'], first=True)" } @@ -194,7 +195,7 @@ }, { "_target_": "TensorBoardStatsHandler", - "log_dir": "eval", + "log_dir": "@output_dir", "iteration_log": false }, { diff --git a/modules/bundles/spleen_segmentation/docs/README.md b/modules/bundles/spleen_segmentation/docs/README.md index 34710531e0..f1aa6e52bd 100644 --- a/modules/bundles/spleen_segmentation/docs/README.md +++ b/modules/bundles/spleen_segmentation/docs/README.md @@ -35,6 +35,12 @@ Override the `train` config to execute multi-GPU training: torchrun --standalone --nnodes=1 --nproc_per_node=2 -m monai.bundle run training --meta_file configs/metadata.json --config_file "['configs/train.json','configs/multi_gpu_train.json']" --logging_file configs/logging.conf ``` +Override the `train` config to execute evaluation with the trained model: + +``` +python -m monai.bundle run evaluating --meta_file configs/metadata.json --config_file "['configs/train.json','configs/evaluate.json']" --logging_file configs/logging.conf +``` + Execute inference: ``` From 3c7a0a5c2fb5ffb3acc4bfb7db7b2fb9b972450c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 28 Apr 2022 11:27:28 +0000 Subject: [PATCH 09/11] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- modules/bundles/spleen_segmentation/configs/evaluate.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/bundles/spleen_segmentation/configs/evaluate.json b/modules/bundles/spleen_segmentation/configs/evaluate.json index 27c154196b..879c3f6060 100644 --- a/modules/bundles/spleen_segmentation/configs/evaluate.json +++ b/modules/bundles/spleen_segmentation/configs/evaluate.json @@ -30,7 +30,7 @@ "resample": false, "squeeze_end_dims": true } - ] + ] }, "validate#handlers": [ { @@ -50,7 +50,7 @@ "batch_transform": "$monai.handlers.from_engine(['image_meta_dict'])", "summary_ops": "*" } - ], + ], "evaluating": [ "$setattr(torch.backends.cudnn, 'benchmark', True)", "$@validate#evaluator.run()" From 69fd5087fb4a67d7ab4d875925d9cfbff00c8aa6 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Thu, 28 Apr 2022 19:39:12 +0800 Subject: [PATCH 10/11] [DLMED] simplify inference Signed-off-by: Nic Ma --- .../bundles/spleen_segmentation/configs/inference.json | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/modules/bundles/spleen_segmentation/configs/inference.json b/modules/bundles/spleen_segmentation/configs/inference.json index 58f4aa078d..215e5f7deb 100644 --- a/modules/bundles/spleen_segmentation/configs/inference.json +++ b/modules/bundles/spleen_segmentation/configs/inference.json @@ -4,8 +4,7 @@ "$import os" ], "bundle_root": "/workspace/data/tutorials/modules/bundles/spleen_segmentation", - "ckpt_path": "$@bundle_root + '/models/model.pt'", - "download_ckpt": "$monai.apps.utils.download_url('https://huggingface.co/MONAI/example_spleen_segmentation/resolve/main/model.pt', @ckpt_path)", + "output_dir": "$@bundle_root + '/eval'", "dataset_dir": "/workspace/data/Task09_Spleen", "datalist": "$list(sorted(glob.glob(@dataset_dir + '/imagesTs/*.nii.gz')))", "device": "$torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')", @@ -101,16 +100,14 @@ "_target_": "SaveImaged", "keys": "pred", "meta_keys": "pred_meta_dict", - "output_dir": "eval" + "output_dir": "@output_dir" } ] }, "handlers": [ { "_target_": "CheckpointLoader", - "_requires_": "@download_ckpt", - "_disabled_": "$not os.path.exists(@ckpt_path)", - "load_path": "@ckpt_path", + "load_path": "$@bundle_root + '/models/model.pt'", "load_dict": {"model": "@network"} }, { From 453aca99357f5e02f1b593871e94ed52a19fa5b0 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Thu, 28 Apr 2022 22:49:45 +0800 Subject: [PATCH 11/11] [DLMED] update according to comments Signed-off-by: Nic Ma --- modules/bundles/get_started.ipynb | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/modules/bundles/get_started.ipynb b/modules/bundles/get_started.ipynb index 66c41e40f0..c521052d6f 100644 --- a/modules/bundles/get_started.ipynb +++ b/modules/bundles/get_started.ipynb @@ -6,13 +6,13 @@ "source": [ "# Get started to MONAI bundle\n", "\n", - "MONAI bundle usually includes the stored weights of a model, TorchScript model, JSON files that include configs and metadata about the model, information for constructing training, inference, and post-processing transform sequences, plain-text description, legal information, and other data the model creator wishes to include.\n", + "A MONAI bundle usually includes the stored weights of a model, TorchScript model, JSON files which include configs and metadata about the model, information for constructing training, inference, and post-processing transform sequences, plain-text description, legal information, and other data the model creator wishes to include.\n", "\n", - "For more information about MONAI bundle description: https://docs.monai.io/en/latest/bundle_intro.html.\n", + "For more information about MONAI bundles read the description: https://docs.monai.io/en/latest/bundle_intro.html.\n", "\n", - "This notebook is step-by-step tutorial to help get started to develop a bundle package, which contains a config file to construct the training pipeline and also have a `metadata.json` file to define the metadata information.\n", + "This notebook is a step-by-step tutorial to help get started to develop a bundle package, which contains a config file to construct the training pipeline and also has a `metadata.json` file to define the metadata information.\n", "\n", - "This notebook mainly contains below sections:\n", + "This notebook mainly contains the below sections:\n", "- Define a training config with `JSON` or `YAML` format\n", "- Execute training based on bundle scripts and configs\n", "- Hybrid programming with config and python code\n", @@ -21,7 +21,6 @@ "- Instantiate a python object from a dictionary config with `_target_` indicating class or function name or module path.\n", "- Execute python expression from a string config with the `$` syntax.\n", "- Refer to other python object with the `@` syntax.\n", - "- Require other independent config items to execute or instantiate first with the `_requires_` syntax.\n", "- Macro text replacement with the `%` syntax to simplify the config content.\n", "- Leverage the `_disabled_` syntax to tune or debug different components.\n", "- Override config content at runtime.\n", @@ -144,13 +143,13 @@ "source": [ "## Define train config - Set imports and input / output environments\n", "\n", - "Now let's start to define the config file for a regular training task. MONAI bundle support both `JSON` and `YAML` format, here we use `JSON` as example.\n", + "Now let's start to define the config file for a regular training task. MONAI bundles support both `JSON` and `YAML` format, here we use `JSON` as the example.\n", "\n", "According to the predefined syntax of MONAI bundle, `$` indicates an expression to evaluate, `@` refers to another object in the config content. For more details about the syntax in bundle config, please check: https://docs.monai.io/en/latest/config_syntax.html.\n", "\n", - "Please note that MONAI bundle doesn't require any hard-code logic in the config, so users can define the config content in any structure.\n", + "Please note that a MONAI bundle doesn't require any hard-coded logic in the config, so users can define the config content in any structure.\n", "\n", - "For the first step, import `os` and `glob` to use in the expressions (start with `$`). Then define input / output environments and enable `cudnn.benchmark` for better performance." + "For the first step, import `os` and `glob` to use in the expressions (start with `$`), then define input / output environments and enable `cudnn.benchmark` for better performance." ] }, { @@ -323,7 +322,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The train and validation image file names are organized into a list of dictionaries." + "The train and validation image file names are organized into a list of dictionaries.\n", + "\n", + "Here we use `dataset` instance as 1 argument of `dataloader` by the `@` syntax, and please note that `\"#\"` in the reference id are interpreted as special characters to go one level further into the nested config structures. For example: `\"dataset\": \"@train#dataset\"`." ] }, { @@ -428,8 +429,6 @@ "\n", "Here we use MONAI engine `SupervisedTrainer` to execute a regular training.\n", "\n", - "`determinism` and `cudnn_opt` are not args of the trainer, but should execute them before training, so here mark them in the `_requires_` field.\n", - "\n", "If users have customized logic, then can put the logic in the `iteration_update` arg or implement their own `trainer` in python code and set `_target_` to the class directly." ] }, @@ -440,7 +439,6 @@ "```json\n", "\"trainer\": {\n", " \"_target_\": \"SupervisedTrainer\",\n", - " \"_requires_\": [\"@determinism\", \"@cudnn_opt\"],\n", " \"max_epochs\": 100,\n", " \"device\": \"@device\",\n", " \"train_data_loader\": \"@train#dataloader\",\n", @@ -497,7 +495,7 @@ "source": [ "## Define metadata information\n", "\n", - "Optinally, we can define a `metadata` file in the bundle, which contains the metadata information relating to the model, including what the shape and format of inputs and outputs are, what the meaning of the outputs are, what type of model is present, and other information. The structure is a dictionary containing a defined set of keys with additional user-specified keys.\n", + "We can define a `metadata` file in the bundle, which contains the metadata information relating to the model, including what the shape and format of inputs and outputs are, what the meaning of the outputs are, what type of model is present, and other information. The structure is a dictionary containing a defined set of keys with additional user-specified keys.\n", "\n", "A typical `metadata` example is available: \n", "https://github.com/Project-MONAI/tutorials/blob/master/modules/bundles/spleen_segmentation/configs/metadata.json" @@ -574,8 +572,9 @@ "source": [ "## Hybrid programming with config and python code\n", "\n", - "MONAI bundle is flexible to support customized logic, there are several ways to achieve that:\n", - "- If defining own components like transform, loss, trainer, etc. in a python file, just use its module path in `_target_`.\n", + "A MONAI bundle supports flexible customized logic, there are several ways to achieve this:\n", + "\n", + "- If defining own components like transform, loss, trainer, etc. in a python file, just use its module path in `_target_` within the config file.\n", "- Parse the config in your own python program and do lazy instantiation with customized logic.\n", "\n", "Here we show an example to parse the config in python code and execute the training."