-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbatch_run.py
More file actions
115 lines (98 loc) · 3.32 KB
/
batch_run.py
File metadata and controls
115 lines (98 loc) · 3.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import argparse
import subprocess
import sys
from pathlib import Path
SWEEP_ROOT = Path("configs/_lambda_sweep_by_dataset")
OUTPUT_ROOT = Path("outputs/_lambda_sweep_by_dataset")
GROUP_ORDER = [
"noclip_noadjust",
"noclip_adjust",
"clip_noadjust",
"clip_adjust",
"scale_noadjust",
"scale_adjust",
]
DATASET_ORDER = ["ETF_A", "ETF_B", "DOW"]
def lambda_sort_key(config_path):
tag = config_path.stem.rsplit("_lambda_", 1)[-1]
return float(tag.replace("p", "."))
def collect_configs(groups=None, datasets=None):
groups = groups or GROUP_ORDER
datasets = datasets or DATASET_ORDER
configs = []
for group in groups:
for dataset in datasets:
dataset_dir = SWEEP_ROOT / group / dataset
if not dataset_dir.exists():
raise FileNotFoundError(f"Missing directory: {dataset_dir}")
configs.extend(sorted(dataset_dir.glob("*.yaml"), key=lambda_sort_key))
return configs
def config_group_dataset(config_path):
rel = config_path.relative_to(SWEEP_ROOT)
group = rel.parts[0]
dataset = rel.parts[1]
return group, dataset
def main():
parser = argparse.ArgumentParser(
description="Run all lambda sweep configs organized by group and dataset."
)
parser.add_argument(
"--python",
default=sys.executable,
help="Python executable used to launch run.py. Defaults to current interpreter.",
)
parser.add_argument(
"--group",
action="append",
choices=GROUP_ORDER,
help="Run only this group. Can be passed multiple times.",
)
parser.add_argument(
"--dataset",
action="append",
choices=DATASET_ORDER,
help="Run only this dataset. Can be passed multiple times.",
)
parser.add_argument(
"--dry-run",
action="store_true",
help="Print commands without running them.",
)
parser.add_argument(
"--continue-on-error",
action="store_true",
help="Keep running remaining configs if one config fails.",
)
parser.add_argument(
"--output-root",
default=str(OUTPUT_ROOT),
help="Root output directory. Results are written to output-root/dataset/group.",
)
parser.add_argument(
"--flat-output",
action="store_true",
help="Use each yaml's output_dir instead of organizing outputs by dataset/group.",
)
args = parser.parse_args()
configs = collect_configs(groups=args.group, datasets=args.dataset)
if not configs:
raise SystemExit("No configs found.")
for i, config in enumerate(configs, start=1):
cmd = [args.python, "run.py", "--config", str(config)]
if not args.flat_output:
group, dataset = config_group_dataset(config)
output_dir = Path(args.output_root) / dataset / group
cmd.extend(["--output_dir", str(output_dir)])
print(f"\n[{i}/{len(configs)}] running {config}")
print(" ".join(cmd))
if args.dry_run:
continue
result = subprocess.run(cmd)
if result.returncode != 0:
message = f"failed: {config} (exit code {result.returncode})"
if args.continue_on_error:
print(message)
else:
raise SystemExit(message)
if __name__ == "__main__":
main()