hydra-nevergrad-sweeper 1.3.0.dev0__tar.gz → 1.4.0.dev4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (18) hide show
  1. hydra_nevergrad_sweeper-1.4.0.dev4/MANIFEST.in +3 -0
  2. {hydra-nevergrad-sweeper-1.3.0.dev0 → hydra_nevergrad_sweeper-1.4.0.dev4}/PKG-INFO +20 -7
  3. {hydra-nevergrad-sweeper-1.3.0.dev0 → hydra_nevergrad_sweeper-1.4.0.dev4}/hydra_nevergrad_sweeper.egg-info/PKG-INFO +20 -7
  4. {hydra-nevergrad-sweeper-1.3.0.dev0 → hydra_nevergrad_sweeper-1.4.0.dev4}/hydra_nevergrad_sweeper.egg-info/SOURCES.txt +3 -1
  5. {hydra-nevergrad-sweeper-1.3.0.dev0 → hydra_nevergrad_sweeper-1.4.0.dev4}/hydra_nevergrad_sweeper.egg-info/requires.txt +1 -1
  6. {hydra-nevergrad-sweeper-1.3.0.dev0 → hydra_nevergrad_sweeper-1.4.0.dev4}/hydra_plugins/hydra_nevergrad_sweeper/__init__.py +1 -1
  7. {hydra-nevergrad-sweeper-1.3.0.dev0 → hydra_nevergrad_sweeper-1.4.0.dev4}/hydra_plugins/hydra_nevergrad_sweeper/_impl.py +11 -8
  8. {hydra-nevergrad-sweeper-1.3.0.dev0 → hydra_nevergrad_sweeper-1.4.0.dev4}/hydra_plugins/hydra_nevergrad_sweeper/config.py +1 -2
  9. hydra_nevergrad_sweeper-1.4.0.dev4/hydra_plugins/hydra_nevergrad_sweeper/py.typed +0 -0
  10. {hydra-nevergrad-sweeper-1.3.0.dev0 → hydra_nevergrad_sweeper-1.4.0.dev4}/setup.py +7 -6
  11. hydra_nevergrad_sweeper-1.4.0.dev4/tests/test_nevergrad_sweeper_plugin.py +200 -0
  12. hydra-nevergrad-sweeper-1.3.0.dev0/MANIFEST.in +0 -3
  13. {hydra-nevergrad-sweeper-1.3.0.dev0 → hydra_nevergrad_sweeper-1.4.0.dev4}/README.md +0 -0
  14. {hydra-nevergrad-sweeper-1.3.0.dev0 → hydra_nevergrad_sweeper-1.4.0.dev4}/hydra_nevergrad_sweeper.egg-info/dependency_links.txt +0 -0
  15. {hydra-nevergrad-sweeper-1.3.0.dev0 → hydra_nevergrad_sweeper-1.4.0.dev4}/hydra_nevergrad_sweeper.egg-info/top_level.txt +0 -0
  16. {hydra-nevergrad-sweeper-1.3.0.dev0 → hydra_nevergrad_sweeper-1.4.0.dev4}/hydra_plugins/hydra_nevergrad_sweeper/nevergrad_sweeper.py +0 -0
  17. {hydra-nevergrad-sweeper-1.3.0.dev0 → hydra_nevergrad_sweeper-1.4.0.dev4}/pyproject.toml +0 -0
  18. {hydra-nevergrad-sweeper-1.3.0.dev0 → hydra_nevergrad_sweeper-1.4.0.dev4}/setup.cfg +0 -0
@@ -0,0 +1,3 @@
1
+ global-exclude *.pyc
2
+ global-exclude __pycache__
3
+ recursive-include hydra_plugins/* *.yaml py.typed
@@ -1,19 +1,32 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: hydra-nevergrad-sweeper
3
- Version: 1.3.0.dev0
3
+ Version: 1.4.0.dev4
4
4
  Summary: Hydra Nevergrad Sweeper plugin
5
5
  Home-page: https://github.com/facebookresearch/hydra/
6
6
  Author: Jeremy Rapin, Omry Yadan, Jieru Hu
7
7
  Author-email: jrapin@fb.com, omry@fb.com, jieru@fb.com
8
- Classifier: License :: OSI Approved :: MIT License
9
- Classifier: Programming Language :: Python :: 3.6
10
- Classifier: Programming Language :: Python :: 3.7
11
- Classifier: Programming Language :: Python :: 3.8
12
- Classifier: Programming Language :: Python :: 3.9
8
+ License: MIT
13
9
  Classifier: Programming Language :: Python :: 3.10
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: Programming Language :: Python :: 3.14
14
14
  Classifier: Operating System :: OS Independent
15
15
  Classifier: Development Status :: 4 - Beta
16
+ Requires-Python: >=3.10
16
17
  Description-Content-Type: text/markdown
18
+ Requires-Dist: hydra-core>=1.1.0.dev7
19
+ Requires-Dist: nevergrad>=1.0.12
20
+ Dynamic: author
21
+ Dynamic: author-email
22
+ Dynamic: classifier
23
+ Dynamic: description
24
+ Dynamic: description-content-type
25
+ Dynamic: home-page
26
+ Dynamic: license
27
+ Dynamic: requires-dist
28
+ Dynamic: requires-python
29
+ Dynamic: summary
17
30
 
18
31
  # Hydra Nevergrad Sweeper plugin
19
32
 
@@ -1,19 +1,32 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: hydra-nevergrad-sweeper
3
- Version: 1.3.0.dev0
3
+ Version: 1.4.0.dev4
4
4
  Summary: Hydra Nevergrad Sweeper plugin
5
5
  Home-page: https://github.com/facebookresearch/hydra/
6
6
  Author: Jeremy Rapin, Omry Yadan, Jieru Hu
7
7
  Author-email: jrapin@fb.com, omry@fb.com, jieru@fb.com
8
- Classifier: License :: OSI Approved :: MIT License
9
- Classifier: Programming Language :: Python :: 3.6
10
- Classifier: Programming Language :: Python :: 3.7
11
- Classifier: Programming Language :: Python :: 3.8
12
- Classifier: Programming Language :: Python :: 3.9
8
+ License: MIT
13
9
  Classifier: Programming Language :: Python :: 3.10
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: Programming Language :: Python :: 3.14
14
14
  Classifier: Operating System :: OS Independent
15
15
  Classifier: Development Status :: 4 - Beta
16
+ Requires-Python: >=3.10
16
17
  Description-Content-Type: text/markdown
18
+ Requires-Dist: hydra-core>=1.1.0.dev7
19
+ Requires-Dist: nevergrad>=1.0.12
20
+ Dynamic: author
21
+ Dynamic: author-email
22
+ Dynamic: classifier
23
+ Dynamic: description
24
+ Dynamic: description-content-type
25
+ Dynamic: home-page
26
+ Dynamic: license
27
+ Dynamic: requires-dist
28
+ Dynamic: requires-python
29
+ Dynamic: summary
17
30
 
18
31
  # Hydra Nevergrad Sweeper plugin
19
32
 
@@ -10,4 +10,6 @@ hydra_nevergrad_sweeper.egg-info/top_level.txt
10
10
  hydra_plugins/hydra_nevergrad_sweeper/__init__.py
11
11
  hydra_plugins/hydra_nevergrad_sweeper/_impl.py
12
12
  hydra_plugins/hydra_nevergrad_sweeper/config.py
13
- hydra_plugins/hydra_nevergrad_sweeper/nevergrad_sweeper.py
13
+ hydra_plugins/hydra_nevergrad_sweeper/nevergrad_sweeper.py
14
+ hydra_plugins/hydra_nevergrad_sweeper/py.typed
15
+ tests/test_nevergrad_sweeper_plugin.py
@@ -1,2 +1,2 @@
1
1
  hydra-core>=1.1.0.dev7
2
- nevergrad>=0.4.3.post9
2
+ nevergrad>=1.0.12
@@ -1,3 +1,3 @@
1
1
  # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
2
2
 
3
- __version__ = "1.3.0.dev0"
3
+ __version__ = "1.4.0.dev4"
@@ -33,7 +33,7 @@ log = logging.getLogger(__name__)
33
33
 
34
34
 
35
35
  def create_nevergrad_param_from_config(
36
- config: Union[MutableSequence[Any], MutableMapping[str, Any]]
36
+ config: Union[MutableSequence[Any], MutableMapping[str, Any]],
37
37
  ) -> Any:
38
38
  if isinstance(config, MutableSequence):
39
39
  if isinstance(config, ListConfig):
@@ -60,7 +60,7 @@ def create_nevergrad_param_from_config(
60
60
  def create_nevergrad_parameter_from_override(override: Override) -> Any:
61
61
  val = override.value()
62
62
  if not override.is_sweep_override():
63
- return val
63
+ return override.get_value_element_as_str()
64
64
  if override.is_choice_sweep():
65
65
  assert isinstance(val, ChoiceSweep)
66
66
  vals = [x for x in override.sweep_iterator(transformer=Transformer.encode)]
@@ -76,7 +76,7 @@ def create_nevergrad_parameter_from_override(override: Override) -> Any:
76
76
  if "log" in val.tags:
77
77
  scalar = ng.p.Log(lower=val.start, upper=val.end)
78
78
  else:
79
- scalar = ng.p.Scalar(lower=val.start, upper=val.end) # type: ignore
79
+ scalar = ng.p.Scalar(lower=val.start, upper=val.end)
80
80
  if isinstance(val.start, int):
81
81
  scalar.set_integer_casting()
82
82
  return scalar
@@ -117,7 +117,6 @@ class NevergradSweeperImpl(Sweeper):
117
117
  )
118
118
 
119
119
  def sweep(self, arguments: List[str]) -> None:
120
-
121
120
  assert self.config is not None
122
121
  assert self.launcher is not None
123
122
  assert self.job_idx is not None
@@ -130,9 +129,9 @@ class NevergradSweeperImpl(Sweeper):
130
129
  parsed = parser.parse_overrides(arguments)
131
130
 
132
131
  for override in parsed:
133
- params[
134
- override.get_key_element()
135
- ] = create_nevergrad_parameter_from_override(override)
132
+ params[override.get_key_element()] = (
133
+ create_nevergrad_parameter_from_override(override)
134
+ )
136
135
 
137
136
  parametrization = ng.p.Dict(**params)
138
137
  parametrization.function.deterministic = not self.opt_config.noisy
@@ -147,7 +146,11 @@ class NevergradSweeperImpl(Sweeper):
147
146
  )
148
147
  log.info(f"with parametrization {parametrization}")
149
148
  log.info(f"Sweep output dir: {self.config.hydra.sweep.dir}")
150
- optimizer = ng.optimizers.registry[opt](parametrization, remaining_budget, nw)
149
+ optimizer = ng.optimizers.registry[opt](
150
+ parametrization=parametrization,
151
+ budget=remaining_budget,
152
+ num_workers=nw,
153
+ )
151
154
  # loop!
152
155
  all_returns: List[Any] = []
153
156
  best: Tuple[float, ng.p.Parameter] = (float("inf"), parametrization)
@@ -35,7 +35,6 @@ class ScalarConfigSpec:
35
35
 
36
36
  @dataclass
37
37
  class OptimConf:
38
-
39
38
  # name of the Nevergrad optimizer to use. Here is a sample:
40
39
  # - "OnePlusOne" extremely simple and robust, especially at low budget, but
41
40
  # tends to converge early.
@@ -74,7 +73,7 @@ class NevergradSweeperConf:
74
73
  )
75
74
 
76
75
  # configuration of the optimizer
77
- optim: OptimConf = OptimConf()
76
+ optim: OptimConf = field(default_factory=OptimConf)
78
77
 
79
78
  # default parametrization of the search space
80
79
  # can be specified:
@@ -11,23 +11,24 @@ setup(
11
11
  author="Jeremy Rapin, Omry Yadan, Jieru Hu",
12
12
  author_email="jrapin@fb.com, omry@fb.com, jieru@fb.com",
13
13
  description="Hydra Nevergrad Sweeper plugin",
14
+ license="MIT",
14
15
  long_description=(Path(__file__).parent / "README.md").read_text(),
15
16
  long_description_content_type="text/markdown",
16
17
  url="https://github.com/facebookresearch/hydra/",
17
18
  packages=find_namespace_packages(include=["hydra_plugins.*"]),
18
19
  classifiers=[
19
- "License :: OSI Approved :: MIT License",
20
- "Programming Language :: Python :: 3.6",
21
- "Programming Language :: Python :: 3.7",
22
- "Programming Language :: Python :: 3.8",
23
- "Programming Language :: Python :: 3.9",
24
20
  "Programming Language :: Python :: 3.10",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Programming Language :: Python :: 3.13",
24
+ "Programming Language :: Python :: 3.14",
25
25
  "Operating System :: OS Independent",
26
26
  "Development Status :: 4 - Beta",
27
27
  ],
28
+ python_requires=">=3.10",
28
29
  install_requires=[
29
30
  "hydra-core>=1.1.0.dev7",
30
- "nevergrad>=0.4.3.post9",
31
+ "nevergrad>=1.0.12",
31
32
  ],
32
33
  include_package_data=True,
33
34
  )
@@ -0,0 +1,200 @@
1
+ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
2
+ import sys
3
+ import warnings
4
+ from pathlib import Path
5
+ from typing import Any
6
+
7
+ import nevergrad as ng
8
+ from hydra.core.override_parser.overrides_parser import OverridesParser
9
+ from hydra.core.plugins import Plugins
10
+ from hydra.plugins.sweeper import Sweeper
11
+ from hydra.test_utils.test_utils import (
12
+ TSweepRunner,
13
+ chdir_plugin_root,
14
+ run_process,
15
+ run_python_script,
16
+ )
17
+ from omegaconf import DictConfig, OmegaConf
18
+ from pytest import mark
19
+
20
+ from hydra_plugins.hydra_nevergrad_sweeper import _impl
21
+ from hydra_plugins.hydra_nevergrad_sweeper.nevergrad_sweeper import NevergradSweeper
22
+
23
+ chdir_plugin_root()
24
+
25
+
26
+ def test_discovery() -> None:
27
+ assert NevergradSweeper.__name__ in [
28
+ x.__name__ for x in Plugins.instance().discover(Sweeper)
29
+ ]
30
+
31
+
32
+ def assert_ng_param_equals(expected: Any, actual: Any) -> None:
33
+ assert type(expected) is type(actual)
34
+ if isinstance(actual, ng.p.Choice) or isinstance(actual, ng.p.TransitionChoice):
35
+ assert sorted(expected.choices.value) == sorted(actual.choices.value)
36
+ elif isinstance(actual, ng.p.Log) or isinstance(actual, ng.p.Scalar):
37
+ assert expected.bounds == actual.bounds
38
+ assert expected.integer == actual.integer
39
+ elif isinstance(actual, str):
40
+ assert expected == actual
41
+ else:
42
+ assert False, f"Unexpected type: {type(actual)}"
43
+
44
+
45
+ def get_scalar_with_integer_bounds(lower: int, upper: int, type: Any) -> ng.p.Scalar:
46
+ scalar = type(lower=lower, upper=upper)
47
+ scalar.set_integer_casting()
48
+ assert isinstance(scalar, ng.p.Scalar)
49
+ return scalar
50
+
51
+
52
+ @mark.parametrize(
53
+ "input, expected",
54
+ [
55
+ ([1, 2, 3], ng.p.Choice([1, 2, 3])),
56
+ (["1", "2", "3"], ng.p.Choice(["1", "2", "3"])),
57
+ ({"lower": 1, "upper": 12, "log": True}, ng.p.Log(lower=1, upper=12)),
58
+ ({"lower": 1, "upper": 12}, ng.p.Scalar(lower=1, upper=12)),
59
+ (
60
+ {"lower": 1, "upper": 12, "integer": True},
61
+ get_scalar_with_integer_bounds(1, 12, ng.p.Scalar),
62
+ ),
63
+ (
64
+ {"lower": 1, "upper": 12, "log": True, "integer": True},
65
+ get_scalar_with_integer_bounds(1, 12, ng.p.Log),
66
+ ),
67
+ ],
68
+ )
69
+ def test_create_nevergrad_parameter_from_config(
70
+ input: Any,
71
+ expected: Any,
72
+ ) -> None:
73
+ actual = _impl.create_nevergrad_param_from_config(input)
74
+ assert_ng_param_equals(expected, actual)
75
+
76
+
77
+ @mark.parametrize(
78
+ "input, expected",
79
+ [
80
+ ("key=choice(1,2)", ng.p.Choice([1, 2])),
81
+ ("key=choice('hello','world')", ng.p.Choice(["hello", "world"])),
82
+ ("key=tag(ordered, choice(1,2,3))", ng.p.TransitionChoice([1, 2, 3])),
83
+ (
84
+ "key=tag(ordered, choice('hello','world', 'nevergrad'))",
85
+ ng.p.TransitionChoice(["hello", "world", "nevergrad"]),
86
+ ),
87
+ ("key=range(1,3)", ng.p.Choice([1, 2])),
88
+ ("key=shuffle(range(1,3))", ng.p.Choice([1, 2])),
89
+ ("key=range(1,5)", ng.p.Choice([1, 2, 3, 4])),
90
+ ("key=float(range(1,5))", ng.p.Choice([1.0, 2.0, 3.0, 4.0])),
91
+ (
92
+ "key=int(interval(1,12))",
93
+ get_scalar_with_integer_bounds(lower=1, upper=12, type=ng.p.Scalar),
94
+ ),
95
+ ("key=tag(log, interval(1,12))", ng.p.Log(lower=1, upper=12)),
96
+ (
97
+ "key=tag(log, int(interval(1,12)))",
98
+ get_scalar_with_integer_bounds(lower=1, upper=12, type=ng.p.Log),
99
+ ),
100
+ ("key=abc", "abc"),
101
+ ("key='a&c'", "'a&c'"),
102
+ ("key='${f:${x}}'", "'${f:${x}}'"),
103
+ (r"key=$\{f\:$\{x\}\}", r"$\{f\:$\{x\}\}"),
104
+ ("key=0", "0"),
105
+ ("key=true", "True"),
106
+ ("key=null", "null"),
107
+ ],
108
+ )
109
+ def test_create_nevergrad_parameter_from_override(
110
+ input: Any,
111
+ expected: Any,
112
+ ) -> None:
113
+ parser = OverridesParser.create()
114
+ parsed = parser.parse_overrides([input])[0]
115
+ param = _impl.create_nevergrad_parameter_from_override(parsed)
116
+ assert_ng_param_equals(param, expected)
117
+
118
+
119
+ def test_launched_jobs(hydra_sweep_runner: TSweepRunner) -> None:
120
+ budget = 8
121
+ sweep = hydra_sweep_runner(
122
+ calling_file=None,
123
+ calling_module="hydra.test_utils.a_module",
124
+ config_path="configs",
125
+ config_name="compose.yaml",
126
+ task_function=None,
127
+ overrides=[
128
+ "hydra/sweeper=nevergrad",
129
+ "hydra/launcher=basic",
130
+ f"hydra.sweeper.optim.budget={budget}", # small budget to test fast
131
+ "hydra.sweeper.optim.num_workers=3",
132
+ "foo=1,2",
133
+ "bar=4:8",
134
+ ],
135
+ )
136
+ with warnings.catch_warnings(): # ignore specific warnings raised by sweep:
137
+ warnings.filterwarnings(
138
+ "ignore", category=ng.common.errors.InefficientSettingsWarning
139
+ )
140
+ warnings.filterwarnings(
141
+ "ignore",
142
+ category=UserWarning,
143
+ message=r"Could not import matplotlib\.pyplot",
144
+ )
145
+ with sweep:
146
+ assert sweep.returns is None
147
+
148
+
149
+ @mark.parametrize("with_commandline", (True, False))
150
+ def test_nevergrad_example(with_commandline: bool, tmpdir: Path) -> None:
151
+ budget = 32 if with_commandline else 1 # make a full test only once (faster)
152
+ cmd = [
153
+ "example/my_app.py",
154
+ "-m",
155
+ "hydra.sweep.dir=" + str(tmpdir),
156
+ "hydra.job.chdir=True",
157
+ f"hydra.sweeper.optim.budget={budget}", # small budget to test fast
158
+ f"hydra.sweeper.optim.num_workers={min(8, budget)}",
159
+ "hydra.sweeper.optim.seed=12", # avoid random failures
160
+ ]
161
+ if with_commandline:
162
+ cmd += [
163
+ "db=mnist,cifar",
164
+ "batch_size=4,8,12,16",
165
+ "lr=tag(log, interval(0.001, 1.0))",
166
+ "dropout=interval(0,1)",
167
+ ]
168
+ run_python_script(cmd)
169
+ returns = OmegaConf.load(f"{tmpdir}/optimization_results.yaml")
170
+ assert isinstance(returns, DictConfig)
171
+ assert returns.name == "nevergrad"
172
+ assert len(returns) == 3
173
+ best_parameters = returns.best_evaluated_params
174
+ assert not best_parameters.dropout.is_integer()
175
+ if budget > 1:
176
+ assert best_parameters.batch_size == 4 # this argument should be easy to find
177
+ # check that all job folders are created
178
+ last_job = max(int(fp.name) for fp in Path(tmpdir).iterdir() if fp.name.isdigit())
179
+ assert last_job == budget - 1
180
+
181
+
182
+ @mark.parametrize("max_failure_rate", (0.5, 1.0))
183
+ def test_failure_rate(max_failure_rate: float, tmpdir: Path) -> None:
184
+ cmd = [
185
+ sys.executable,
186
+ "example/my_app.py",
187
+ "-m",
188
+ f"hydra.sweep.dir={tmpdir}",
189
+ "hydra.sweeper.optim.budget=2", # small budget to test fast
190
+ "hydra.sweeper.optim.num_workers=2",
191
+ f"hydra.sweeper.optim.max_failure_rate={max_failure_rate}",
192
+ "error=true",
193
+ ]
194
+ out, err = run_process(cmd, print_error=False, raise_exception=False)
195
+ assert "Returning infinity for failed experiment" in out
196
+ error_string = "RuntimeError: cfg.error is True"
197
+ if max_failure_rate < 1.0:
198
+ assert error_string in err
199
+ else:
200
+ assert error_string not in err
@@ -1,3 +0,0 @@
1
- global-exclude *.pyc
2
- global-exclude __pycache__
3
- recursive-include hydra_plugins/* *.yaml