[Tune]Add integer loguniform support (#12994)

* Add integer quantization and loguniform support

* Fix hyperopt qloguniform not being np.log'd first

* Add tests, __init__

* Try to fix tests, better exceptions

* Tweak docstrings

* Type checks in SearchSpaceTest

* Update docs

* Lint, tests

* Update doc/source/tune/api_docs/search_space.rst

Co-authored-by: Kai Fricke <krfricke@users.noreply.github.com>

Co-authored-by: Kai Fricke <krfricke@users.noreply.github.com>
This commit is contained in:
Antoni Baum
2020-12-23 18:27:16 +01:00
committed by GitHub
parent d37e2c3a20
commit a4f2dd2138
8 changed files with 147 additions and 40 deletions
+9 -1
View File
@@ -281,7 +281,15 @@ class TuneBOHB(Searcher):
log=False)
elif isinstance(domain, Integer):
if isinstance(sampler, Uniform):
if isinstance(sampler, LogUniform):
lower = domain.lower
upper = domain.upper
if quantize:
lower = math.ceil(domain.lower / quantize) * quantize
upper = math.floor(domain.upper / quantize) * quantize
return ConfigSpace.UniformIntegerHyperparameter(
par, lower=lower, upper=upper, q=quantize, log=True)
elif isinstance(sampler, Uniform):
lower = domain.lower
upper = domain.upper
if quantize:
+17 -7
View File
@@ -400,8 +400,9 @@ class HyperOptSearch(Searcher):
if isinstance(domain, Float):
if isinstance(sampler, LogUniform):
if quantize:
return hpo.hp.qloguniform(par, domain.lower,
domain.upper, quantize)
return hpo.hp.qloguniform(par, np.log(domain.lower),
np.log(domain.upper),
quantize)
return hpo.hp.loguniform(par, np.log(domain.lower),
np.log(domain.upper))
elif isinstance(sampler, Uniform):
@@ -416,12 +417,21 @@ class HyperOptSearch(Searcher):
return hpo.hp.normal(par, sampler.mean, sampler.sd)
elif isinstance(domain, Integer):
if isinstance(sampler, Uniform):
if isinstance(sampler, LogUniform):
if quantize:
logger.warning(
"HyperOpt does not support quantization for "
"integer values. Reverting back to 'randint'.")
return hpo.hp.randint(par, domain.lower, high=domain.upper)
return hpo.base.pyll.scope.int(
hpo.hp.qloguniform(par, np.log(domain.lower),
np.log(domain.upper), quantize))
return hpo.base.pyll.scope.int(
hpo.hp.qloguniform(par, np.log(domain.lower),
np.log(domain.upper), 1.0))
elif isinstance(sampler, Uniform):
if quantize:
return hpo.base.pyll.scope.int(
hpo.hp.quniform(par, domain.lower, domain.upper,
quantize))
return hpo.hp.uniformint(
par, domain.lower, high=domain.upper)
elif isinstance(domain, Categorical):
if isinstance(sampler, Uniform):
return hpo.hp.choice(par, [
+11 -4
View File
@@ -310,16 +310,23 @@ class NevergradSearch(Searcher):
exponent=sampler.base)
return ng.p.Scalar(lower=domain.lower, upper=domain.upper)
if isinstance(domain, Integer):
elif isinstance(domain, Integer):
if isinstance(sampler, LogUniform):
return ng.p.Log(
lower=domain.lower,
upper=domain.upper,
exponent=sampler.base).set_integer_casting()
return ng.p.Scalar(
lower=domain.lower,
upper=domain.upper).set_integer_casting()
if isinstance(domain, Categorical):
elif isinstance(domain, Categorical):
return ng.p.Choice(choices=domain.categories)
raise ValueError("SkOpt does not support parameters of type "
"`{}`".format(type(domain).__name__))
raise ValueError("Nevergrad does not support parameters of type "
"`{}` with samplers of type `{}`".format(
type(domain).__name__,
type(domain.sampler).__name__))
# Parameter name is e.g. "a/b/c" for nested dicts
space = {
+17 -14
View File
@@ -4,7 +4,8 @@ import pickle
from typing import Dict, List, Optional, Tuple, Union
from ray.tune.result import DEFAULT_METRIC
from ray.tune.sample import Categorical, Domain, Float, Integer, Quantized
from ray.tune.sample import Categorical, Domain, Float, Integer, Quantized, \
LogUniform
from ray.tune.suggest.suggestion import UNRESOLVED_SEARCH_SPACE, \
UNDEFINED_METRIC_MODE, UNDEFINED_SEARCH_SPACE
from ray.tune.suggest.variant_generator import parse_spec_vars
@@ -334,24 +335,26 @@ class SkOptSearch(Searcher):
sampler = sampler.get_sampler()
if isinstance(domain, Float):
if domain.sampler is not None:
logger.warning(
"SkOpt does not support specific sampling methods."
" The {} sampler will be dropped.".format(sampler))
return domain.lower, domain.upper
if isinstance(domain.sampler, LogUniform):
return sko.space.Real(
domain.lower, domain.upper, prior="log-uniform")
return sko.space.Real(
domain.lower, domain.upper, prior="uniform")
if isinstance(domain, Integer):
if domain.sampler is not None:
logger.warning(
"SkOpt does not support specific sampling methods."
" The {} sampler will be dropped.".format(sampler))
return domain.lower, domain.upper
elif isinstance(domain, Integer):
if isinstance(domain.sampler, LogUniform):
return sko.space.Integer(
domain.lower, domain.upper, prior="log-uniform")
return sko.space.Integer(
domain.lower, domain.upper, prior="uniform")
if isinstance(domain, Categorical):
elif isinstance(domain, Categorical):
return domain.categories
raise ValueError("SkOpt does not support parameters of type "
"`{}`".format(type(domain).__name__))
"`{}` with samplers of type `{}`".format(
type(domain).__name__,
type(domain.sampler).__name__))
# Parameter name is e.g. "a/b/c" for nested dicts
space = {