mirror of
https://github.com/wassname/ray.git
synced 2026-06-29 07:07:00 +08:00
[tune] Add compatibility to nevergrad 0.2.0+ (#4529)
## What do these changes do? This PR prepares for future version 0.2.0 of `nevergrad`, in which each suggestion is a `Candidate` instance having fields `args` and `kwargs` instead of being a `np.ndarray`. The proposed changes are compatible with all versions of `nevergrad` (manually tested with `nevergrad_example.py` on both `master` and current version `v0.1.6`). See `nevergrad`'s [CHANGELOG](https://github.com/facebookresearch/nevergrad/blob/master/CHANGELOG.md) for more information on the change. ## Related issue number None ## Linter - [x] I've run `scripts/format.sh` to lint the changes in this PR.
This commit is contained in:
@@ -42,9 +42,18 @@ if __name__ == "__main__":
|
||||
"timesteps_total": 100
|
||||
}
|
||||
}
|
||||
optimizer = optimizerlib.OnePlusOne(dimension=2)
|
||||
instrumentation = 2
|
||||
parameter_names = ["height", "width"]
|
||||
# With nevergrad v0.2.0+ the following is also possible:
|
||||
# from nevergrad import instrumentation as inst
|
||||
# instrumentation = inst.Instrumentation(
|
||||
# height=inst.var.Array(1).bounded(0, 200).asfloat(),
|
||||
# width=inst.var.OrderedDiscrete([0, 10, 20, 30, 40, 50]))
|
||||
# parameter_names = None # names are provided by the instrumentation
|
||||
optimizer = optimizerlib.OnePlusOne(instrumentation)
|
||||
algo = NevergradSearch(
|
||||
optimizer, ["height", "width"],
|
||||
optimizer,
|
||||
parameter_names,
|
||||
max_concurrent=4,
|
||||
reward_attr="neg_mean_loss")
|
||||
scheduler = AsyncHyperBandScheduler(reward_attr="neg_mean_loss")
|
||||
|
||||
@@ -23,7 +23,9 @@ class NevergradSearch(SuggestionAlgorithm):
|
||||
optimizer (nevergrad.optimization.Optimizer): Optimizer provided
|
||||
from Nevergrad.
|
||||
parameter_names (list): List of parameter names. Should match
|
||||
the dimension of the optimizer output.
|
||||
the dimension of the optimizer output. Alternatively, set to None
|
||||
if the optimizer is already instrumented with kwargs
|
||||
(see nevergrad v0.2.0+).
|
||||
max_concurrent (int): Number of maximum concurrent trials. Defaults
|
||||
to 10.
|
||||
reward_attr (str): The training result objective value attribute.
|
||||
@@ -31,9 +33,24 @@ class NevergradSearch(SuggestionAlgorithm):
|
||||
|
||||
Example:
|
||||
>>> from nevergrad.optimization import optimizerlib
|
||||
>>> optimizer = optimizerlib.OnePlusOne(dimension=1, budget=100)
|
||||
>>> algo = NevergradSearch(
|
||||
>>> optimizer, max_concurrent=4, reward_attr="neg_mean_loss")
|
||||
>>> instrumentation = 1
|
||||
>>> optimizer = optimizerlib.OnePlusOne(instrumentation, budget=100)
|
||||
>>> algo = NevergradSearch(optimizer, ["lr"], max_concurrent=4,
|
||||
>>> reward_attr="neg_mean_loss")
|
||||
|
||||
Note:
|
||||
In nevergrad v0.2.0+, optimizers can be instrumented.
|
||||
For instance, the following will specifies searching
|
||||
for "lr" from 1 to 2.
|
||||
|
||||
>>> from nevergrad.optimization import optimizerlib
|
||||
>>> from nevergrad import instrumentation as inst
|
||||
>>> lr = inst.var.Array(1).bounded(1, 2).asfloat()
|
||||
>>> instrumentation = inst.Instrumentation(lr=lr)
|
||||
>>> optimizer = optimizerlib.OnePlusOne(instrumentation, budget=100)
|
||||
>>> algo = NevergradSearch(optimizer, None, max_concurrent=4,
|
||||
>>> reward_attr="neg_mean_loss")
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -50,12 +67,40 @@ class NevergradSearch(SuggestionAlgorithm):
|
||||
self._nevergrad_opt = optimizer
|
||||
self._live_trial_mapping = {}
|
||||
super(NevergradSearch, self).__init__(**kwargs)
|
||||
# validate parameters
|
||||
if hasattr(optimizer, "instrumentation"): # added in v0.2.0
|
||||
if optimizer.instrumentation.kwargs:
|
||||
if optimizer.instrumentation.args:
|
||||
raise ValueError(
|
||||
"Instrumented optimizers should use kwargs only")
|
||||
if parameter_names is not None:
|
||||
raise ValueError("Instrumented optimizers should provide "
|
||||
"None as parameter_names")
|
||||
else:
|
||||
if parameter_names is None:
|
||||
raise ValueError("Non-instrumented optimizers should have "
|
||||
"a list of parameter_names")
|
||||
if len(optimizer.instrumentation.args) != 1:
|
||||
raise ValueError(
|
||||
"Instrumented optimizers should use kwargs only")
|
||||
if parameter_names is not None and optimizer.dimension != len(
|
||||
parameter_names):
|
||||
raise ValueError("len(parameters_names) must match optimizer "
|
||||
"dimension for non-instrumented optimizers")
|
||||
|
||||
def _suggest(self, trial_id):
|
||||
if self._num_live_trials() >= self._max_concurrent:
|
||||
return None
|
||||
suggested_config = self._nevergrad_opt.ask()
|
||||
self._live_trial_mapping[trial_id] = suggested_config
|
||||
# in v0.2.0+, output of ask() is a Candidate,
|
||||
# with fields args and kwargs
|
||||
if hasattr(self._nevergrad_opt, "instrumentation"):
|
||||
if not suggested_config.kwargs:
|
||||
return dict(zip(self._parameters, suggested_config.args[0]))
|
||||
else:
|
||||
return suggested_config.kwargs
|
||||
# legacy: output of ask() is a np.ndarray
|
||||
return dict(zip(self._parameters, suggested_config))
|
||||
|
||||
def on_trial_result(self, trial_id, result):
|
||||
|
||||
Reference in New Issue
Block a user