ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Hydra 输出/工作目录机制详解:自动创建输出目录、chdir 切换与原始工作目录访问

Hydra 输出/工作目录机制详解:自动创建输出目录、chdir 切换与原始工作目录访问 Hydra 输出/工作目录机制详解自动创建输出目录、chdir 切换与原始工作目录访问【免费下载链接】hydraHydra is a framework for elegantly configuring complex applications项目地址: https://gitcode.com/GitHub_Trending/hyd/hydra本指南系统讲解 Hydra 的 Output/Working directory输出/工作目录机制Hydra 如何为每次运行自动创建独立输出目录、如何通过 Hydra 配置在代码中获取输出目录路径、hydra.job.chdir如何改变进程工作目录以及get_original_cwd()/to_absolute_path()如何帮助你始终定位到原始启动目录。读完本文你将能够彻底掌控 Hydra 应用的文件落盘位置并据此设计出可复现、易排查的工程实践。Hydra 为什么为每次运行创建独立输出目录在深度学习、科学计算等场景中应用常常需要把结果、日志、模型权重等写入文件。如果每次都写到同一个目录不同实验的产物会互相覆盖难以回溯。Hydra 的核心设计之一就是解决“每次运行都要手动指定一个新输出目录”的痛点Hydra 会在每次运行前自动创建一个新的输出目录并在你的代码执行前将进程的工作目录切换到该输出目录此行为可通过hydra.job.chdir控制详见后文默认情况下该输出目录用于存放本次运行的 Hydra 输出包括组合后的配置Configuration与日志Logs等每次运行都会创建全新的目录互不干扰天然支持多实验并行与事后追溯。这一行为在仓库中由 hydra/core/utils.py 中的任务运行逻辑落地运行开始时执行Path(str(output_dir)).mkdir(parentsTrue, exist_okTrue)创建目录随后依据hydra.job.chdir决定是否调用os.chdir(output_dir)见 hydra/core/utils.py#L150-L159。在代码中获取输出目录路径检查 Hydra 配置输出目录的完整路径会在运行时写入 Hydra 配置的hydra.runtime.output_dir字段。你可以在被hydra.main装饰的函数内通过HydraConfig单例读取它。下面是一个完整可运行的示例对应仓库中的 examples/tutorials/basic/running_your_hydra_app/3_working_directory/my_app.pyimport os from omegaconf import DictConfig import hydra hydra.main(version_baseNone) def my_app(_cfg: DictConfig) - None: print(fWorking directory : {os.getcwd()}) print(fOutput directory : {hydra.core.hydra_config.HydraConfig.get().runtime.output_dir})运行两次观察输出目录如何变化$ python my_app.py Working directory : /home/omry/dev/hydra Output directory : /home/omry/dev/hydra/outputs/2019-09-25/15-16-17 $ python my_app.py Working directory : /home/omry/dev/hydra Output directory : /home/omry/dev/hydra/outputs/2019-09-25/15-16-19可以看到默认未开启chdir时os.getcwd()仍然是启动应用的目录工作目录与输出目录是两个不同的位置输出目录形如outputs/日期/时间两次运行因为时刻不同而彼此独立。关于访问 Hydra 配置的更多方式如配置内使用${hydra:job.name}解析器、代码内使用HydraConfig.get()可参考 website/docs/configure_hydra/Intro.md。输出目录里到底有什么.hydra 与日志文件用tree查看其中一个输出目录的完整内容$ tree outputs/2019-09-25/15-16-17 outputs/2019-09-25/15-16-17 ├── .hydra │ ├── config.yaml │ ├── hydra.yaml │ └── overrides.yaml └── my_app.log输出目录默认包含两部分条目说明.hydra/Hydra 输出子目录默认名称存放本次运行的三个 YAML 转储my_app.log本次运行的应用日志文件依据默认job_logging配置生成.hydra内的三个文件各自承担不同职责config.yaml用户指定配置组合后任务配置的转储即去除 Hydra 命名空间后的最终配置快照hydra.yamlHydra 自身配置的转储包含hydra.run.dir、hydra.job、hydra.runtime等完整 Hydra 配置overrides.yaml本次运行使用的命令行覆盖项command line overrides列表。这三个文件的落盘逻辑在 hydra/core/utils.py#L164-L170当config.hydra.output_subdir不为None时依次调用_save_config(task_cfg, config.yaml, hydra_output)、_save_config(hydra_cfg, hydra.yaml, hydra_output)与_save_config(config.hydra.overrides.task, overrides.yaml, hydra_output)。正是有了这套“配置快照 覆盖记录”任何一次运行都能被完整复现。默认输出目录模式从哪来上述outputs/日期/时间的命名规则并非魔法而是定义在 Hydra 自带的默认输出配置 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}单次运行RUN 模式使用hydra.run.dir默认按“日期/时刻”两级组织多运行MULTIRUN/sweep使用hydra.sweep.dir作为总目录、hydra.sweep.subdir作为每个 job 的子目录默认是 job 序号${hydra.job.num}。其中${now:%Y-%m-%d}等是 Hydra 内置的now时间解析器对应配置结构定义在 hydra/conf/init.py#L30-L33RunDir/SweepDir与 hydra/conf/init.py#L127-L130HydraConf.run/hydra_conf.sweep。自动把工作目录切换到输出目录hydra.job.chdir从 Hydra v1.2 开始你可以通过设置hydra.job.chdirTrue让hydra.main装饰器在把控制权交给你的主函数之前调用os.chdir把 Python 进程的工作目录切换到输出目录。chdir的默认值为False自 v1.2 起该默认值在源码中可查证hydra/conf/init.py#L50-L51 中的JobConf.chdir: bool False。命令行中的行为对比# check current working dir $ pwd /home/jasha/dev/hydra # for Hydra 1.2, working dir remains unchanged by default $ python my_app.py Working directory : /home/jasha/dev/hydra Output directory : /home/jasha/dev/hydra/outputs/2023-04-18/13-43-24 # working dir changed to output dir $ python my_app.py hydra.job.chdirTrue Working directory : /home/jasha/dev/hydra/outputs/2023-04-18/13-43-17 Output directory : /home/jasha/dev/hydra/outputs/2023-04-18/13-43-17 # output dir and files are still created even if chdir is disabled: $ tree -a outputs/2023-04-18/13-43-24/ outputs/2023-04-18/13-43-24/ ├── .hydra │ ├── config.yaml │ ├── hydra.yaml │ └── overrides.yaml └── my_app.log要点总结hydra.job.chdirFalse默认进程 cwd 保持为启动目录输出目录照常创建但你的代码写相对路径时落盘位置是启动目录而非输出目录hydra.job.chdirTrueos.getcwd()与输出目录一致此时在代码里写相对路径例如数据库 dump 文件会直接落到输出目录中天然实现“一个实验一份产物”非常适合需要持久化中间结果的场景。chdir在底层执行顺序为创建输出目录 →os.chdir(output_dir)→ 记录working_dir→ 配置日志 → 保存.hydra配置文件 → 调用用户主函数见 hydra/core/utils.py#L150-L176。仓库测试也覆盖了两种取值例如 tests/test_basic_sweeper.py 中分别用hydra.job.chdirTrue与hydra.job.chdirFalse验证工作目录行为tests/test_callbacks.py 同样在回调场景下做了验证hydra.job.chdirnull这类非法覆盖会被拒绝见 tests/test_compose.py 中的合并报错测试。修改或禁用 .hydra 输出子目录默认情况下三个 YAML 快照文件被放在名为.hydra的子目录里。你可以通过覆盖hydra.output_subdir改变它的名称或将其设为null来彻底禁用该子目录的创建# 修改子目录名称 python my_app.py hydra.output_subdirhydra_config # 禁用子目录创建不再生成 .hydra python my_app.py hydra.output_subdirnull该字段在源码中的定义是output_subdir: Optional[str] .hydra见 hydra/conf/init.py#L148-L152注释明确指出hydra.yaml、overrides.yaml等将写入此目录便于调试与回顾历史运行设为None将阻止输出子目录的创建。相应地hydra/core/utils.py#L164-L170 仅在config.hydra.output_subdir is not None时才保存这三个文件。需要提醒的是虽然禁用.hydra可以减少磁盘占用但也会失去配置与覆盖项的快照影响运行可复现性通常不建议在生产流程中关闭。开启 chdir 后如何访问原始工作目录启用hydra.job.chdirTrue后os.getcwd()变成了输出目录那么原本的启动目录如何访问Hydra 在hydra.utils中提供了两个工具函数get_original_cwd()返回应用最初启动时的工作目录to_absolute_path(path)把传入路径转为绝对路径——若为相对路径则基于原始工作目录解析若本身是绝对路径则原样返回。参考示例对应 examples/tutorials/basic/running_your_hydra_app/3_working_directory/original_cwd.pyfrom hydra.utils import get_original_cwd, to_absolute_path hydra.main(version_baseNone) def my_app(_cfg: DictConfig) - None: print(fCurrent working directory : {os.getcwd()}) print(fOrig working directory : {get_original_cwd()}) print(fto_absolute_path(foo) : {to_absolute_path(foo)}) print(fto_absolute_path(/foo) : {to_absolute_path(/foo)}) if __name__ __main__: my_app()Current working directory : /Users/omry/dev/hydra/outputs/2019-10-23/10-53-03 Original working directory : /Users/omry/dev/hydra to_absolute_path(foo) : /Users/omry/dev/hydra/foo to_absolute_path(/foo) : /foo这一组合的意义在于无论进程是否 chdir 到输出目录你都能稳定地读写位于启动目录下的输入数据如数据集、预训练权重。其实现可直接在 hydra/utils.py#L93-L123 中看到get_original_cwd()读取HydraConfig.get().runtime.cwd并要求 HydraConfig 已初始化否则抛出ValueErrorto_absolute_path()则依据“相对路径以原始工作目录为基准、绝对路径原样返回”的规则拼接。因此把数据加载写成to_absolute_path(data/train.csv)无论在哪里运行都不会迷失路径。自定义输出目录模式除了默认的outputs/日期/时间Hydra 允许通过配置hydra.run.dir单次运行与hydra.sweep.dir/hydra.sweep.subdir多运行 sweep完全自定义目录模式。仓库配套示例见 examples/configure_hydra/workdir/conf/config.yaml# package _global_ hydra: run: dir: run_dir sweep: dir: sweep_dir subdir: ${hydra.job.num} a: a1常用模式示例完整说明见 website/docs/configure_hydra/workdir.md# 按日期分组 hydra: run: dir: ./outputs/${now:%Y-%m-%d}/${now:%H-%M-%S} # 按 job 名分组 hydra: run: dir: outputs/${hydra.job.name}/${now:%Y-%m-%d_%H-%M-%S} # 目录名中嵌入用户配置变量 hydra: run: dir: outputs/${now:%Y-%m-%d_%H-%M-%S}/opt:${optimizer.type}多运行sweep模式下则通过hydra.sweep.dir控制所有 job 的公共目录、hydra.sweep.subdir控制每个 job 的子目录例如基于命令行覆盖项生成目录名可使用hydra_override_dirname解析器。输出目录模式的最终值会在运行时反映到hydra.runtime.output_dir供HydraConfig.get().runtime.output_dir读取。小结Hydra 的输出/工作目录机制可以用一张流程图概括应用启动 → Hydra 按hydra.run.dir或hydra.sweep.dir/subdir模式计算出本次运行的输出目录并自动创建依据hydra.job.chdir决定是否把进程 cwd 切换到输出目录配置日志、写入.hydra/config.yaml、.hydra/hydra.yaml、.hydra/overrides.yaml三个快照文件执行用户主函数代码中可通过HydraConfig.get().runtime.output_dir、get_original_cwd()、to_absolute_path()定位任何需要的路径。掌握以上机制你就能做到每次实验产物自动隔离、配置与覆盖项完整留档、输入数据路径始终稳定从而获得干净、可复现、易排查的实验工作流。若想进一步定制目录命名按 job 名、按配置变量、按命令行参数生成目录请继续阅读 website/docs/configure_hydra/workdir.md。【免费下载链接】hydraHydra is a framework for elegantly configuring complex applications项目地址: https://gitcode.com/GitHub_Trending/hyd/hydra创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表