MONAI Bundle 配置#
monai.bundle 模块支持通过结构化配置构建基于 Python 的工作流。
主要有三大优势:
通过将系统参数设置与 Python 代码分离,提供了良好的可读性和易用性。
以相对高层级描述工作流,并允许使用不同的底层实现。
联邦学习和 AutoML 等高层级学习范式可以与组件细节解耦。
目录
基础示例#
作为工作流一部分的组件可以使用 JSON 或 YAML 语法指定,例如,网络架构定义可以存储在包含以下内容的 demo_config.json 文件中:
{
"demo_net": {
"_target_": "monai.networks.nets.BasicUNet",
"spatial_dims": 3,
"in_channels": 1,
"out_channels": 2,
"features": [16, 16, 32, 32, 64, 64]
}
}
或者使用 YAML 格式(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]
配置解析器可以将组件实例化为 Python 对象:
>>> 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'>
或者额外调整输入参数后再实例化组件:
>>> 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).
有关 ConfigParser API 的更多详细信息,请参阅 monai.bundle.ConfigParser。
语法示例详解#
除了普通文本外,还有一些字符和关键字会被特殊解释,以下是语法示例:
在配置中引用 Python 对象#
"@preprocessing::transforms::keys"
描述: @ 字符表示引用 preprocessing::transforms::keys 中定义的另一个配置值。其中 :: 表示该配置文件的子结构。(# 是 :: 的同义词,preprocessing#transforms#keys 指向同一个对象。)
"@preprocessing::1"
描述: 1 被视为整数引用,用于索引(从零开始)preprocessing 子结构。
通过以 # 开头的引用支持相对引用。例如,@#A 表示使用同一配置结构层级下的 A,而 @##A 指向上方一级层级中的 A。
评估为 Python 表达式#
"$print(42)"
描述: $ 是一个特殊字符,表示在运行时执行 print(42)。
"$[i for i in @datalist]"
描述: 使用 datalist 中的值作为输入,在运行时创建一个列表。
"$from torchvision.models import resnet18"
描述: $ 后跟 import 语句的处理方式与普通 Python 表达式略有不同。导入的模块 resnet18 将作为全局变量提供给其他配置部分。这是为了简化在配置中使用外部模块。
配置表达式可以使用 @ 来引用其他配置项。例如,在 $lambda x: x + @a + @b 中,@a 和 @b 是对其他 Python 对象的引用,并作为“全局变量”提供给匿名函数。因此,可以在表达式中修改 Python 对象,例如 $lambda x: @my_list.pop() + x 将从 @my_list 中弹出最后一个元素并将其加到 x 上。
文本替换配置元素#
"%demo_config.json::demo_net::in_channels"
描述: % 字符表示一个宏,用于将当前配置元素替换为 demo_config.json 文件中 demo_net::in_channels 的文本。替换发生在实例化或评估组件之前。
实例化 Python 对象#
{
"demo_name":{
"_target_": "my.python.module.Class",
"args1": "string",
"args2": 42}
}
描述: 该字典定义了一个引用名称为 demo_name 的对象,其可实例化类型在 _target_ 中指定,并带有输入参数 args1 和 args2。该字典将在运行时被实例化为 Pytorch 对象。
_target_ 是 MONAI Bundle 语法中指定 Python 对象名称的必要键。args1 和 args2 应与要实例化的 Python 对象兼容。
{
"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"}
}
描述: _requires_, _disabled_, _desc_ 和 _mode_ 是可选键。
_requires_指定在实例化_target_对象之前需要评估/实例化的引用(以@开头的字符串)或 Python 表达式。当组件不通过参数显式依赖其他 ConfigItems,但需要先实例化/评估依赖项时,这非常有用。_disabled_指定是否跳过实例化的标志。_desc_可用于提供自由文本描述。_mode_指定实例化组件或调用可调用对象时的操作模式。目前支持以下值:"default"(默认) – 返回_target_(**kwargs)的返回值。"callable"– 返回一个可调用对象,要么是_target_本身,如果提供了kwargs,则作为functools.partial(_target_, **kwargs)的偏函数。适用于定义稍后将实例化或调用的类或函数。用户可以预定义_target_的某些参数,并在稍后使用附加参数进行调用。"debug"– 使用调试提示符执行并返回pdb.runcall(_target_, **kwargs)的返回值,另请参阅pdb.runcall。
多个配置文件#
描述: 可以在命令行中指定多个配置文件。这些配置文件的内容会被合并。当多个配置文件中指定了相同的键时,该键关联的值将被按指定顺序覆盖。如果期望的行为是合并两个文件中的值,则第二个配置文件中的键应加上 + 前缀。合并内容的值类型必须匹配且均为 dict 或 list 类型。dict 值将通过 update() 合并,list 值通过 extend() 连接。这是一个示例。在此情况下,“amp”值将被 extra_config.json 覆盖。imports 和 preprocessing#transforms 列表将被合并。如果 "+imports" 中的值类型不是 list,则会抛出错误。
config.json
{
"amp": "$True"
"imports": [
"$import torch"
],
"preprocessing": {
"_target_": "Compose",
"transforms": [
"$@t1",
"$@t2"
]
},
}
extra_config.json
{
"amp": "$False"
"+imports": [
"$from monai.networks import trt_compile"
],
"+preprocessing#transforms": [
"$@t3"
]
}
命令行界面#
除了 Python API 外,还提供了一些命令行界面 (CLI) 来与 bundle 进行交互。主要用法是:
python -m monai.bundle COMMANDS
其中 COMMANDS 为以下之一:run, verify_metadata, ckpt_export, …(请参阅 python -m monai.bundle --help 获取可用选项列表)。
CLI 支持灵活的用例,例如在运行时覆盖配置和在文件中预定义参数。要显示命令(例如 run)的使用页面:
python -m monai.bundle run -- --help
此支持由 Python Fire 提供,请确保安装了该可选依赖项,例如使用 pip install monai[fire] 或 pip install fire。有关 CLI 参数解析的详细信息,请参阅 Python Fire 指南。
建议#
支持
YAML和JSON,但不支持这些格式的高级特性。为配置元素使用有意义的名称可以提高可读性。
虽然可以使用 Bundle 语法构建复杂的配置,但更推荐使用结构简单、少量使用表达式或引用的配置。
对于配置中的
$import <module>,如果<module>不是 MONAI 的(可选)依赖项,请确保提供用户安装该<module>的说明。由于
#,::和$可能会被shell或CLI工具以不同方式解释,在命令行中可能需要添加转义字符或引号,例如:"\$torch.device('cuda:1')","'train_part#trainer'"。有关更多详细信息和示例,请参阅 教程。