从实例化配置中获取原始 Hydra 配置
Get original Hydra configuration from instantiated config
在Hydra I can automatically instantiate my classes中,例如
_target_: ClassA
foo: bar
model:
_target_: ClassB
hello: world
这导致递归实例化 classes,例如“内部 class”实例传递给“外部 classes”的地方:
ClassA(
foo="bar"
model=ClassB(
hello="world"
)
)
有没有办法让 ClassA
获得 ClassB
的原始配置结构,以便我同时拥有实例 ClassB
和原始结构,例如模型及其超参数
model:
_target_: ClassB
hello: world
您可以结合使用 OmegaConf 的 variable interpolation with its custom resolvers。
这是一个示例,其中 ClassA.__init__
接收 model
和 modelconf
作为参数。参数 modelconf
是 cfg.model
的副本,它的 _target_
字段已被删除。
# conf.yaml
_target_: app.ClassA
foo: bar
model:
_target_: app.ClassB
hello: world
modelconf: "${remove_target: ${.model}}"
# app.py
import hydra
from omegaconf import DictConfig, OmegaConf
class ClassB:
def __init__(self, hello: str):
print(f"ClassB.__init__ got {hello=}")
class ClassA:
def __init__(self, foo: str, model: ClassB, modelconf: DictConfig) -> None:
print(f"ClassA.__init__ got {foo=}, {model=}, {modelconf=}")
def remove_target_impl(conf: DictConfig) -> DictConfig:
"""Return a copy of `conf` with its `_target_` field removed."""
conf = conf.copy()
conf.pop("_target_")
return conf
OmegaConf.register_new_resolver(
"remove_target", resolver=remove_target_impl, replace=True
)
@hydra.main(config_path=".", config_name="conf.yaml")
def main(cfg: DictConfig) -> None:
hydra.utils.instantiate(cfg)
if __name__ == "__main__":
main()
在命令行:
$ python3 app.py
ret = run_job(
ClassB.__init__ got hello='world'
ClassA.__init__ got foo='bar', model=<app.ClassB object at 0x10a125ee0>, modelconf={'hello': 'world'}
从modelconf
中删除_target_
字段的动机如下:
如果 _target_
键 而不是 删除,那么对 instantiate
的调用将导致 modelconf
被映射到 ClassB
的实例(而不是DictConfig
)。
另请参阅 instantiate
的 _convert_
参数。使用 _convert_=="partial"
或 _convert_=="all"
意味着 ClassA.__init__
将接收 modelconf
类型的参数 dict
而不是类型 DictConfig
.
def remove_target_and_add_convert_impl(conf: DictConfig) -> DictConfig:
conf = conf.copy()
conf.pop("_target_")
conf["_convert_"] = "all" # instantiate should now result in a dict rather than in a DictConfig
return conf
在Hydra I can automatically instantiate my classes中,例如
_target_: ClassA
foo: bar
model:
_target_: ClassB
hello: world
这导致递归实例化 classes,例如“内部 class”实例传递给“外部 classes”的地方:
ClassA(
foo="bar"
model=ClassB(
hello="world"
)
)
有没有办法让 ClassA
获得 ClassB
的原始配置结构,以便我同时拥有实例 ClassB
和原始结构,例如模型及其超参数
model:
_target_: ClassB
hello: world
您可以结合使用 OmegaConf 的 variable interpolation with its custom resolvers。
这是一个示例,其中 ClassA.__init__
接收 model
和 modelconf
作为参数。参数 modelconf
是 cfg.model
的副本,它的 _target_
字段已被删除。
# conf.yaml
_target_: app.ClassA
foo: bar
model:
_target_: app.ClassB
hello: world
modelconf: "${remove_target: ${.model}}"
# app.py
import hydra
from omegaconf import DictConfig, OmegaConf
class ClassB:
def __init__(self, hello: str):
print(f"ClassB.__init__ got {hello=}")
class ClassA:
def __init__(self, foo: str, model: ClassB, modelconf: DictConfig) -> None:
print(f"ClassA.__init__ got {foo=}, {model=}, {modelconf=}")
def remove_target_impl(conf: DictConfig) -> DictConfig:
"""Return a copy of `conf` with its `_target_` field removed."""
conf = conf.copy()
conf.pop("_target_")
return conf
OmegaConf.register_new_resolver(
"remove_target", resolver=remove_target_impl, replace=True
)
@hydra.main(config_path=".", config_name="conf.yaml")
def main(cfg: DictConfig) -> None:
hydra.utils.instantiate(cfg)
if __name__ == "__main__":
main()
在命令行:
$ python3 app.py
ret = run_job(
ClassB.__init__ got hello='world'
ClassA.__init__ got foo='bar', model=<app.ClassB object at 0x10a125ee0>, modelconf={'hello': 'world'}
从modelconf
中删除_target_
字段的动机如下:
如果 _target_
键 而不是 删除,那么对 instantiate
的调用将导致 modelconf
被映射到 ClassB
的实例(而不是DictConfig
)。
另请参阅 instantiate
的 _convert_
参数。使用 _convert_=="partial"
或 _convert_=="all"
意味着 ClassA.__init__
将接收 modelconf
类型的参数 dict
而不是类型 DictConfig
.
def remove_target_and_add_convert_impl(conf: DictConfig) -> DictConfig:
conf = conf.copy()
conf.pop("_target_")
conf["_convert_"] = "all" # instantiate should now result in a dict rather than in a DictConfig
return conf