The monai.bundle module supports building Python-based workflows via structured configurations.
The main benefits are threefold:
- it provides good readability and usability by separating system parameter settings from the Python code.
- it describes workflow at a relatively high level and allows for different low-level implementations.
- learning paradigms at a higher level such as federated learning and AutoML can be decoupled from the component details.
Content:
Components as part of a workflow can be specified using JSON or YAML syntax, for example, a network architecture
definition could be stored in a demo_config.json file with the following content:
{
"demo_net": {
"_target_": "monai.networks.nets.BasicUNet",
"spatial_dims": 3,
"in_channels": 1,
"out_channels": 2,
"features": [16, 16, 32, 32, 64, 64]
}
}or alternatively, in YAML format (demo_config.yaml):
demo_net:
_target_: monai.networks.nets.BasicUNet
spatial_dims: 3
in_channels: 1
out_channels: 2
features: [16, 16, 32, 32, 64, 64]The configuration parser can instantiate the component as a Python object:
>>> from monai.bundle import ConfigParser
>>> config = ConfigParser()
>>> config.read_config("demo_config.json")
>>> net = config.get_parsed_content("demo_net", instantiate=True)
BasicUNet features: (16, 16, 32, 32, 64, 64).
>>> print(type(net))
<class 'monai.networks.nets.basic_unet.BasicUNet'>or additionally, tune the input parameters then instantiate the component:
>>> config["demo_net"]["features"] = [32, 32, 32, 64, 64, 64]
>>> net = config.get_parsed_content("demo_net", instantiate=True)
BasicUNet features: (32, 32, 32, 64, 64, 64).For more details on the ConfigParser API, please see monai.bundle.ConfigParser.
A few characters and keywords are interpreted beyond the plain texts, here are examples of the syntax:
"@preprocessing::transforms::keys"Description: @ character indicates a reference to another configuration value defined at preprocessing::transforms::keys.
where :: indicates a sub-structure of this configuration file. (# is a synonym for ::, preprocessing#transforms#keys
refers to the same object.)
"@preprocessing::1"Description: 1 is referencing as an integer, which is used to index (zero-based indexing) the preprocessing sub-structure.
Relative reference is supported by starting the reference with #. For example, @#A is to use A at the
same config structure level, and @##A refers to A at one level above.
"$print(42)"Description: $ is a special character to indicate evaluating print(42) at runtime.
"$[i for i in @datalist]"Description: Create a list at runtime using the values in datalist as input.
"$from torchvision.models import resnet18"Description: $ followed by an import statement is handled slightly differently from the
Python expressions. The imported module resnet18 will be available as a global variable
to the other configuration sections. This is to simplify the use of external modules in the configuration.
The config expressions may use @ to reference other config items. For example, in $lambda x: x + @a + @b,
@a and @b are references to other Python objects and are made available to the anonymous function
as 'globals'.
It's therefore possible to modify the Python objects within an expression, for example,
$lambda x: @my_list.pop() + x will pop the last element from @my_list and add it to x.
"%demo_config.json::demo_net::in_channels"Description: % character indicates a macro to replace the current configuration element with the texts at demo_net::in_channels in the
demo_config.json file. The replacement is done before instantiating or evaluating the components.
{
"demo_name":{
"_target_": "my.python.module.Class",
"args1": "string",
"args2": 42}
}Description: This dictionary defines an object with a reference name demo_name, with an instantiable type
specified at _target_ and with input arguments args1 and args2.
This dictionary will be instantiated as a Pytorch object at runtime.
_target_ is a required key by monai bundle syntax for the Python object name.
args1 and args2 should be compatible with the Python object to instantiate.
{
"component_name": {
"_target_": "my.module.Class",
"_desc_": "this is a customized class which also triggers 'cudnn_opt' reference",
"_requires_": "@cudnn_opt",
"_disabled_": "true",
"_mode_": "default"}
}Description: _requires_, _disabled_, _desc_, and _mode_ are optional keys.
_requires_specifies references (string starts with@) or Python expression that will be evaluated/instantiated before_target_object is instantiated. It is useful when the component does not explicitly depend on the other ConfigItems via its arguments, but requires the dependencies to be instantiated/evaluated beforehand._disabled_specifies a flag to indicate whether to skip the instantiation._desc_can be used for providing free text descriptions._mode_specifies the operating mode when the component is instantiated or the callable is called. it currently supports the following values:"default"(default) -- return the return value of_target_(**kwargs)"partial"-- return a partial function offunctools.partial(_target_, **kwargs)(this is often useful when some portion of the full set of arguments are supplied to the_target_, and the user wants to call it with additional arguments later)."debug"-- execute with debug prompt and return the return value ofpdb.runcall(_target_, **kwargs), see alsopdb.runcall.
In addition to the Pythonic APIs, a few command line interfaces (CLI) are provided to interact with the bundle. The primary usage is:
python -m monai.bundle COMMANDSwhere COMMANDS is one of the following: run, verify_metadata, ckpt_export, ...
(please see python -m monai.bundle --help for a list of available options).
The CLI supports flexible use cases, such as overriding configs at runtime and predefining arguments in a file.
To display a usage page for a command, for example run:
python -m monai.bundle run -- --helpThe support is provided by Python Fire, please
make sure the optional dependency is installed, for example,
using pip install monai[fire] or pip install fire.
Details on the CLI argument parsing is provided in the
Python Fire Guide.
- Both
YAMLandJSONare supported, but the advanced features of these formats are not supported. - Using meaningful names for the configuration elements can improve the readability.
- While it is possible to build complex configurations with the bundle syntax, simple structures with sparse uses of expressions or references are preferred.
- For
$import <module>in the configuration, please make sure there are instructions for the users to install the<module>if it is not a (optional) dependency of MONAI. - As
#,::, and$might be interpreted differently by theshellorCLItools, may need to add escape characters or quotes for them in the command line, like:"\$torch.device('cuda:1')","'train_part#trainer'". - For more details and examples, please see the tutorials.