[tune] Handle infinite and NaN values (#11835)

This commit is contained in:
Kai Fricke
2020-11-09 11:18:31 -08:00
committed by GitHub
parent 904f48ebd9
commit 88be1ea20b
9 changed files with 275 additions and 12 deletions
+180
View File
@@ -0,0 +1,180 @@
import unittest
import numpy as np
import ray
from ray import tune
def _invalid_objective(config):
# DragonFly uses `point`
metric = "point" if "point" in config else "report"
if config[metric] > 4:
tune.report(float("inf"))
elif config[metric] > 3:
tune.report(float("-inf"))
elif config[metric] > 2:
tune.report(np.nan)
else:
tune.report(float(config[metric]) or 0.1)
class InvalidValuesTest(unittest.TestCase):
def setUp(self):
self.config = {"report": tune.uniform(0.0, 5.0)}
def tearDown(self):
pass
@classmethod
def setUpClass(cls):
ray.init(num_cpus=4, num_gpus=0, include_dashboard=False)
@classmethod
def tearDownClass(cls):
ray.shutdown()
def testBayesOpt(self):
from ray.tune.suggest.bayesopt import BayesOptSearch
np.random.seed(1234) # At least one nan, inf, -inf and float
out = tune.run(
_invalid_objective,
search_alg=BayesOptSearch(),
config=self.config,
metric="_metric",
mode="max",
num_samples=8,
reuse_actors=False)
best_trial = out.best_trial
self.assertLessEqual(best_trial.config["report"], 2.0)
def testBOHB(self):
from ray.tune.suggest.bohb import TuneBOHB
converted_config = TuneBOHB.convert_search_space(self.config)
converted_config.seed(1000) # At least one nan, inf, -inf and float
out = tune.run(
_invalid_objective,
search_alg=TuneBOHB(
space=converted_config, metric="_metric", mode="max"),
metric="_metric",
mode="max",
num_samples=8,
reuse_actors=False)
best_trial = out.best_trial
self.assertLessEqual(best_trial.config["report"], 2.0)
def testDragonfly(self):
from ray.tune.suggest.dragonfly import DragonflySearch
np.random.seed(1000) # At least one nan, inf, -inf and float
out = tune.run(
_invalid_objective,
search_alg=DragonflySearch(domain="euclidean", optimizer="random"),
config=self.config,
metric="_metric",
mode="max",
num_samples=8,
reuse_actors=False)
best_trial = out.best_trial
self.assertLessEqual(best_trial.config["point"], 2.0)
def testHyperopt(self):
from ray.tune.suggest.hyperopt import HyperOptSearch
out = tune.run(
_invalid_objective,
# At least one nan, inf, -inf and float
search_alg=HyperOptSearch(random_state_seed=1234),
config=self.config,
metric="_metric",
mode="max",
num_samples=8,
reuse_actors=False)
best_trial = out.best_trial
self.assertLessEqual(best_trial.config["report"], 2.0)
def testNevergrad(self):
from ray.tune.suggest.nevergrad import NevergradSearch
import nevergrad as ng
np.random.seed(2020) # At least one nan, inf, -inf and float
out = tune.run(
_invalid_objective,
search_alg=NevergradSearch(optimizer=ng.optimizers.RandomSearch),
config=self.config,
metric="_metric",
mode="max",
num_samples=16,
reuse_actors=False)
best_trial = out.best_trial
self.assertLessEqual(best_trial.config["report"], 2.0)
def testOptuna(self):
from ray.tune.suggest.optuna import OptunaSearch
from optuna.samplers import RandomSampler
np.random.seed(1000) # At least one nan, inf, -inf and float
out = tune.run(
_invalid_objective,
search_alg=OptunaSearch(sampler=RandomSampler(seed=1234)),
config=self.config,
metric="_metric",
mode="max",
num_samples=8,
reuse_actors=False)
best_trial = out.best_trial
self.assertLessEqual(best_trial.config["report"], 2.0)
def testSkopt(self):
from ray.tune.suggest.skopt import SkOptSearch
np.random.seed(1234) # At least one nan, inf, -inf and float
out = tune.run(
_invalid_objective,
search_alg=SkOptSearch(),
config=self.config,
metric="_metric",
mode="max",
num_samples=8,
reuse_actors=False)
best_trial = out.best_trial
self.assertLessEqual(best_trial.config["report"], 2.0)
def testZOOpt(self):
from ray.tune.suggest.zoopt import ZOOptSearch
np.random.seed(1000) # At least one nan, inf, -inf and float
out = tune.run(
_invalid_objective,
search_alg=ZOOptSearch(budget=100, parallel_num=4),
config=self.config,
metric="_metric",
mode="max",
num_samples=8,
reuse_actors=False)
best_trial = out.best_trial
self.assertLessEqual(best_trial.config["report"], 2.0)
if __name__ == "__main__":
import pytest
import sys
sys.exit(pytest.main(["-v", __file__]))
@@ -1836,6 +1836,21 @@ class AsyncHyperBandSuite(unittest.TestCase):
TrialScheduler.CONTINUE)
return t1, t2
def nanInfSetup(self, scheduler, runner=None):
t1 = Trial("PPO")
t2 = Trial("PPO")
t3 = Trial("PPO")
scheduler.on_trial_add(runner, t1)
scheduler.on_trial_add(runner, t2)
scheduler.on_trial_add(runner, t3)
for i in range(10):
scheduler.on_trial_result(runner, t1, result(i, np.nan))
for i in range(10):
scheduler.on_trial_result(runner, t2, result(i, float("inf")))
for i in range(10):
scheduler.on_trial_result(runner, t3, result(i, float("-inf")))
return t1, t2, t3
def testAsyncHBOnComplete(self):
scheduler = AsyncHyperBandScheduler(
metric="episode_reward_mean", mode="max", max_t=10, brackets=1)
@@ -1921,6 +1936,41 @@ class AsyncHyperBandSuite(unittest.TestCase):
scheduler.on_trial_result(None, t3, result(2, 260)),
TrialScheduler.STOP)
def testMedianStoppingNanInf(self):
scheduler = MedianStoppingRule(
metric="episode_reward_mean", mode="max")
t1, t2, t3 = self.nanInfSetup(scheduler)
scheduler.on_trial_complete(None, t1, result(10, np.nan))
scheduler.on_trial_complete(None, t2, result(10, float("inf")))
scheduler.on_trial_complete(None, t3, result(10, float("-inf")))
def testHyperbandNanInf(self):
scheduler = HyperBandScheduler(
metric="episode_reward_mean", mode="max")
t1, t2, t3 = self.nanInfSetup(scheduler)
scheduler.on_trial_complete(None, t1, result(10, np.nan))
scheduler.on_trial_complete(None, t2, result(10, float("inf")))
scheduler.on_trial_complete(None, t3, result(10, float("-inf")))
def testBOHBNanInf(self):
scheduler = HyperBandForBOHB(metric="episode_reward_mean", mode="max")
runner = _MockTrialRunner(scheduler)
runner._search_alg = MagicMock()
runner._search_alg.searcher = MagicMock()
t1, t2, t3 = self.nanInfSetup(scheduler, runner)
# skip trial complete in this mock setting
def testPBTNanInf(self):
scheduler = PopulationBasedTraining(
metric="episode_reward_mean", mode="max")
t1, t2, t3 = self.nanInfSetup(scheduler)
scheduler.on_trial_complete(None, t1, result(10, np.nan))
scheduler.on_trial_complete(None, t2, result(10, float("inf")))
scheduler.on_trial_complete(None, t3, result(10, float("-inf")))
def _test_metrics(self, result_func, metric, mode):
scheduler = AsyncHyperBandScheduler(
grace_period=1,