Skip to content

Commit 7bd9eb5

Browse files
authored
feat: optuna tune script PoC (#1411)
* feat: optuna tune script PoC * fix: workaround for latest version of Jinja2 * fix: workaround for latest version of click * fix: workaround for minimal tests added * fix: workaround for new version of "accelerate" added * tests: test_tune minimal updated * docs: changelog updated * tests: "check_config_api.sh" workflow added
1 parent bd9578e commit 7bd9eb5

File tree

15 files changed

+375
-23
lines changed

15 files changed

+375
-23
lines changed

.github/workflows/codestyle.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ jobs:
8383
env:
8484
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
8585
run: |
86-
LINE_LENGTH=99 catalyst-codestyle-flake8 . | reviewdog -f=pep8 -reporter=github-pr-review
86+
LINE_LENGTH=89 catalyst-codestyle-flake8 . | reviewdog -f=pep8 -reporter=github-pr-review
8787
8888
build:
8989
name: codestyle-and-docs

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
88

99
### Added
1010

11-
-
11+
- `catalyst-tune` for Config API added [#1411](https://github.com/catalyst-team/catalyst/pull/1411)
1212

1313
### Changed
1414

bin/workflows/check_config_api.sh

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#!/usr/bin/env bash
2+
3+
# Cause the script to exit if a single command fails
4+
set -eo pipefail -v
5+
6+
DEVICE=${DEVICE:="cpu"}
7+
8+
pip install -e . --quiet --no-deps --upgrade-strategy only-if-needed
9+
10+
################################ pipeline 00 ################################
11+
# checking `catalyst-run` console script entry point
12+
13+
PYTHONPATH="${PYTHONPATH}:." catalyst-run \
14+
-C "tests/pipelines/configs/test_mnist.yml" \
15+
"tests/pipelines/configs/engine_${DEVICE}.yml"
16+
17+
rm -rf tests/logs
18+
19+
################################ pipeline 01 ################################
20+
# checking `catalyst-tune` console script entry point
21+
22+
pip install -r requirements/requirements-optuna.txt --quiet \
23+
--find-links https://download.pytorch.org/whl/cpu/torch_stable.html \
24+
--upgrade-strategy only-if-needed
25+
26+
PYTHONPATH="${PYTHONPATH}:." catalyst-tune \
27+
-C "tests/contrib/scripts/test_tune.yml" \
28+
"tests/pipelines/configs/engine_${DEVICE}.yml" \
29+
--n-trials 2
30+
31+
rm -rf tests/logs

catalyst/contrib/scripts/run.py

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
from typing import Iterable
1+
#!/usr/bin/env python
2+
from typing import Dict, Iterable
23
import argparse
34
import logging
45

56
from catalyst import utils
67
from catalyst.registry import REGISTRY
78

89

9-
def parse_args():
10+
def parse_args(args: Iterable = None, namespace: argparse.Namespace = None):
1011
"""Parses the command line arguments and returns arguments and config."""
1112
parser = argparse.ArgumentParser()
1213
parser.add_argument(
@@ -29,18 +30,14 @@ def parse_args():
2930
)
3031
utils.boolean_flag(parser, "benchmark", default=None, help="Use CuDNN benchmark")
3132

32-
args, unknown_args = parser.parse_known_args()
33+
args, unknown_args = parser.parse_known_args(args=args, namespace=namespace)
3334
return vars(args), unknown_args
3435

3536

36-
def run_from_config(
37-
configs: Iterable[str],
38-
deterministic: bool = None,
39-
benchmark: bool = None,
40-
) -> None:
41-
"""Creates Runner from YAML configs and runs experiment."""
42-
logger = logging.getLogger(__name__)
43-
37+
def process_configs(
38+
configs: Iterable[str], deterministic: bool = None, benchmark: bool = None
39+
) -> Dict:
40+
"""Merges YAML configs and prepares env."""
4441
# there is no way to set deterministic/benchmark flags with a runner,
4542
# so do it manually
4643
utils.prepare_cudnn(deterministic, benchmark)
@@ -49,9 +46,13 @@ def run_from_config(
4946
for config_path in configs:
5047
config_part = utils.load_config(config_path, ordered=True)
5148
config = utils.merge_dicts(config, config_part)
52-
# config_copy = copy.deepcopy(config)
5349

54-
experiment_params = REGISTRY.get_from_params(**config)
50+
return config
51+
52+
53+
def run_from_params(experiment_params: Dict) -> None:
54+
"""Runs multi-stage experiment."""
55+
logger = logging.getLogger(__name__)
5556

5657
runner = experiment_params["runner"]
5758
for stage_params in experiment_params["run"]:
@@ -62,15 +63,21 @@ def run_from_config(
6263
if result is not None:
6364
logger.info(f"{name}:\n{result}")
6465

65-
# TODO: check if needed
66-
# logdir = getattr(runner, "logdir", getattr(runner, "_logdir"), None)
67-
# if logdir and utils.get_rank() <= 0:
68-
# utils.dump_environment(logdir=logdir, config=config_copy, configs_path=configs)
66+
67+
def run_from_config(
68+
configs: Iterable[str],
69+
deterministic: bool = None,
70+
benchmark: bool = None,
71+
) -> None:
72+
"""Creates Runner from YAML configs and runs experiment."""
73+
config = process_configs(configs, deterministic=deterministic, benchmark=benchmark)
74+
experiment_params = REGISTRY.get_from_params(**config)
75+
run_from_params(experiment_params)
6976

7077

7178
def main():
7279
"""Runs the ``catalyst-run`` script."""
73-
kwargs, unknown_args = parse_args()
80+
kwargs, _ = parse_args()
7481
run_from_config(**kwargs)
7582

7683

catalyst/contrib/scripts/tune.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#!/usr/bin/env python
2+
"""Config API and Optuna integration for AutoML hyperparameters tuning."""
3+
from typing import Iterable
4+
import argparse
5+
import copy
6+
7+
import optuna
8+
9+
from catalyst import utils
10+
from catalyst.contrib.scripts import run
11+
from catalyst.registry import REGISTRY
12+
from hydra_slayer import functional as F
13+
14+
15+
def parse_args(args: Iterable = None, namespace: argparse.Namespace = None):
16+
"""Parses the command line arguments and returns arguments and config."""
17+
parser = argparse.ArgumentParser()
18+
parser.add_argument("--n-trials", type=int, default=None)
19+
parser.add_argument("--timeout", type=int, default=None)
20+
parser.add_argument("--n-jobs", type=int, default=1)
21+
utils.boolean_flag(parser, "gc-after-trial", default=False)
22+
utils.boolean_flag(parser, "show-progress-bar", default=False)
23+
24+
args, unknown_args = parser.parse_known_args(args=args, namespace=namespace)
25+
return vars(args), unknown_args
26+
27+
28+
def main():
29+
"""Runs the ``catalyst-tune`` script."""
30+
kwargs_run, unknown_args = run.parse_args()
31+
kwargs_tune, _ = parse_args(args=unknown_args)
32+
33+
config_full = run.process_configs(**kwargs_run)
34+
config = copy.copy(config_full)
35+
config_study = config.pop("study")
36+
37+
# optuna objective
38+
def objective(trial: optuna.trial):
39+
# workaround for `REGISTRY.get_from_params` - redefine `trial` var
40+
experiment_params, _ = F._recursive_get_from_params(
41+
factory_key=REGISTRY.name_key,
42+
get_factory_func=REGISTRY.get,
43+
params=config,
44+
shared_params={},
45+
var_key=REGISTRY.var_key,
46+
attrs_delimiter=REGISTRY.attrs_delimiter,
47+
vars_dict={**REGISTRY._vars_dict, "trial": trial},
48+
)
49+
runner = experiment_params["runner"]
50+
runner._trial = trial
51+
52+
run.run_from_params(experiment_params)
53+
score = runner.epoch_metrics[runner._valid_loader][runner._valid_metric]
54+
55+
return score
56+
57+
study = REGISTRY.get_from_params(**config_study)
58+
study.optimize(objective, **kwargs_tune)
59+
60+
61+
if __name__ == "__main__":
62+
main()

examples/notebooks/XLA.ipynb

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,36 @@
704704
"runner = CustomRunner(logdir)\n",
705705
"runner.run()"
706706
]
707+
},
708+
{
709+
"cell_type": "markdown",
710+
"metadata": {},
711+
"source": [
712+
"# Integrations"
713+
]
714+
},
715+
{
716+
"cell_type": "markdown",
717+
"metadata": {},
718+
"source": []
719+
},
720+
{
721+
"cell_type": "code",
722+
"execution_count": null,
723+
"metadata": {},
724+
"outputs": [],
725+
"source": [
726+
"! cd catalyst && pip install -e ."
727+
]
728+
},
729+
{
730+
"cell_type": "code",
731+
"execution_count": null,
732+
"metadata": {},
733+
"outputs": [],
734+
"source": [
735+
"! cd catalyst && DEVICE=\"engine_core\" bash bin/workflows/check_config_api.sh"
736+
]
707737
}
708738
],
709739
"metadata": {

examples/notebooks/XLA_ddp.ipynb

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,6 +1047,36 @@
10471047
"world_size: int = 8\n",
10481048
"xmp.spawn(train_fn, args=(world_size,), nprocs=world_size, start_method=\"fork\")"
10491049
]
1050+
},
1051+
{
1052+
"cell_type": "markdown",
1053+
"metadata": {},
1054+
"source": [
1055+
"# Integrations"
1056+
]
1057+
},
1058+
{
1059+
"cell_type": "markdown",
1060+
"metadata": {},
1061+
"source": []
1062+
},
1063+
{
1064+
"cell_type": "code",
1065+
"execution_count": null,
1066+
"metadata": {},
1067+
"outputs": [],
1068+
"source": [
1069+
"! cd catalyst && pip install -e ."
1070+
]
1071+
},
1072+
{
1073+
"cell_type": "code",
1074+
"execution_count": null,
1075+
"metadata": {},
1076+
"outputs": [],
1077+
"source": [
1078+
"! cd catalyst && DEVICE=\"ddp_xla\" bash bin/workflows/check_config_api.sh"
1079+
]
10501080
}
10511081
],
10521082
"metadata": {

examples/notebooks/colab_ci_cd.ipynb

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@
145145
},
146146
"outputs": [],
147147
"source": [
148-
"! cd catalyst && catalyst-make-codestyle && catalyst-check-codestyle > codestyle.txt"
148+
"! cd catalyst && catalyst-make-codestyle -l 89 && catalyst-check-codestyle -l 89 > codestyle.txt"
149149
]
150150
},
151151
{
@@ -236,6 +236,16 @@
236236
"! cd catalyst && pip install -e ."
237237
]
238238
},
239+
{
240+
"cell_type": "code",
241+
"execution_count": null,
242+
"metadata": {},
243+
"outputs": [],
244+
"source": [
245+
"! cd catalyst && DEVICE=\"cpu\" bash bin/workflows/check_config_api.sh\n",
246+
"! cd catalyst && DEVICE=\"gpu\" bash bin/workflows/check_config_api.sh"
247+
]
248+
},
239249
{
240250
"cell_type": "code",
241251
"execution_count": null,

requirements/requirements-dev.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
pytest==5.3.1
22
sphinx==2.2.1
3+
Jinja2<=3.0.3
34
docutils==0.17.1
45
# sphinx==4.2.0
56
# git+https://github.com/bitprophet/releases/#egg=releases
67
# git+https://github.com/readthedocs/sphinx_rtd_theme
78
mock==3.0.5
89
catalyst-codestyle==21.09.2
910
black==21.8b0
11+
click<=8.0.4
1012
catalyst-sphinx-theme==1.2.0
1113
tomlkit==0.7.2
1214
pre-commit==2.13.0
13-
path
15+
path

requirements/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ numpy>=1.18
33
torch>=1.4.0
44

55
# hardware backend
6-
accelerate
6+
accelerate>=0.5.1
77

88
# registry
99
hydra-slayer>=0.4.0

0 commit comments

Comments
 (0)