Code quality improvement based on #275 (#313)

* simplify & restructure

Co-authored-by: Albern S <62778698+albernsrya@users.noreply.github.com>
This commit is contained in:
Chi Wang 2021-11-28 10:14:25 -08:00 committed by GitHub
parent 63f402b29e
commit 2f25a87d98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 49 additions and 63 deletions

View File

@ -202,7 +202,7 @@ def get_output_from_log(filename, time_budget):
def concat(X1, X2): def concat(X1, X2):
"""concatenate two matrices vertically""" """concatenate two matrices vertically"""
if isinstance(X1, DataFrame) or isinstance(X1, Series): if isinstance(X1, (DataFrame, Series)):
df = pd.concat([X1, X2], sort=False) df = pd.concat([X1, X2], sort=False)
df.reset_index(drop=True, inplace=True) df.reset_index(drop=True, inplace=True)
if isinstance(X1, DataFrame): if isinstance(X1, DataFrame):

View File

@ -169,8 +169,7 @@ class FLOW2(Searcher):
if lb > self.step: if lb > self.step:
self.step = lb * 2 self.step = lb * 2
# upper bound # upper bound
if self.step > self.step_ub: self.step = min(self.step, self.step_ub)
self.step = self.step_ub
# maximal # consecutive no improvements # maximal # consecutive no improvements
self.dir = 2 ** (min(9, self.dim)) self.dir = 2 ** (min(9, self.dim))
self._configs = {} # dict from trial_id to (config, stepsize) self._configs = {} # dict from trial_id to (config, stepsize)
@ -233,8 +232,7 @@ class FLOW2(Searcher):
return resource return resource
def rand_vector_gaussian(self, dim, std=1.0): def rand_vector_gaussian(self, dim, std=1.0):
vec = self._random.normal(0, std, dim) return self._random.normal(0, std, dim)
return vec
def complete_config( def complete_config(
self, self,
@ -339,8 +337,7 @@ class FLOW2(Searcher):
if self._K > 0: if self._K > 0:
# self._oldK must have been set when self._K>0 # self._oldK must have been set when self._K>0
self.step *= np.sqrt(self._K / self._oldK) self.step *= np.sqrt(self._K / self._oldK)
if self.step > self.step_ub: self.step = min(self.step, self.step_ub)
self.step = self.step_ub
self._iter_best_config = self.trial_count_complete self._iter_best_config = self.trial_count_complete
if self._trunc: if self._trunc:
self._trunc = min(self._trunc + 1, self.dim) self._trunc = min(self._trunc + 1, self.dim)
@ -366,9 +363,7 @@ class FLOW2(Searcher):
): ):
# check stuck condition if using max resource # check stuck condition if using max resource
self._num_complete4incumbent -= 2 self._num_complete4incumbent -= 2
if self._num_allowed4incumbent < 2: self._num_allowed4incumbent = max(self._num_allowed4incumbent, 2)
self._num_allowed4incumbent = 2
# elif proposed_by: del self._proposed_by[trial_id]
def on_trial_result(self, trial_id: str, result: Dict): def on_trial_result(self, trial_id: str, result: Dict):
"""Early update of incumbent.""" """Early update of incumbent."""
@ -420,16 +415,7 @@ class FLOW2(Searcher):
>= self.cost_incumbent * self.resource_multiple_factor >= self.cost_incumbent * self.resource_multiple_factor
) )
): ):
# consider increasing resource using sum eval cost of complete return self._increase_resource(trial_id)
# configs
old_resource = self._resource
self._resource = self._round(self._resource * self.resource_multiple_factor)
self.cost_incumbent *= self._resource / old_resource
config = self.best_config.copy()
config[self.prune_attr] = self._resource
self._direction_tried = None
self._configs[trial_id] = (config, self.step)
return unflatten_dict(config)
self._num_allowed4incumbent -= 1 self._num_allowed4incumbent -= 1
move = self.incumbent.copy() move = self.incumbent.copy()
if self._direction_tried is not None: if self._direction_tried is not None:
@ -453,24 +439,21 @@ class FLOW2(Searcher):
if self._init_phase: if self._init_phase:
if self._direction_tried is None: if self._direction_tried is None:
if self._same: if self._same:
# check if the new config is different from best_config same = not any(
same = True key not in best_config or value != best_config[key]
for key, value in config.items(): for key, value in config.items()
if key not in best_config or value != best_config[key]: )
same = False
break
if same: if same:
# increase step size # increase step size
self.step += self.STEPSIZE self.step += self.STEPSIZE
if self.step > self.step_ub: self.step = min(self.step, self.step_ub)
self.step = self.step_ub
else: else:
# check if the new config is different from best_config same = not any(
same = True key not in best_config or value != best_config[key]
for key, value in config.items(): for key, value in config.items()
if key not in best_config or value != best_config[key]: )
same = False
break
self._same = same self._same = same
if self._num_proposedby_incumbent == self.dir and ( if self._num_proposedby_incumbent == self.dir and (
not self._resource or self._resource == self.max_resource not self._resource or self._resource == self.max_resource
@ -478,13 +461,12 @@ class FLOW2(Searcher):
# check stuck condition if using max resource # check stuck condition if using max resource
self._num_proposedby_incumbent -= 2 self._num_proposedby_incumbent -= 2
self._init_phase = False self._init_phase = False
if self.step >= self.step_lower_bound: if self.step < self.step_lower_bound:
# decrease step size
self._oldK = self._K if self._K else self._iter_best_config
self._K = self.trial_count_proposed + 1
self.step *= np.sqrt(self._oldK / self._K)
else:
return None return None
# decrease step size
self._oldK = self._K or self._iter_best_config
self._K = self.trial_count_proposed + 1
self.step *= np.sqrt(self._oldK / self._K)
if self._init_phase: if self._init_phase:
return unflatten_dict(config) return unflatten_dict(config)
if self._trunc == 1 and self._direction_tried is not None: if self._trunc == 1 and self._direction_tried is not None:
@ -498,14 +480,24 @@ class FLOW2(Searcher):
config[key] = generated["config"][key] config[key] = generated["config"][key]
return unflatten_dict(config) return unflatten_dict(config)
break break
else: elif len(config) == len(best_config):
# check if config == best_config for key, value in best_config.items():
if len(config) == len(best_config): if value != config[key]:
for key, value in best_config.items(): return unflatten_dict(config)
if value != config[key]: # print('move to', move)
return unflatten_dict(config) self.incumbent = move
# print('move to', move) return unflatten_dict(config)
self.incumbent = move
def _increase_resource(self, trial_id):
# consider increasing resource using sum eval cost of complete
# configs
old_resource = self._resource
self._resource = self._round(self._resource * self.resource_multiple_factor)
self.cost_incumbent *= self._resource / old_resource
config = self.best_config.copy()
config[self.prune_attr] = self._resource
self._direction_tried = None
self._configs[trial_id] = (config, self.step)
return unflatten_dict(config) return unflatten_dict(config)
def _project(self, config): def _project(self, config):
@ -526,10 +518,7 @@ class FLOW2(Searcher):
def config_signature(self, config, space: Dict = None) -> tuple: def config_signature(self, config, space: Dict = None) -> tuple:
"""Return the signature tuple of a config.""" """Return the signature tuple of a config."""
config = flatten_dict(config) config = flatten_dict(config)
if space: space = flatten_dict(space) if space else self._space
space = flatten_dict(space)
else:
space = self._space
value_list = [] value_list = []
# self._space_keys doesn't contain keys with const values, # self._space_keys doesn't contain keys with const values,
# e.g., "eval_metric": ["logloss", "error"]. # e.g., "eval_metric": ["logloss", "error"].
@ -541,17 +530,14 @@ class FLOW2(Searcher):
else: else:
# key must be in space # key must be in space
domain = space[key] domain = space[key]
if self.hierarchical: if self.hierarchical and not (
# can't remove constant for hierarchical search space, domain is None
# e.g., learner or type(domain) in (str, int, float)
if not ( or isinstance(domain, sample.Domain)
domain is None ):
or type(domain) in (str, int, float) # not domain or hashable
or isinstance(domain, sample.Domain) # get rid of list type for hierarchical search space.
): continue
# not domain or hashable
# get rid of list type for hierarchical search space.
continue
if isinstance(domain, sample.Integer): if isinstance(domain, sample.Integer):
value_list.append(int(round(value))) value_list.append(int(round(value)))
else: else: