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
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
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)