def test_optimize_normalize_Y(): np.random.seed(42) arr_range = np.array([ [0.0, 10.0], [-2.0, 2.0], [-5.0, 5.0], ]) dim_X = arr_range.shape[0] num_X = 5 X = np.random.randn(num_X, dim_X) Y = np.random.randn(num_X, 1) model_bo = BO(arr_range, normalize_Y=True) next_point, dict_info = model_bo.optimize(X, Y) Y_original = dict_info['Y_original'] Y_normalized = dict_info['Y_normalized'] assert np.all(Y == Y_original) assert np.all(Y != Y_normalized) assert np.all(utils_bo.normalize_min_max(Y) == Y_normalized) model_bo = BO(arr_range, normalize_Y=False) next_point, dict_info = model_bo.optimize(X, Y) Y_original = dict_info['Y_original'] Y_normalized = dict_info['Y_normalized'] assert np.all(Y == Y_normalized) assert np.all(Y == Y_original)
def test_normalize_min_max(): Y = np.array([ [1.0], [2.0], [10.0], [-5.0], [4.0], [2.0], [-4.0], [2.0], ]) with pytest.raises(AssertionError) as error: package_target.normalize_min_max(123) with pytest.raises(AssertionError) as error: package_target.normalize_min_max('abc') with pytest.raises(AssertionError) as error: package_target.normalize_min_max(np.squeeze(Y)) Y_normalized = package_target.normalize_min_max(Y) truth_Y = np.array([ [6.0 / 15.0], [7.0 / 15.0], [1.0], [0.0], [9.0 / 15.0], [7.0 / 15.0], [1.0 / 15.0], [7.0 / 15.0], ]) * constants.MULTIPLIER_RESPONSE assert np.all(Y_normalized == truth_Y) Y = np.array([ [10.0], [10.0], [10.0], ]) Y_normalized = package_target.normalize_min_max(Y) assert np.all(Y_normalized == Y)
def thompson_sampling_gp_iteration(range_X: np.ndarray, X: np.ndarray, Y: np.ndarray, normalize_Y: bool=constants.NORMALIZE_RESPONSE, str_sampling_method: str='sobol', num_samples: int=200, debug: bool=False, ) -> np.ndarray: """ It chooses the next query point via Thompson sampling. :param range_X: bounds for a search space. Shape: (d, 2). :type range_X: numpy.ndarray :param X: inputs. Shape: (n, d). :type X: numpy.ndarray :param Y: outputs. Shape: (n, 1). :type Y: numpy.ndarray :param normalize_Y: flag for normalizing responses. :type normalize_Y: bool., optional :param str_sampling_method: the name of sampling method. :type str_sampling_method: str., optional :param num_samples: the number of samples. :type num_samples: int., optional :param debug: flag for a debug option. :type debug: bool., optional :returns: the next point. Shape: (d, ). :rtype: numpy.ndarray :raises: AssertionError, ValueError """ assert isinstance(range_X, np.ndarray) assert isinstance(X, np.ndarray) assert isinstance(Y, np.ndarray) assert isinstance(normalize_Y, bool) assert isinstance(str_sampling_method, str) assert isinstance(num_samples, int) assert isinstance(debug, bool) assert len(range_X.shape) == 2 assert len(X.shape) == 2 assert len(Y.shape) == 2 assert X.shape[0] == Y.shape[0] assert range_X.shape[0] == X.shape[1] assert range_X.shape[1] == 2 str_cov = 'matern52' prior_mu = None str_optimizer_method_gp = 'BFGS' # use_ard = True if normalize_Y: if debug: logger.debug('Responses are normalized.') Y = utils_bo.normalize_min_max(Y) model_bo = bo.BOwGP(range_X) X_test = model_bo.get_samples(str_sampling_method, num_samples=num_samples) mu_Xs, _, Sigma_Xs = gp.predict_with_optimized_hyps(X, Y, X_test, str_cov=str_cov, str_optimizer_method=str_optimizer_method_gp, prior_mu=prior_mu, debug=debug) mu_Xs = np.squeeze(mu_Xs, axis=1) Y_sampled = None list_jitters = [0.0, 1e-4, 1e-2, 1e0, 1e1, 1e2, 1e3, 1e4] for jitter_cov in list_jitters: try: Sigma_Xs_ = Sigma_Xs + jitter_cov * np.eye(Sigma_Xs.shape[0]) Y_sampled = gp.sample_functions(mu_Xs, Sigma_Xs_, num_samples=1) break except ValueError: # pragma: no cover pass if Y_sampled is None: # pragma: no cover raise ValueError('jitter_cov is not large enough.') ind_min = np.argmin(Y_sampled[:, 0]) next_point = X_test[ind_min] return next_point
def optimize( self, X_train: np.ndarray, Y_train: np.ndarray, str_sampling_method: str = constants.STR_SAMPLING_METHOD_AO, num_samples: int = constants.NUM_SAMPLES_AO, str_mlm_method: str = constants.STR_MLM_METHOD, ) -> constants.TYPING_TUPLE_ARRAY_DICT: """ It computes acquired example, candidates of acquired examples, acquisition function values for the candidates, covariance matrix, inverse matrix of the covariance matrix, hyperparameters optimized, and execution times. :param X_train: inputs. Shape: (n, d) or (n, m, d). :type X_train: numpy.ndarray :param Y_train: outputs. Shape: (n, 1). :type Y_train: numpy.ndarray :param str_sampling_method: the name of sampling method for acquisition function optimization. :type str_sampling_method: str., optional :param num_samples: the number of samples. :type num_samples: int., optional :param str_mlm_method: the name of marginal likelihood maximization method for Gaussian process regression. :type str_mlm_method: str., optional :returns: acquired example and dictionary of information. Shape: ((d, ), dict.). :rtype: (numpy.ndarray, dict.) :raises: AssertionError """ assert isinstance(X_train, np.ndarray) assert isinstance(Y_train, np.ndarray) assert isinstance(str_sampling_method, str) assert isinstance(num_samples, int) assert isinstance(str_mlm_method, str) assert len(X_train.shape) == 2 assert len(Y_train.shape) == 2 assert Y_train.shape[1] == 1 assert X_train.shape[0] == Y_train.shape[0] assert X_train.shape[1] == self.num_dim assert num_samples > 0 assert str_sampling_method in constants.ALLOWED_SAMPLING_METHOD assert str_mlm_method in constants.ALLOWED_MLM_METHOD time_start = time.time() Y_train_orig = Y_train if self.normalize_Y and str_mlm_method != 'converged': if self.debug: self.logger.debug('Responses are normalized.') Y_train = utils_bo.normalize_min_max(Y_train) time_start_surrogate = time.time() if str_mlm_method == 'regular': cov_X_X, inv_cov_X_X, hyps = gp_kernel.get_optimized_kernel( X_train, Y_train, self.prior_mu, self.str_cov, str_optimizer_method=self.str_optimizer_method_gp, str_modelselection_method=self.str_modelselection_method, use_ard=self.use_ard, debug=self.debug) elif str_mlm_method == 'combined': from bayeso.gp import gp_likelihood from bayeso.utils import utils_gp from bayeso.utils import utils_covariance prior_mu_train = utils_gp.get_prior_mu(self.prior_mu, X_train) neg_log_ml_best = np.inf cov_X_X_best = None inv_cov_X_X_best = None hyps_best = None for cur_str_optimizer_method in ['BFGS', 'Nelder-Mead']: cov_X_X, inv_cov_X_X, hyps = gp_kernel.get_optimized_kernel( X_train, Y_train, self.prior_mu, self.str_cov, str_optimizer_method=cur_str_optimizer_method, str_modelselection_method=self.str_modelselection_method, use_ard=self.use_ard, debug=self.debug) cur_neg_log_ml_ = gp_likelihood.neg_log_ml( X_train, Y_train, utils_covariance.convert_hyps( self.str_cov, hyps, fix_noise=constants.FIX_GP_NOISE), self.str_cov, prior_mu_train, use_ard=self.use_ard, fix_noise=constants.FIX_GP_NOISE, use_gradient=False, debug=self.debug) if cur_neg_log_ml_ < neg_log_ml_best: neg_log_ml_best = cur_neg_log_ml_ cov_X_X_best = cov_X_X inv_cov_X_X_best = inv_cov_X_X hyps_best = hyps cov_X_X = cov_X_X_best inv_cov_X_X = inv_cov_X_X_best hyps = hyps_best elif str_mlm_method == 'converged': fix_noise = constants.FIX_GP_NOISE if self.is_optimize_hyps: cov_X_X, inv_cov_X_X, hyps = gp_kernel.get_optimized_kernel( X_train, Y_train, self.prior_mu, self.str_cov, str_optimizer_method=self.str_optimizer_method_gp, str_modelselection_method=self.str_modelselection_method, use_ard=self.use_ard, debug=self.debug) self.is_optimize_hyps = not utils_bo.check_hyps_convergence( self.historical_hyps, hyps, self.str_cov, fix_noise) else: # pragma: no cover if self.debug: self.logger.debug('hyps converged.') hyps = self.historical_hyps[-1] cov_X_X, inv_cov_X_X, _ = covariance.get_kernel_inverse( X_train, hyps, self.str_cov, fix_noise=fix_noise, debug=self.debug) else: # pragma: no cover raise ValueError('optimize: missing condition for str_mlm_method.') self.historical_hyps.append(hyps) time_end_surrogate = time.time() time_start_acq = time.time() fun_negative_acquisition = lambda X_test: -1.0 * self.compute_acquisitions( X_test, X_train, Y_train, cov_X_X, inv_cov_X_X, hyps) next_point, next_points = self._optimize( fun_negative_acquisition, str_sampling_method=str_sampling_method, num_samples=num_samples) time_end_acq = time.time() acquisitions = fun_negative_acquisition(next_points) time_end = time.time() dict_info = { 'next_points': next_points, 'acquisitions': acquisitions, 'Y_original': Y_train_orig, 'Y_normalized': Y_train, 'cov_X_X': cov_X_X, 'inv_cov_X_X': inv_cov_X_X, 'hyps': hyps, 'time_surrogate': time_end_surrogate - time_start_surrogate, 'time_acq': time_end_acq - time_start_acq, 'time_overall': time_end - time_start, } if self.debug: self.logger.debug('overall time consumed to acquire: %.4f sec.', time_end - time_start) return next_point, dict_info
def optimize( self, X_train: np.ndarray, Y_train: np.ndarray, str_sampling_method: str = constants.STR_SAMPLING_METHOD_AO_TREES, num_samples: int = constants.NUM_SAMPLES_AO_TREES, ) -> constants.TYPING_TUPLE_ARRAY_DICT: """ It computes acquired example, candidates of acquired examples, acquisition function values for the candidates, covariance matrix, inverse matrix of the covariance matrix, hyperparameters optimized, and execution times. :param X_train: inputs. Shape: (n, d). :type X_train: numpy.ndarray :param Y_train: outputs. Shape: (n, 1). :type Y_train: numpy.ndarray :param str_sampling_method: the name of sampling method for acquisition function optimization. :type str_sampling_method: str., optional :param num_samples: the number of samples. :type num_samples: int., optional :returns: acquired example and dictionary of information. Shape: ((d, ), dict.). :rtype: (numpy.ndarray, dict.) :raises: AssertionError """ assert isinstance(X_train, np.ndarray) assert isinstance(Y_train, np.ndarray) assert isinstance(str_sampling_method, str) assert isinstance(num_samples, int) assert len(X_train.shape) == 2 assert len(Y_train.shape) == 2 assert Y_train.shape[1] == 1 assert X_train.shape[0] == Y_train.shape[0] assert X_train.shape[1] == self.num_dim assert num_samples > 0 assert str_sampling_method in constants.ALLOWED_SAMPLING_METHOD time_start = time.time() Y_train_orig = Y_train if self.normalize_Y: if self.debug: self.logger.debug('Responses are normalized.') Y_train = utils_bo.normalize_min_max(Y_train) time_start_surrogate = time.time() trees = self.get_trees(X_train, Y_train) time_end_surrogate = time.time() time_start_acq = time.time() next_points = self.get_samples(str_sampling_method, fun_objective=None, num_samples=num_samples) fun_negative_acquisition = lambda X_test: -1.0 * self.compute_acquisitions( X_test, X_train, Y_train, trees) acquisitions = fun_negative_acquisition(next_points) ind_next_point = np.argmin(acquisitions) next_point = next_points[ind_next_point] time_end_acq = time.time() time_end = time.time() dict_info = { 'next_points': next_points, 'acquisitions': acquisitions, 'Y_original': Y_train_orig, 'Y_normalized': Y_train, 'trees': trees, 'time_surrogate': time_end_surrogate - time_start_surrogate, 'time_acq': time_end_acq - time_start_acq, 'time_overall': time_end - time_start, } if self.debug: self.logger.debug('overall time consumed to acquire: %.4f sec.', time_end - time_start) return next_point, dict_info