[tune] Add Nevergrad to Tune (#3985)

This commit is contained in:
Adi Zimmerman
2019-02-12 11:00:04 -08:00
committed by Richard Liaw
parent c523bc04ad
commit dac1969647
7 changed files with 183 additions and 2 deletions
@@ -0,0 +1,56 @@
"""This test checks that Nevergrad is functional.
It also checks that it is usable with a separate scheduler.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import ray
from ray.tune import run_experiments, register_trainable
from ray.tune.schedulers import AsyncHyperBandScheduler
from ray.tune.suggest import NevergradSearch
def easy_objective(config, reporter):
import time
time.sleep(0.2)
for i in range(config["iterations"]):
reporter(
timesteps_total=i,
neg_mean_loss=-(config["height"] - 14)**2 +
abs(config["width"] - 3))
time.sleep(0.02)
if __name__ == '__main__':
import argparse
from nevergrad.optimization import optimizerlib
parser = argparse.ArgumentParser()
parser.add_argument(
"--smoke-test", action="store_true", help="Finish quickly for testing")
args, _ = parser.parse_known_args()
ray.init(redirect_output=True)
register_trainable("exp", easy_objective)
config = {
"nevergrad": {
"run": "exp",
"num_samples": 10 if args.smoke_test else 50,
"config": {
"iterations": 100,
},
"stop": {
"timesteps_total": 100
},
}
}
optimizer = optimizerlib.OnePlusOne(dimension=2)
algo = NevergradSearch(
optimizer, ["height", "width"],
max_concurrent=4,
reward_attr="neg_mean_loss")
scheduler = AsyncHyperBandScheduler(reward_attr="neg_mean_loss")
run_experiments(config, search_alg=algo, scheduler=scheduler)
+2
View File
@@ -3,6 +3,7 @@ from ray.tune.suggest.basic_variant import BasicVariantGenerator
from ray.tune.suggest.suggestion import SuggestionAlgorithm
from ray.tune.suggest.bayesopt import BayesOptSearch
from ray.tune.suggest.hyperopt import HyperOptSearch
from ray.tune.suggest.nevergrad import NevergradSearch
from ray.tune.suggest.skopt import SkOptSearch
from ray.tune.suggest.sigopt import SigOptSearch
from ray.tune.suggest.variant_generator import grid_search, function, \
@@ -13,6 +14,7 @@ __all__ = [
"BasicVariantGenerator",
"BayesOptSearch",
"HyperOptSearch",
"NevergradSearch",
"SkOptSearch",
"SigOptSearch",
"SuggestionAlgorithm",
+89
View File
@@ -0,0 +1,89 @@
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
try:
import nevergrad
except Exception:
nevergrad = None
from ray.tune.suggest.suggestion import SuggestionAlgorithm
class NevergradSearch(SuggestionAlgorithm):
"""A wrapper around Nevergrad to provide trial suggestions.
Requires Nevergrad to be installed.
Nevergrad is an open source tool from Facebook for derivative free
optimization of parameters and/or hyperparameters. It features a wide
range of optimizers in a standard ask and tell interface. More information
can be found at https://github.com/facebookresearch/nevergrad.
Parameters:
optimizer (nevergrad.optimization.Optimizer): Optimizer provided
from Nevergrad.
parameter_names (list): List of parameter names. Should match
the dimension of the optimizer output.
max_concurrent (int): Number of maximum concurrent trials. Defaults
to 10.
reward_attr (str): The training result objective value attribute.
This refers to an increasing value.
Example:
>>> from nevergrad.optimization import optimizerlib
>>> optimizer = optimizerlib.OnePlusOne(dimension=1, budget=100)
>>> config = {
>>> "my_exp": {
>>> "run": "exp",
>>> "num_samples": 10,
>>> "stop": {
>>> "training_iteration": 100
>>> },
>>> }
>>> }
>>> algo = NevergradSearch(
>>> optimizer, max_concurrent=4, reward_attr="neg_mean_loss")
"""
def __init__(self,
optimizer,
parameter_names,
max_concurrent=10,
reward_attr="episode_reward_mean",
**kwargs):
assert nevergrad is not None, "Nevergrad must be installed!"
assert type(max_concurrent) is int and max_concurrent > 0
self._max_concurrent = max_concurrent
self._parameters = parameter_names
self._reward_attr = reward_attr
self._nevergrad_opt = optimizer
self._live_trial_mapping = {}
super(NevergradSearch, self).__init__(**kwargs)
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
return dict(zip(self._parameters, suggested_config))
def on_trial_result(self, trial_id, result):
pass
def on_trial_complete(self,
trial_id,
result=None,
error=False,
early_terminated=False):
"""Passes the result to Nevergrad unless early terminated or errored.
The result is internally negated when interacting with Nevergrad
so that Nevergrad Optimizers can "maximize" this value,
as it minimizes on default.
"""
ng_trial_info = self._live_trial_mapping.pop(trial_id)
if result:
self._nevergrad_opt.tell(ng_trial_info, -result[self._reward_attr])
def _num_live_trials(self):
return len(self._live_trial_mapping)