44from tensorflow .keras .losses import BinaryCrossentropy
55import scipy .stats as sps
66
7- from ..engine import Ledger , minimize_multi_start , is_duplicate
7+ from ..engine import Record , minimize_multi_start
88from ..types import DenseConfigurationSpace , DenseConfiguration
99from ..models import DenseSequential
1010from ..decorators import unbatch , value_and_gradient , numpy_io
@@ -20,19 +20,21 @@ def __init__(self, config_space, eta=3, min_budget=0.01, max_budget=1,
2020 num_restarts = 10 , batch_size = 64 , num_steps_per_iter = 1000 ,
2121 optimizer = "adam" , num_layers = 2 , num_units = 32 ,
2222 activation = "relu" , normalize = True , method = "L-BFGS-B" ,
23- max_iter = 100 , ftol = 1e-2 , distortion = 1e-3 , seed = None , ** kwargs ):
23+ max_iter = 100 , ftol = 1e-2 , distortion = None , seed = None , ** kwargs ):
2424
2525 if gamma is None :
2626 gamma = 1 / eta
2727
2828 cg = RatioEstimator (config_space = config_space , gamma = gamma ,
29- num_random_init = num_random_init , random_rate = random_rate ,
30- num_restarts = num_restarts , batch_size = batch_size ,
29+ num_random_init = num_random_init ,
30+ random_rate = random_rate , num_restarts = num_restarts ,
31+ batch_size = batch_size ,
3132 num_steps_per_iter = num_steps_per_iter ,
3233 optimizer = optimizer , num_layers = num_layers ,
3334 num_units = num_units , activation = activation ,
3435 normalize = normalize , method = method ,
35- max_iter = max_iter , ftol = ftol , distortion = distortion , seed = seed )
36+ max_iter = max_iter , ftol = ftol ,
37+ distortion = distortion , seed = seed )
3638 # (LT): Note this is using the *grandparent* class initializer to
3739 # replace the config_generator!
3840 super (HyperBand , self ).__init__ (config_generator = cg , ** kwargs )
@@ -71,7 +73,7 @@ def __init__(self, config_space, gamma=1/3, num_random_init=10,
7173 random_rate = 0.25 , num_restarts = 3 , batch_size = 64 ,
7274 num_steps_per_iter = 1000 , optimizer = "adam" , num_layers = 2 ,
7375 num_units = 32 , activation = "relu" , normalize = True ,
74- method = "L-BFGS-B" , max_iter = 100 , ftol = 1e-2 , distortion = 1e-3 ,
76+ method = "L-BFGS-B" , max_iter = 100 , ftol = 1e-2 , distortion = None ,
7577 seed = None , ** kwargs ):
7678
7779 super (RatioEstimator , self ).__init__ (** kwargs )
@@ -106,7 +108,7 @@ def __init__(self, config_space, gamma=1/3, num_random_init=10,
106108 self .batch_size = batch_size
107109 self .num_steps_per_iter = num_steps_per_iter
108110
109- self .ledger = Ledger ()
111+ self .record = Record ()
110112
111113 self .seed = seed
112114 self .random_state = np .random .RandomState (seed )
@@ -151,9 +153,9 @@ def loss(x):
151153
152154 def _update_model (self ):
153155
154- X , z = self .ledger .load_classification_data (self .gamma )
156+ X , z = self .record .load_classification_data (self .gamma )
155157
156- dataset_size = self .ledger .size ()
158+ dataset_size = self .record .size ()
157159 steps_per_epoch = self ._get_steps_per_epoch (dataset_size )
158160 num_epochs = self .num_steps_per_iter // steps_per_epoch
159161
@@ -189,8 +191,10 @@ def _get_maximum(self):
189191 f" ({ res .message } )" )
190192
191193 # TODO(LT): Create Enum type for these status codes
192- if (res .status == 0 or res .status == 9 ) and \
193- not is_duplicate (res .x , self .ledger .features ):
194+ # status == 1 signifies maximum iteration reached, which we don't
195+ # want to treat as a failure condition.
196+ if (res .success or res .status == 1 ) and \
197+ not self .record .is_duplicate (res .x ):
194198 # if (res_best is not None) *implies* (res.fun < res_best.fun)
195199 # (i.e. material implication) is logically equivalent to below
196200 if res_best is None or res .fun < res_best .fun :
@@ -200,20 +204,20 @@ def _get_maximum(self):
200204
201205 def get_config (self , budget ):
202206
203- dataset_size = self .ledger .size ()
207+ dataset_size = self .record .size ()
204208
205209 config_random = self .config_space .sample_configuration ()
206210 config_random_dict = config_random .get_dictionary ()
207211
208212 if dataset_size < self .num_random_init :
209213 self .logger .debug (f"Completed { dataset_size } /{ self .num_random_init } "
210- " initial runs. Returning random candidate..." )
214+ " initial runs. Suggesting random candidate..." )
211215 return (config_random_dict , {})
212216
213217 if self .random_state .binomial (p = self .random_rate , n = 1 ):
214218 self .logger .info ("[Glob. maximum: skipped "
215219 f"(prob={ self .random_rate :.2f} )] "
216- "Returning random candidate ..." )
220+ "Suggesting random candidate ..." )
217221 return (config_random_dict , {})
218222
219223 # Update model
@@ -227,11 +231,9 @@ def get_config(self, budget):
227231 self .logger .warn ("[Glob. maximum: not found!] Either optimization "
228232 f"failed in all { self .num_restarts } starts, or "
229233 "all maxima found have been evaluated previously!"
230- " Returning random candidate..." )
234+ " Suggesting random candidate..." )
231235 return (config_random_dict , {})
232236
233- self .logger .info (f"[Glob. maximum: value={ - opt .fun :.3f} , x={ opt .x } " )
234-
235237 loc = opt .x
236238
237239 if self .distortion is None :
@@ -246,6 +248,9 @@ def get_config(self, budget):
246248
247249 config_opt_arr = dist .rvs (random_state = self .random_state )
248250
251+ self .logger .info (f"[Glob. maximum: value={ - opt .fun :.3f} x={ loc } ] "
252+ f"Suggesting x={ config_opt_arr } " )
253+
249254 config_opt_dict = self ._dict_from_array (config_opt_arr )
250255
251256 return (config_opt_dict , {})
@@ -262,4 +267,4 @@ def new_result(self, job, update_model=True):
262267
263268 loss = job .result ["loss" ]
264269
265- self .ledger .append (x = config_arr , y = loss , b = budget )
270+ self .record .append (x = config_arr , y = loss , b = budget )
0 commit comments