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 COMMANDS
where 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 -- --help
The 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
YAML
andJSON
are 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 theshell
orCLI
tools, 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.