Exemplo n.º 1
0
    def create_trials(losses, statuses, vals, scope_keys):
        trials = Trials()

        tids = trials.new_trial_ids(len(losses))
        specs = [None for x in range(len(tids))]
        results = []
        miscs = []
        for i in range(len(tids)):
            idxs_content = [[i] for key in scope_keys]
            idxs_vals_content = []
            for key in scope_keys:
                idxs_vals_content.append([vals[key][i]])

            results.append(dict(loss=losses[i], status=statuses[i]))
            miscs.append(
                dict(tid=tids[i],
                     cmd=None,
                     idxs=dict(zip(scope_keys, idxs_content)),
                     vals=dict(zip(scope_keys, idxs_vals_content))))

        trials.insert_trial_docs(
            trials.new_trial_docs(
                tids,
                specs,
                results,
                miscs,
            ))
        trials.refresh()
        return trials
Exemplo n.º 2
0
class OptExecutorHyperopt(OptExecutor):
    HYP_ALGO_RAND = "rand"
    HYP_ALGO_ANNEAL = "anneal"
    HYP_ALGO_TPE = "tpe"
    HYP_ALGO_MIX = "mix"

    HYP_OUT_RESULT = "result"
    HYP_OUT_STATUS = "status"
    HYP_OUT_MISC = "misc"
    HYP_OUT_VALS = "vals"

    def __init__(self, json_loaded):
        super().__init__(json_loaded)
        self.trials = Trials()

        if COMMON_SEED in json_loaded.keys():
            self.set_randomseed(json_loaded[COMMON_SEED])

        scope_params = json_loaded[COMMON_SCOPE]
        scope_keys = [
            x for scope_list in scope_params for x in scope_list.keys()
        ]
        space = []
        for i, key in enumerate(scope_keys):
            try:
                #  List先頭を抜いて*listで可変長引数渡し
                # space.append(getattr(hp, v[0])(k, v[1], v[2]))
                #  2018/01 多重層空間定義には対応していない
                method_name = scope_params[i][key][0]
                method_args = scope_params[i][key][1:]
                space.append(getattr(hp, method_name)(key, *method_args))
            except AttributeError:
                print('error occurred [{}] on space creation.'.format(key))

        # space = [
        #             hp.uniform('x', -5, 5),
        #             hp.uniform('y', -5, 5),
        #         ]
        self.domain = Domain(None, space, None, pass_expr_memo_ctrl=False)
        if COMMON_RESULTS in json_loaded:
            losses = json_loaded[COMMON_RESULTS][COMMON_LOSSES]
            statuses = json_loaded[COMMON_RESULTS][COMMON_STATUSES]
            vals = json_loaded[COMMON_RESULTS][COMMON_VALS]
            self.trials = self.create_trials(losses, statuses, vals,
                                             scope_keys)

    @staticmethod
    def create_trials(losses, statuses, vals, scope_keys):
        trials = Trials()

        tids = trials.new_trial_ids(len(losses))
        specs = [None for x in range(len(tids))]
        results = []
        miscs = []
        for i in range(len(tids)):
            idxs_content = [[i] for key in scope_keys]
            idxs_vals_content = []
            for key in scope_keys:
                idxs_vals_content.append([vals[key][i]])

            results.append(dict(loss=losses[i], status=statuses[i]))
            miscs.append(
                dict(tid=tids[i],
                     cmd=None,
                     idxs=dict(zip(scope_keys, idxs_content)),
                     vals=dict(zip(scope_keys, idxs_vals_content))))

        trials.insert_trial_docs(
            trials.new_trial_docs(
                tids,
                specs,
                results,
                miscs,
            ))
        trials.refresh()
        return trials

    @stop_watch_add
    def suggest(self):
        """Return the next parameter suggestion

        >>> import json
        >>> json_str='{"seed":0,"lib":"hyperopt","algo":"tpe","scope":{"x":["uniform",-10,10],"y":["uniform",-10,10]},'
        >>> json_str+='"max_evals":1,'
        >>> json_str+='"results":{"losses":[3.4620,3.192,28.963,19.64,20.458],'
        >>> json_str+='"statuses":["ok","ok","ok","ok","ok"],'
        >>> json_str+='"vals":{"y":[-0.16774,0.3122,-2.416,0.27455,-3.2827],'
        >>> json_str+='"x":[1.857,1.760,4.785,-4.498,2.837]}}}'
        >>> exec=ExecutorFactory.get_executor(json_str)
        >>> reval=json.loads(exec.suggest())

        >>> reval["alog"] == 'tpe'
        True
        >>> reval["scope"]["x"][0] == 4.30378732744839
        True
        >>> reval["scope"]["y"][0] == 0.9762700785464951
        True
        """
        _logger = getLogger(__name__)

        id_qnt = int(self.json_loaded[COMMON_MAXEVALS])
        additional_args = []
        executed_alog = self.json_loaded[COMMON_ALGO]
        if executed_alog == self.HYP_ALGO_TPE:
            algo = tpe.suggest
            id_qnt = 1
            additional_args.append(tpe._default_prior_weight)
            additional_args.append(5)  # n_startup_jobs
        elif executed_alog == self.HYP_ALGO_ANNEAL:
            algo = anneal.suggest
        elif executed_alog == self.HYP_ALGO_RAND:
            algo = rand.suggest
        elif executed_alog == self.HYP_ALGO_MIX:
            algo = partial(mix.suggest,
                           p_suggest=[
                               (.1, rand.suggest),
                               (.2, anneal.suggest),
                               (.7, tpe.suggest),
                           ])
        else:
            _logger.warning('unknown algo define. use tpe')
            algo = tpe.suggest

        new_ids = self.trials.new_trial_ids(id_qnt)
        args = [new_ids, self.domain, self.trials, self.rand_seed
                ] + additional_args
        rval_docs = algo(*args)

        statuses = []
        vals = {}
        for i in range(len(new_ids)):
            statuses.append(
                rval_docs[i][self.HYP_OUT_RESULT][self.HYP_OUT_STATUS])
            vals = self.merge_dict_valuelist(
                vals, rval_docs[i][self.HYP_OUT_MISC][self.HYP_OUT_VALS])

        results = dict(algo=executed_alog, statuses=statuses, vals=vals)

        return results
Exemplo n.º 3
0
class _HyperOpt(base.Optimizer):
    # pylint: disable=too-many-instance-attributes
    def __init__(
        self,
        parametrization: IntOrParameter,
        budget: tp.Optional[int] = None,
        num_workers: int = 1,
        *,
        prior_weight: float = 1.0,
        n_startup_jobs: int = 20,
        n_EI_candidates: int = 24,
        gamma: float = 0.25,
        verbose: bool = False,
    ) -> None:
        super().__init__(parametrization,
                         budget=budget,
                         num_workers=num_workers)
        try:
            # try to convert parametrization to hyperopt search space
            if not isinstance(self.parametrization, p.Instrumentation):
                raise NotImplementedError
            self.space = _get_search_space(self.parametrization.name,
                                           self.parametrization)
            self._transform = None
        except NotImplementedError:
            self._transform = transforms.ArctanBound(0, 1)
            self.space = {
                f"x_{i}": hp.uniform(f"x_{i}", 0, 1)
                for i in range(self.dimension)
            }

        self.trials = Trials()
        self.domain = Domain(fn=None,
                             expr=self.space,
                             pass_expr_memo_ctrl=False)
        self.tpe_args = {
            "prior_weight": prior_weight,
            "n_startup_jobs": n_startup_jobs,
            "n_EI_candidates": n_EI_candidates,
            "gamma": gamma,
            "verbose": verbose,
        }

    def _internal_ask_candidate(self) -> p.Parameter:
        # Inspired from FMinIter class (hyperopt)
        next_id = self.trials.new_trial_ids(1)
        new_trial = tpe.suggest(next_id, self.domain, self.trials,
                                self._rng.randint(2**31 - 1),
                                **self.tpe_args)[0]
        self.trials.insert_trial_doc(new_trial)
        self.trials.refresh()

        candidate = self.parametrization.spawn_child()

        if self._transform:
            data = np.array([
                new_trial["misc"]["vals"][f"x_{i}"][0]
                for i in range(self.dimension)
            ])
            candidate = candidate.set_standardized_data(
                self._transform.backward(data))

            # For consistency, we need to update hyperopt history
            # when standardized data is changed
            if any(data != self._transform.forward(
                    candidate.get_standardized_data(
                        reference=self.parametrization))):
                for it, val in enumerate(
                        self._transform.forward(
                            candidate.get_standardized_data(
                                reference=self.parametrization))):
                    self.trials._dynamic_trials[
                        next_id[0]]["misc"]["vals"][f"x_{it}"][0] = val
        else:
            spec = hyperopt.base.spec_from_misc(new_trial["misc"])
            config = hyperopt.space_eval(self.space, spec)
            candidate.value = _hp_dict_to_parametrization(config)

        candidate._meta["trial_id"] = new_trial["tid"]
        return candidate

    def _internal_tell_candidate(self, candidate: p.Parameter,
                                 loss: float) -> None:
        result = {"loss": loss, "status": "ok"}
        assert "trial_id" in candidate._meta
        tid = candidate._meta["trial_id"]
        assert self.trials._dynamic_trials[tid][
            "state"] == hyperopt.JOB_STATE_NEW

        now = hyperopt.utils.coarse_utcnow()
        self.trials._dynamic_trials[tid]["book_time"] = now
        self.trials._dynamic_trials[tid]["refresh_time"] = now
        self.trials._dynamic_trials[tid]["state"] = hyperopt.JOB_STATE_DONE
        self.trials._dynamic_trials[tid]["result"] = result
        self.trials._dynamic_trials[tid][
            "refresh_time"] = hyperopt.utils.coarse_utcnow()
        self.trials.refresh()

    def _internal_tell_not_asked(self, candidate: p.Parameter,
                                 loss: float) -> None:
        next_id = self.trials.new_trial_ids(1)
        new_trial = hyperopt.rand.suggest(next_id, self.domain, self.trials,
                                          self._rng.randint(2**31 - 1))
        self.trials.insert_trial_docs(new_trial)
        self.trials.refresh()
        tid = next_id[0]

        if self._transform:
            data = candidate.get_standardized_data(
                reference=self.parametrization)
            data = self._transform.forward(data)
            self.trials._dynamic_trials[tid]["misc"]["vals"] = {
                f"x_{i}": [data[i]]
                for i in range(len(data))
            }
        else:
            null_config: dict = {
                k: []
                for k in self.trials._dynamic_trials[tid]["misc"]
                ["vals"].keys()
            }
            new_vals: dict = _hp_parametrization_to_dict(candidate,
                                                         default=null_config)
            self.trials._dynamic_trials[tid]["misc"]["vals"] = new_vals

        self.trials.refresh()
        candidate._meta["trial_id"] = tid
        self._internal_tell_candidate(candidate, loss)