def _init(self, n_suggestions): self.batch_size = n_suggestions n_init_points = self.config['n_init_points'] if n_init_points == -1: # Special value to use the default 2*D+1 number. n_init_points = 2 * self.dim + 1 self.n_init = max(self.batch_size, n_init_points) exp_design = self.config['experimental_design'] if exp_design == 'latin_hypercube': X_init = latin_hypercube(self.n_init, self.dim) elif exp_design == 'halton': halton_sampler = sampler.Sampler(method='halton', api_config=self.api_config, n_points=self.n_init) X_init = halton_sampler.generate(random_state=self.sampler_seed) X_init = self.space_x.warp(X_init) X_init = to_unit_cube(X_init, self.lb, self.ub) elif exp_design == 'lhs_classic_ratio': lhs_sampler = sampler.Sampler( method='lhs', api_config=self.api_config, n_points=self.n_init, generator_kwargs={'lhs_type': 'classic', 'criterion': 'ratio'}) X_init = lhs_sampler.generate(random_state=self.sampler_seed) X_init = self.space_x.warp(X_init) X_init = to_unit_cube(X_init, self.lb, self.ub) else: raise ValueError(f'Unknown experimental design: {exp_design}.') self.X_init = X_init if DEBUG: print(f'Initialized the method with {self.n_init} points by {exp_design}:') print(X_init)
def turbo_suggest(self, n_suggestions=1): if self.turbo_batch_size is None: # Remember the batch size on the first call to suggest self.turbo_batch_size = n_suggestions self.turbo.batch_size = n_suggestions self.turbo.failtol = np.ceil(np.max([4.0 / self.turbo_batch_size, self.dim / self.turbo_batch_size])) self.turbo.n_init = max([self.turbo.n_init, self.turbo_batch_size]) self.restart() X_next = np.zeros((n_suggestions, self.dim)) # Pick from the initial points n_init = min(len(self.X_init), n_suggestions) if n_init > 0: X_next[:n_init] = deepcopy(self.X_init[:n_init, :]) self.X_init = self.X_init[n_init:, :] # Remove these pending points # Get remaining points from TuRBO n_adapt = n_suggestions - n_init if n_adapt > 0: if len(self.turbo._X) > 0: # Use random points if we can't fit a GP X = to_unit_cube(deepcopy(self.turbo._X), self.lb, self.ub) fX = copula_standardize(deepcopy(self.turbo._fX).ravel()) # Use Copula X_cand, y_cand, _ = self.turbo._create_candidates( X, fX, length=self.turbo.length, n_training_steps=100, hypers={} ) X_next[-n_adapt:, :] = self.turbo._select_candidates(X_cand, y_cand)[:n_adapt, :] X_next[-n_adapt:, :] = from_unit_cube(X_next[-n_adapt:, :], self.lb, self.ub) # Unwarp the suggestions suggestions = self.space_x.unwarp(X_next) suggestions[-1] = self.meta_init[2] return suggestions
def _suggest(self, n_suggestions): X = to_unit_cube(deepcopy(self.X), self.lb, self.ub) y = deepcopy(self.y) if not self.node: self.split_used = 0 self.node = self._build_tree(X, y) used_budget = len(y) idx = (self._get_in_node_region(X, self.node) == 1) X = X[idx] y = y[idx] print(f'Rebuilt the tree of depth {len(self.node)}') model_config = self.config['turbo'] #print('CONFIG!!!!!', model_config) self.turbo = Turbo1( f=None, lb=self.bounds[:, 0], ub=self.bounds[:, 1], n_init=len(X), max_evals=np.iinfo(np.int32).max, batch_size=self.batch_size, verbose=False, use_cylinder=model_config['use_cylinder'], budget=model_config['budget'], use_decay=model_config['use_decay'], decay_threshold=model_config['decay_threshold'], decay_alpha=model_config['decay_alpha'], use_pull=model_config['use_pull'], use_lcb=model_config['use_lcb'], kappa=model_config['kappa'], length_min=model_config['length_min'], length_max=model_config['length_max'], length_init=model_config['length_init'], length_multiplier=model_config['length_multiplier'], used_budget=used_budget) self.turbo._X = np.array(X, copy=True) self.turbo._fX = np.array(y, copy=True) self.turbo.X = np.array(X, copy=True) self.turbo.fX = np.array(y, copy=True) print('Initialized TURBO') else: idx = (self._get_in_node_region(X, self.node) == 1) X = X[idx] y = y[idx] self.split_used += 1 length_init_method = self.config['turbo_length_init_method'] if length_init_method == 'default': length = self.turbo.length elif length_init_method == 'length_init': length = self.turbo.length_init elif length_init_method == 'length_max': length = self.turbo.length_max elif length_init_method == 'infinity': length = np.iinfo(np.int32).max else: raise ValueError( f'Unknown init method for turbo\'s length: {length_init_method}.' ) length_reties = self.config['turbo_length_retries'] for retry in range(length_reties): XX = X yy = copula_standardize(y.ravel()) X_cand, y_cand, _ = self.turbo._create_candidates( XX, yy, length=length, n_training_steps=self.config['turbo_training_steps'], hypers={}) in_region_predictions = self._get_in_node_region(X_cand, self.node) in_region_idx = in_region_predictions == 1 if DEBUG: print( f'In region: {np.sum(in_region_idx)} out of {len(X_cand)}') if np.sum(in_region_idx) >= n_suggestions: X_cand, y_cand = X_cand[in_region_idx], y_cand[in_region_idx] self.turbo.f_var = self.turbo.f_var[in_region_idx] if DEBUG: print('Found a suitable set of candidates.') break else: length /= 2 if DEBUG: print(f'Retrying {retry + 1}/{length_reties} time') X_cand = self.turbo._select_candidates(X_cand, y_cand)[:n_suggestions, :] if DEBUG: if X.shape[1] == 3: tx = np.arange(0.0, 1.0 + 1e-6, 0.1) ty = np.arange(0.0, 1.0 + 1e-6, 0.1) tz = np.arange(0.0, 1.0 + 1e-6, 0.1) p = np.array([[x, y, z] for x in tx for y in ty for z in tz]) elif X.shape[1] == 2: tx = np.arange(0.0, 1.0 + 1e-6, 0.1) ty = np.arange(0.0, 1.0 + 1e-6, 0.1) p = np.array([[x, y] for x in tx for y in ty]) else: raise ValueError( 'The points for the DEBUG should either be 2D or 3D.') p_predictions = self._get_in_node_region(p, self.node) in_turbo_bounds = np.logical_and( np.all(self.turbo.cand_lb <= p, axis=1), np.all(p <= self.turbo.cand_ub, axis=1)) pcds = [] _add_pcd(pcds, p[p_predictions == 0], (1.0, 0.0, 0.0)) _add_pcd( pcds, p[np.logical_and(p_predictions == 1, np.logical_not(in_turbo_bounds))], (0.0, 1.0, 0.0)) _add_pcd(pcds, p[np.logical_and(p_predictions == 1, in_turbo_bounds)], (0.0, 0.5, 0.0)) _add_pcd(pcds, X_cand, (0.0, 0.0, 0.0)) open3d.visualization.draw_geometries(pcds) return X_cand