Hydra 配置定制完全指南:从 `--cfg` 到运行期变量与内置解析器
Hydra 配置定制完全指南从--cfg到运行期变量与内置解析器【免费下载链接】hydraHydra is a framework for elegantly configuring complex applications项目地址: https://gitcode.com/GitHub_Trending/hyd/hydraHydra 不仅是配置复杂应用的框架它自身同样是一套可深度定制的配置系统启动器Launcher、搜索器Sweeper、日志Logging、输出目录模式以及应用帮助--help/--hydra-help都可以像定制你自己的配置一样被覆盖和组合。本文以仓库中 version-1.0 的 configure_hydra/Intro.md 为骨架结合当前仓库源码与测试系统讲解 Hydra 自身配置的组成原理、查看方式--cfg、运行期变量以及now、hydra、python_version等内置解析器的使用与实现帮助你彻底掌握配置 Hydra 的 Hydra这一核心能力。版本说明本文主体依据仓库中的 version-1.0 文档撰写并在涉及默认值时以当前仓库主线代码约 version-1.2/1.3 演进的实际内容为准进行对照说明二者存在差异处均已标注。一、Hydra 中可以被定制的内容在 Hydra 中框架自身的大量行为都可以被定制主要包括子系统说明对应的 Hydra 配置组Launcher 配置控制作业如何被启动本地、SLURM、Ray、Submitit 等hydra/launcherSweeper 配置控制多运行multirun / sweep时如何生成参数组合hydra/sweeperLogging 配置控制 Hydra 自身与 Job 的日志行为hydra/hydra_logging、hydra/job_loggingRun 与 Multirun 输出目录模式控制单次运行与批量运行的结果输出路径hydra/output应用帮助控制--help与--hydra-help的展示内容hydra/help、hydra/hydra_help在 hydra/conf/init.py 的HydraConf数据类中这些子系统的默认组合被定义为dataclass class HydraConf: defaults: List[Any] field( default_factorylambda: [ {output: default}, {launcher: basic}, {sweeper: basic}, {help: default}, {hydra_help: default}, {hydra_logging: default}, {job_logging: default}, {callbacks: None}, {env: default}, ] ) ...也就是说Hydra 的配置本身就是一个 defaults 列表驱动组合出来的配置节点这与你在教程中为业务配置使用 defaults 的机制完全一致。二、定制 Hydra 的三种方式Version-1.0 文档明确说明Hydra 可以用你在教程中已经熟悉的方式被定制具体有三种途径在你的配置中直接覆盖把一段 Hydra 配置片段写进自己的配置里直接覆盖对应节点。例如在你的config.yaml中加入hydra: run: dir: my_outputs/${now:%Y-%m-%d}组合不同的配置通过 defaults 或命令行组合插件、或你自己代码提供的不同配置例如hydra/launchersubmitit、hydra/job_loggingdisabled。命令行覆盖像覆盖你自己的配置一样用命令行覆盖 Hydra 的一切。例如python my_app.py hydra.run.direxperiments/exp1 python my_app.py hydra.job.chdirTrue python my_app.py hydra/launcherbasic其中第 3 种方式的底层依据可以从源码中看到在 hydra/core/utils.py 中filter_overrides()会把以hydra.开头的命令行覆盖项过滤出来return [x for x in overrides if not x.startswith(hydra.)]交给 Launcher 处理而任务配置则不受这些 Hydra 专属覆盖项的干扰。三、Hydra 配置与任务配置同体而生、运行前分离Version-1.0 文档指出一个关键设计Hydra 配置实际上位于与你的配置相同的 config 对象中但在运行你的函数之前会被移除以减少混淆。可以用--cfg参数查看三种视图python my_app.py --cfg hydra # 只显示 Hydra 配置 python my_app.py --cfg job # 只显示任务配置 python my_app.py --cfg all # 显示完整配置job hydra--cfg还支持短参数-c并可搭配--package短参数-p精确查看某个子节点。仓库中的测试 tests/test_hydra.py 直接验证了这一行为mark.parametrize( flag,expected_keys, [(--cfgall, [db, hydra]), (--cfghydra, [hydra]), (--cfgjob, [db])], ) def test_cfg(tmpdir, flag, resolve, expected_keys): ...而在 tests/test_hydra.py 的test_cfg_with_package中还演示了--cfgjob --packagedb.driver之类的精确切片查看方式输出mysql。运行前删除的实现位于 hydra/core/utils.py 的run_job()中在调用任务函数前它会深拷贝配置并从拷贝中删除hydra节点再交给任务函数task_cfg copy.deepcopy(config) with read_write(task_cfg): with open_dict(task_cfg): del task_cfg[hydra] ret.cfg task_cfg因此你的任务函数拿到的cfg里没有hydra节点但你依然可以通过解析器见下文访问它。四、Hydra 配置的组成结构与默认值Version-1.0 文档给出了一份部分清单式的 defaults 片段defaults: - hydra/job_logging : default # Jobs logging config - hydra/launcher: basic # Launcher config - hydra/sweeper: basic # Sweeper config - hydra/output: default # Output directory在当前仓库中这些配置组对应的 YAML 文件位于 hydra/conf/hydra/ 目录下例如hydra/conf/hydra/output/default.yaml输出目录默认配置hydra/conf/hydra/job_logging/default.yaml任务日志默认配置hydra/conf/hydra/hydra_logging/default.yamlHydra 自身日志默认配置hydra/conf/hydra/help/default.yaml 与 hydra/conf/hydra/hydra_help/default.yaml两种帮助模板Launcher 与 Sweeper 的默认实现则由核心插件注册见 hydra/_internal/core_plugins/basic_launcher.py其中BasicLauncherConf通过ConfigStore.instance().store(grouphydra/launcher, namebasic, ...)注册到hydra/launcher配置组。输出目录配置Version-1.0 文档展示了组合后 Hydra 配置节点的一个子集hydra: run: # Output directory for normal runs dir: ./outputs/${now:%Y-%m-%d_%H-%M-%S} sweep: # Output directory for sweep runs dir: /checkpoint/${env:USER}/outputs/${now:%Y-%m-%d_%H-%M-%S} # Output sub directory for sweep runs. subdir: ${hydra.job.num}_${hydra.job.id}需要注意其中sweep.dir的/checkpoint/${env:USER}/...是文档示例而当前仓库的实际默认值位于 hydra/conf/hydra/output/default.yaml# package hydra run: dir: outputs/${now:%Y-%m-%d}/${now:%H-%M-%S} sweep: dir: multirun/${now:%Y-%m-%d}/${now:%H-%M-%S} subdir: ${hydra.job.num}也就是说现代版本中单次运行默认输出到outputs/日期/时间多运行默认输出到multirun/日期/时间/序号。这些值均可通过覆盖hydra.run.dir、hydra.sweep.dir、hydra.sweep.subdir自定义。hydra.job.chdirTrue时任务函数的工作目录还会切换到输出目录参见 hydra/core/utils.py 中run_job()对_chdir的处理。五、运行期变量hydra.job.*与hydra.runtime.*Version-1.0 文档指出hydra包会在函数运行时从配置中删除但你仍然可以通过自定义解析器hydra访问 Hydra 中的所有配置节点。语法为解析器名是hydra冒号后面传入key。例如config_name: ${hydra:job.config_name}文档列出的部分运行期变量完整视图可用--cfg hydra查看hydra.jobhydra.job.name作业名默认为去掉后缀的 Python 文件名可被覆盖hydra.job.override_dirname由该作业的覆盖项派生出的路径名hydra.job.num作业在多运行sweep中的序号hydra.job.id底层作业系统如 SLURM中的作业 IDhydra.runtimehydra.runtime.versionHydra 的版本号hydra.runtime.cwd应用启动时的原始工作目录这些字段的运行时定义可以从 hydra/conf/init.py 的JobConf与RuntimeConf数据类中看到name、id、num、config_name、version、cwd、output_dir等均为运行期填充的MISSING字段。在 BasicLauncher 中多运行模式下每个作业的hydra.job.id与hydra.job.num会被显式赋值见 hydra/_internal/core_plugins/basic_launcher.py 的launch()sweep_config.hydra.job.id idx; sweep_config.hydra.job.num idx。版本演进提示hydra.job.override_dirname在当前主线已被标记为废弃见 hydra/core/utils.py 中hydra_deprecated_override_dirname()的deprecation_warning推荐改用${hydra_override_dirname:}解析器其格式化选项kv_sep、item_sep、exclude_keys等定义于hydra.job.config.override_dirname。六、内置解析器ResolversVersion-1.0 文档介绍了 Hydra 默认支持的三个 OmegaConf 解析器。这些解析器的注册代码集中在 hydra/core/utils.py 的setup_globals()中可以逐一对照。now当前时间字符串使用 Pythonstrftime格式生成当前时间字符串例如${now:%H-%M-%S}。底层实现为OmegaConf.register_resolver( now, lambda pattern: datetime.now().strftime(pattern), use_cacheTrue, replaceTrue, )典型用法就是上一节看到的输出目录模式outputs/${now:%Y-%m-%d}/${now:%H-%M-%S}。hydra插值到 Hydra 配置节点例如${hydra:job.name}获取 Hydra 作业名。底层实现为OmegaConf.register_resolver( hydra, lambda path: OmegaConf.select(cast(DictConfig, HydraConfig.get()), path), replaceTrue, )它通过HydraConfig单例拿到当前的 Hydra 配置再用OmegaConf.select按path取节点。因此冒号后可以是任意合法的点路径例如hydra:job.config_name、hydra:runtime.version、hydra:runtime.output_dir等。注意解析器名为hydra与配置组hydra/job_logging这种写法区分开。python_version运行期 Python 版本通过调用sys.version_info返回运行期 Python 版本字符串并可通过参数控制返回粒度。Version-1.0 文档给出的完整示例python_version: ${python_version:} # runtime python version, eg: 3.8 major_version: ${python_version:major} # runtime python major version, eg: 3 minor_version: ${python_version:minor} # runtime python version in the format major.minor, eg: 3.8 micro_version: ${python_version:micro} # runtime python version in the format major.minor.micro, eg: 3.8.2底层实现为vi sys.version_info version_dict { major: f{vi[0]}, minor: f{vi[0]}.{vi[1]}, micro: f{vi[0]}.{vi[1]}.{vi[2]}, } OmegaConf.register_resolver( python_version, lambda levelminor: version_dict.get(level), replaceTrue )可以看到默认不传参数返回major.minor如3.8传major只返回主版本号传minor返回major.minor传micro返回完整的major.minor.micro。解析器之外的补充hydra_override_dirname虽然 1.0 文档未提及但当前仓库还注册了hydra_override_dirname解析器见setup_globals()中OmegaConf.register_resolver(hydra_override_dirname, hydra_override_dirname, replaceTrue)它会根据任务的命令行覆盖项生成目录名并支持kv_sep、item_sep、exclude_keys、element_resolver等选项控制格式是替代已废弃的hydra.job.override_dirname的推荐方式。七、运行期杂项与调试输出除了上述内容理解以下两点有助于排查问题--resolve标志与--cfg或--help搭配时会先解析配置中的插值再打印便于查看最终生效的值。测试 tests/test_hydra.py 验证了a: ${b}在--cfgjob与--cfgjob --resolve两种模式下的不同输出若单独使用--resolve则会报错ValueError: The --resolve flag can only be used in conjunction with --cfg or --help。.hydra输出子目录默认情况下Hydra 会在输出目录中生成.hydra子目录保存config.yaml任务配置、hydra.yamlHydra 配置与overrides.yaml命令行覆盖这在 hydra/core/utils.py 的run_job()中通过_save_config()实现。设置hydra.output_subdir为None可以禁止生成该目录。八、小结与延伸阅读Hydra 把框架自身也当作一等公民配置来对待它与其他配置共存于同一个 config 对象中组合、覆盖、命令行定制的方式与业务配置完全一致仅在任务函数执行前被剥离。掌握--cfg hydra|job|all、运行期变量hydra.job.*、hydra.runtime.*以及now、hydra、python_version等内置解析器就等于掌握了定制 Hydra 输出目录、日志、帮助与调度行为的通用入口。若想继续深入可在本仓库中查看各配置组的实际 YAMLhydra/conf/hydra/output、job_logging、hydra_logging、help、hydra_helpHydra 配置的结构化定义dataclass schemahydra/conf/init.py解析器注册与run_job()实现hydra/core/utils.py--cfg与--package的测试验证tests/test_hydra.py1.0 版本配套文档Configure Hydra Overview【免费下载链接】hydraHydra is a framework for elegantly configuring complex applications项目地址: https://gitcode.com/GitHub_Trending/hyd/hydra创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考