def infer_relative_search_space(self, study, trial): # type: (InTrialStudy, FrozenTrial) -> Dict[str, BaseDistribution] search_space = {} for name, distribution in samplers.intersection_search_space(study).items(): if distribution.single(): if not isinstance(distribution, distributions.CategoricalDistribution): # `skopt` cannot handle non-categorical distributions that contain just # a single value, so we skip this distribution. # # Note that `Trial` takes care of this distribution during suggestion. continue search_space[name] = distribution return search_space
def _get_distributions( study: Study, params: Optional[List[str]]) -> Dict[str, BaseDistribution]: _check_evaluate_args(study, params) if params is None: return intersection_search_space(study, ordered_dict=True) # New temporary required to pass mypy. Seems like a bug. params_not_none = params assert params_not_none is not None # Compute the search space based on the subset of trials containing all parameters. distributions = None for trial in study.trials: if trial.state != TrialState.COMPLETE: continue trial_distributions = trial.distributions if not all(name in trial_distributions for name in params_not_none): continue if distributions is None: distributions = dict( filter( lambda name_and_distribution: name_and_distribution[0] in params_not_none, trial_distributions.items(), )) continue if any(trial_distributions[name] != distribution for name, distribution in distributions.items()): raise ValueError( "Parameters importances cannot be assessed with dynamic search spaces if " "parameters are specified. Specified parameters: {}.".format( params)) assert distributions is not None # Required to pass mypy. distributions = OrderedDict( sorted(distributions.items(), key=lambda name_and_distribution: name_and_distribution[0])) return distributions
def test_intersection_search_space() -> None: search_space = IntersectionSearchSpace() study = create_study() # No trial. assert search_space.calculate(study) == {} assert search_space.calculate(study) == intersection_search_space(study) # First trial. study.optimize( lambda t: t.suggest_float("y", -3, 3) + t.suggest_int("x", 0, 10), n_trials=1) assert search_space.calculate(study) == { "x": IntUniformDistribution(low=0, high=10), "y": UniformDistribution(low=-3, high=3), } assert search_space.calculate(study) == intersection_search_space(study) # Returning sorted `OrderedDict` instead of `dict`. assert search_space.calculate(study, ordered_dict=True) == OrderedDict([ ("x", IntUniformDistribution(low=0, high=10)), ("y", UniformDistribution(low=-3, high=3)), ]) assert search_space.calculate( study, ordered_dict=True) == intersection_search_space(study, ordered_dict=True) # Second trial (only 'y' parameter is suggested in this trial). study.optimize(lambda t: t.suggest_float("y", -3, 3), n_trials=1) assert search_space.calculate(study) == { "y": UniformDistribution(low=-3, high=3) } assert search_space.calculate(study) == intersection_search_space(study) # Failed or pruned trials are not considered in the calculation of # an intersection search space. def objective(trial: Trial, exception: Exception) -> float: trial.suggest_float("z", 0, 1) raise exception study.optimize(lambda t: objective(t, RuntimeError()), n_trials=1, catch=(RuntimeError, )) study.optimize(lambda t: objective(t, TrialPruned()), n_trials=1) assert search_space.calculate(study) == { "y": UniformDistribution(low=-3, high=3) } assert search_space.calculate(study) == intersection_search_space(study) # If two parameters have the same name but different distributions, # those are regarded as different parameters. study.optimize(lambda t: t.suggest_float("y", -1, 1), n_trials=1) assert search_space.calculate(study) == {} assert search_space.calculate(study) == intersection_search_space(study) # The search space remains empty once it is empty. study.optimize( lambda t: t.suggest_float("y", -3, 3) + t.suggest_int("x", 0, 10), n_trials=1) assert search_space.calculate(study) == {} assert search_space.calculate(study) == intersection_search_space(study)