在文件或文件夹上使用 glob 进行多次运行

Multirun with glob on files or folders

假设目录结构如下:

/input/files/path
  /input1
    /file1_1.json
    /file1_2.json
  /input2
    /file2_1.json
  /someting_unrelated
  ...

我想 运行 多次使用 Hydra 配置的脚本,每次都获取 input* 文件夹之一的完整路径。

这是如何实现的?

以下是我能想到的两种方法:

方法 1:使用 shell 实用程序将 *.json 文件名列表传递给您的应用程序

您可以使用外部实用程序,例如GNU findpaste,以创建您要使用的 *.json 文件的逗号分隔列表。

$ find input -name '*.json' | paste -sd "," -
input/files/path/input1/file1_1.json,input/files/path/input1/file1_2.json,input/files/path/input2/file2_1.json

然后您可以将这些文件路径传递给您的应用以执行 multirun sweep:

$ python my_app.py --multirun file_path="$(find input -name '*.json' | paste -sd ',' -)"
[2021-10-29 12:53:37,059][HYDRA] Launching 3 jobs locally
[2021-10-29 12:53:37,059][HYDRA]        #0 : file_path=input/files/path/input1/file1_1.json
{'file_path': 'input/files/path/input1/file1_1.json'}
[2021-10-29 12:53:37,136][HYDRA]        #1 : file_path=input/files/path/input1/file1_2.json
{'file_path': 'input/files/path/input1/file1_2.json'}
[2021-10-29 12:53:37,219][HYDRA]        #2 : file_path=input/files/path/input2/file2_1.json
{'file_path': 'input/files/path/input2/file2_1.json'}

.json 文件的文件路径可通过应用配置中的 file_path 键提供给应用的主要功能。

这是我用来生成上述输出的 my_app.pyconfig.yaml 文件:

# my_app.py
import hydra

@hydra.main(config_path=".", config_name="config")
def main(cfg):
    print(cfg)

if __name__ == "__main__":
    main()
# config.yaml
file_path: ???

方法 2:在配置组中注册 .json 文件的路径

  • 第 1 步:使用 python 代码生成您感兴趣的 .json 个文件的路径列表。
  • 第 2 步:使用包含每个文件路径的 Config Store API to register input configs
  • 第 3 步:在命令行中,使用 glob choice sweep 扫描在第 2 步中注册的所有输入配置。

详细:

# my_app.py
import os
import hydra

# Step 1: Use os.walk to make a list of paths to .json files
json_filepaths = []
for dirpath, dirnames, filenames in os.walk("input"):
    for filename in filenames:
        if filename.endswith(".json"):
            json_filepaths.append(f"{dirpath}/{filename}")

# Step 2: For each .json file path, register an input config
cs = hydra.core.config_store.ConfigStore.instance()
for fpath in json_filepaths:
    cs.store(
        name=fpath.replace("/", "-"),  # the names must be unique for each fpath and must not contain a forward slash
        node={"file_path": fpath},
        group="json_input",
    )

@hydra.main(config_path=".", config_name="config")
def main(cfg):
    print(cfg)

if __name__ == "__main__":
    main()
# config.yaml
defaults:
  - json_input: ???
$ # Step 3: Doing a --multirun sweep over the `json_input` group:
$ p3 my_app.py --multirun 'json_input=glob(*)'
[2021-10-29 21:14:28,643][HYDRA] Launching 3 jobs locally
[2021-10-29 21:14:28,643][HYDRA]        #0 : json_input=input-files-path-input1-file1_1.json
{'json_input': {'file_path': 'input/files/path/input1/file1_1.json'}}
[2021-10-29 21:14:28,726][HYDRA]        #1 : json_input=input-files-path-input1-file1_2.json
{'json_input': {'file_path': 'input/files/path/input1/file1_2.json'}}
[2021-10-29 21:14:28,817][HYDRA]        #2 : json_input=input-files-path-input2-file2_1.json
{'json_input': {'file_path': 'input/files/path/input2/file2_1.json'}}

.json 文件的文件路径可通过应用配置中的 json_input.file_path 键提供给应用的主要功能。

Hydra 不支持 json。使用 yaml 文件。

关于 glob 上的多重运行,请参阅覆盖语法页面中的glob

例如:

python foo.py 'config/group=glob(input*)'

请注意,根据您的 shell 行为,可能需要引用。

从你的问题中不清楚的一件事是你的配置文件是否在配置搜索路径中。如果它们不是,您必须将它们的目录添加到搜索路径中。有关详细信息,请参阅 searchpath