diff --git a/bayeso/acquisition.py b/bayeso/acquisition.py index 33f4a64..a3f1bad 100644 --- a/bayeso/acquisition.py +++ b/bayeso/acquisition.py @@ -72,3 +72,31 @@ def aei(pred_mean, pred_std, Y_train, noise, ei = (np.min(Y_train) - pred_mean) * scipy.stats.norm.cdf(val_z) + pred_std * scipy.stats.norm.pdf(val_z) aei = ei * (1.0 - noise / np.sqrt(pred_std**2 + noise**2)) return aei + +# pred_std and Y_train are ignored. +def pure_exploit(pred_mean, pred_std=None, Y_train=None): + assert isinstance(pred_mean, np.ndarray) + assert isinstance(pred_std, np.ndarray) or pred_std is None + assert isinstance(Y_train, np.ndarray) or Y_train is None + assert len(pred_mean.shape) == 1 + if pred_std is not None: + assert len(pred_std.shape) == 1 + assert pred_mean.shape[0] == pred_std.shape[0] + if Y_train is not None: + assert len(Y_train.shape) == 2 + + return -pred_mean + +# pred_mean and Y_train are ignored. +def pure_explore(pred_std, pred_mean=None, Y_train=None): + assert isinstance(pred_mean, np.ndarray) or pred_mean is None + assert isinstance(pred_std, np.ndarray) + assert isinstance(Y_train, np.ndarray) or Y_train is None + assert len(pred_std.shape) == 1 + if pred_mean is not None: + assert len(pred_mean.shape) == 1 + assert pred_mean.shape[0] == pred_std.shape[0] + if Y_train is not None: + assert len(Y_train.shape) == 2 + + return pred_std diff --git a/bayeso/bo.py b/bayeso/bo.py index a64cc15..be907bb 100644 --- a/bayeso/bo.py +++ b/bayeso/bo.py @@ -113,7 +113,8 @@ def get_initial(self, str_initial_method, def _optimize_objective(self, fun_acquisition, X_train, Y_train, X_test, cov_X_X, inv_cov_X_X, hyps): X_test = np.atleast_2d(X_test) pred_mean, pred_std = gp.predict_test_(X_train, Y_train, X_test, cov_X_X, inv_cov_X_X, hyps, self.str_cov, self.prior_mu) - acquisitions = fun_acquisition(pred_mean.flatten(), pred_std.flatten(), Y_train=Y_train) + # no matter which acquisition functions are given, we input pred_mean, pred_std, and Y_train. + acquisitions = fun_acquisition(pred_mean=pred_mean.flatten(), pred_std=pred_std.flatten(), Y_train=Y_train) return acquisitions def _optimize(self, fun_negative_acquisition, str_initial_method, int_samples): @@ -171,6 +172,10 @@ def optimize(self, X_train, Y_train, fun_acquisition = acquisition.ucb elif self.str_acq == 'aei': fun_acquisition = lambda pred_mean, pred_std, Y_train: acquisition.aei(pred_mean, pred_std, Y_train, hyps['noise']) + elif self.str_acq == 'pure_exploit': + fun_acquisition = acquisition.pure_exploit + elif self.str_acq == 'pure_explore': + fun_acquisition = acquisition.pure_explore else: raise NotImplementedError('optimize: allowed str_acq, but it is not implemented.') diff --git a/bayeso/constants.py b/bayeso/constants.py index a5b6ffa..786c74b 100644 --- a/bayeso/constants.py +++ b/bayeso/constants.py @@ -32,7 +32,7 @@ RANGE_SHADE = 1.96 ALLOWED_GP_COV = ['se', 'matern32', 'matern52'] -ALLOWED_BO_ACQ = ['pi', 'ei', 'ucb', 'aei'] +ALLOWED_BO_ACQ = ['pi', 'ei', 'ucb', 'aei', 'pure_exploit', 'pure_explore'] ALLOWED_INITIALIZATIONS_BO = ['sobol', 'uniform', 'latin'] ALLOWED_INITIALIZATIONS_AO = ALLOWED_INITIALIZATIONS_BO + ['grid'] diff --git a/examples/example_basics_bo.py b/examples/example_basics_bo.py new file mode 100644 index 0000000..c46ac31 --- /dev/null +++ b/examples/example_basics_bo.py @@ -0,0 +1,47 @@ +# example_basics_bo +# author: Jungtaek Kim (jtkim@postech.ac.kr) +# last updated: July 12, 2018 + +import numpy as np +import os + +from bayeso import gp +from bayeso import bo +from bayeso import acquisition +from bayeso.utils import utils_plotting + + +PATH_SAVE = './figures/bo/' + +def fun_target(X): + return 4.0 * np.cos(X) + 0.1 * X + 2.0 * np.sin(X) + 0.4 * (X - 0.5)**2 + +def main(): + num_iter = 10 + X_train = np.array([ + [-5], + [-1], + [1], + [2], + ]) + num_init = X_train.shape[0] + model_bo = bo.BO(np.array([[-6., 6.]])) + X_test = np.linspace(-6, 6, 400) + X_test = np.reshape(X_test, (400, 1)) + for ind_ in range(1, num_iter + 1): + Y_train = fun_target(X_train) + next_x, _, _, cov_X_X, inv_cov_X_X, hyps = model_bo.optimize(X_train, fun_target(X_train), str_initial_method='uniform') + mu_test, sigma_test = gp.predict_test_(X_train, Y_train, X_test, cov_X_X, inv_cov_X_X, hyps) + acq_test = acquisition.ei(mu_test.flatten(), sigma_test.flatten(), Y_train) + acq_test = np.expand_dims(acq_test, axis=1) + X_train = np.vstack((X_train, next_x)) + Y_train = fun_target(X_train) + utils_plotting.plot_bo_step(X_train, Y_train, X_test, fun_target(X_test), mu_test, sigma_test, path_save=PATH_SAVE, str_postfix='basics_bo_' + str(ind_), int_init=num_init) + utils_plotting.plot_bo_step_acq(X_train, Y_train, X_test, fun_target(X_test), mu_test, sigma_test, acq_test, path_save=PATH_SAVE, str_postfix='basics_bo_' + str(ind_), int_init=num_init, is_acq_axis_small=True) + + +if __name__ == '__main__': + if not os.path.isdir(PATH_SAVE): + os.makedirs(PATH_SAVE) + main() + diff --git a/examples/example_basics_bo_aei.py b/examples/example_bo_aei.py similarity index 88% rename from examples/example_basics_bo_aei.py rename to examples/example_bo_aei.py index 202f089..7f5f095 100644 --- a/examples/example_basics_bo_aei.py +++ b/examples/example_bo_aei.py @@ -1,4 +1,4 @@ -# example_basics_bo_aei +# example_bo_aei # author: Jungtaek Kim (jtkim@postech.ac.kr) # last updated: July 12, 2018 @@ -37,8 +37,8 @@ def main(): acq_test = np.expand_dims(acq_test, axis=1) X_train = np.vstack((X_train, next_x)) Y_train = fun_target(X_train) - utils_plotting.plot_bo_step(X_train, Y_train, X_test, fun_target(X_test), mu_test, sigma_test, path_save=PATH_SAVE, str_postfix='bascis_{}_'.format(str_acq) + str(ind_), int_init=num_init) - utils_plotting.plot_bo_step_acq(X_train, Y_train, X_test, fun_target(X_test), mu_test, sigma_test, acq_test, path_save=PATH_SAVE, str_postfix='basics_{}_'.format(str_acq) + str(ind_), int_init=num_init, is_acq_axis_small=True) + utils_plotting.plot_bo_step(X_train, Y_train, X_test, fun_target(X_test), mu_test, sigma_test, path_save=PATH_SAVE, str_postfix='bo_{}_'.format(str_acq) + str(ind_), int_init=num_init) + utils_plotting.plot_bo_step_acq(X_train, Y_train, X_test, fun_target(X_test), mu_test, sigma_test, acq_test, path_save=PATH_SAVE, str_postfix='bo_{}_'.format(str_acq) + str(ind_), int_init=num_init, is_acq_axis_small=True) if __name__ == '__main__': diff --git a/examples/example_basics_bo_ei.py b/examples/example_bo_ei.py similarity index 88% rename from examples/example_basics_bo_ei.py rename to examples/example_bo_ei.py index 775f388..18cba9e 100644 --- a/examples/example_basics_bo_ei.py +++ b/examples/example_bo_ei.py @@ -1,4 +1,4 @@ -# example_basics_bo_ei +# example_bo_ei # author: Jungtaek Kim (jtkim@postech.ac.kr) # last updated: July 12, 2018 @@ -37,8 +37,8 @@ def main(): acq_test = np.expand_dims(acq_test, axis=1) X_train = np.vstack((X_train, next_x)) Y_train = fun_target(X_train) - utils_plotting.plot_bo_step(X_train, Y_train, X_test, fun_target(X_test), mu_test, sigma_test, path_save=PATH_SAVE, str_postfix='bascis_{}_'.format(str_acq) + str(ind_), int_init=num_init) - utils_plotting.plot_bo_step_acq(X_train, Y_train, X_test, fun_target(X_test), mu_test, sigma_test, acq_test, path_save=PATH_SAVE, str_postfix='basics_{}_'.format(str_acq) + str(ind_), int_init=num_init, is_acq_axis_small=True) + utils_plotting.plot_bo_step(X_train, Y_train, X_test, fun_target(X_test), mu_test, sigma_test, path_save=PATH_SAVE, str_postfix='bo_{}_'.format(str_acq) + str(ind_), int_init=num_init) + utils_plotting.plot_bo_step_acq(X_train, Y_train, X_test, fun_target(X_test), mu_test, sigma_test, acq_test, path_save=PATH_SAVE, str_postfix='bo_{}_'.format(str_acq) + str(ind_), int_init=num_init, is_acq_axis_small=True) if __name__ == '__main__': diff --git a/examples/example_basics_bo_pi.py b/examples/example_bo_pi.py similarity index 88% rename from examples/example_basics_bo_pi.py rename to examples/example_bo_pi.py index 051b4fb..8beb70e 100644 --- a/examples/example_basics_bo_pi.py +++ b/examples/example_bo_pi.py @@ -1,4 +1,4 @@ -# example_basics_bo_pi +# example_bo_pi # author: Jungtaek Kim (jtkim@postech.ac.kr) # last updated: July 12, 2018 @@ -37,8 +37,8 @@ def main(): acq_test = np.expand_dims(acq_test, axis=1) X_train = np.vstack((X_train, next_x)) Y_train = fun_target(X_train) - utils_plotting.plot_bo_step(X_train, Y_train, X_test, fun_target(X_test), mu_test, sigma_test, path_save=PATH_SAVE, str_postfix='bascis_{}_'.format(str_acq) + str(ind_), int_init=num_init) - utils_plotting.plot_bo_step_acq(X_train, Y_train, X_test, fun_target(X_test), mu_test, sigma_test, acq_test, path_save=PATH_SAVE, str_postfix='basics_{}_'.format(str_acq) + str(ind_), int_init=num_init, is_acq_axis_small=True) + utils_plotting.plot_bo_step(X_train, Y_train, X_test, fun_target(X_test), mu_test, sigma_test, path_save=PATH_SAVE, str_postfix='bo_{}_'.format(str_acq) + str(ind_), int_init=num_init) + utils_plotting.plot_bo_step_acq(X_train, Y_train, X_test, fun_target(X_test), mu_test, sigma_test, acq_test, path_save=PATH_SAVE, str_postfix='bo_{}_'.format(str_acq) + str(ind_), int_init=num_init, is_acq_axis_small=True) if __name__ == '__main__': diff --git a/examples/example_bo_pure_exploit.py b/examples/example_bo_pure_exploit.py new file mode 100644 index 0000000..f001eba --- /dev/null +++ b/examples/example_bo_pure_exploit.py @@ -0,0 +1,48 @@ +# example_bo_pure_exploit +# author: Jungtaek Kim (jtkim@postech.ac.kr) +# last updated: July 12, 2018 + +import numpy as np +import os + +from bayeso import gp +from bayeso import bo +from bayeso import acquisition +from bayeso.utils import utils_plotting + + +PATH_SAVE = './figures/bo/' + +def fun_target(X): + return 4.0 * np.cos(X) + 0.1 * X + 2.0 * np.sin(X) + 0.4 * (X - 0.5)**2 + +def main(): + str_acq = 'pure_exploit' + num_iter = 10 + X_train = np.array([ + [-5], + [-1], + [1], + [2], + ]) + num_init = X_train.shape[0] + model_bo = bo.BO(np.array([[-6., 6.]]), str_acq=str_acq) + X_test = np.linspace(-6, 6, 400) + X_test = np.reshape(X_test, (400, 1)) + for ind_ in range(1, num_iter + 1): + Y_train = fun_target(X_train) + next_x, _, _, cov_X_X, inv_cov_X_X, hyps = model_bo.optimize(X_train, fun_target(X_train), str_initial_method='uniform') + mu_test, sigma_test = gp.predict_test_(X_train, Y_train, X_test, cov_X_X, inv_cov_X_X, hyps) + acq_test = acquisition.pure_exploit(mu_test.flatten()) + acq_test = np.expand_dims(acq_test, axis=1) + X_train = np.vstack((X_train, next_x)) + Y_train = fun_target(X_train) + utils_plotting.plot_bo_step(X_train, Y_train, X_test, fun_target(X_test), mu_test, sigma_test, path_save=PATH_SAVE, str_postfix='bo_{}_'.format(str_acq) + str(ind_), int_init=num_init) + utils_plotting.plot_bo_step_acq(X_train, Y_train, X_test, fun_target(X_test), mu_test, sigma_test, acq_test, path_save=PATH_SAVE, str_postfix='bo_{}_'.format(str_acq) + str(ind_), int_init=num_init, is_acq_axis_small=True) + + +if __name__ == '__main__': + if not os.path.isdir(PATH_SAVE): + os.makedirs(PATH_SAVE) + main() + diff --git a/examples/example_bo_pure_explore.py b/examples/example_bo_pure_explore.py new file mode 100644 index 0000000..4ae99af --- /dev/null +++ b/examples/example_bo_pure_explore.py @@ -0,0 +1,48 @@ +# example_bo_pure_explore +# author: Jungtaek Kim (jtkim@postech.ac.kr) +# last updated: July 12, 2018 + +import numpy as np +import os + +from bayeso import gp +from bayeso import bo +from bayeso import acquisition +from bayeso.utils import utils_plotting + + +PATH_SAVE = './figures/bo/' + +def fun_target(X): + return 4.0 * np.cos(X) + 0.1 * X + 2.0 * np.sin(X) + 0.4 * (X - 0.5)**2 + +def main(): + str_acq = 'pure_explore' + num_iter = 10 + X_train = np.array([ + [-5], + [-1], + [1], + [2], + ]) + num_init = X_train.shape[0] + model_bo = bo.BO(np.array([[-6., 6.]]), str_acq=str_acq) + X_test = np.linspace(-6, 6, 400) + X_test = np.reshape(X_test, (400, 1)) + for ind_ in range(1, num_iter + 1): + Y_train = fun_target(X_train) + next_x, _, _, cov_X_X, inv_cov_X_X, hyps = model_bo.optimize(X_train, fun_target(X_train), str_initial_method='uniform') + mu_test, sigma_test = gp.predict_test_(X_train, Y_train, X_test, cov_X_X, inv_cov_X_X, hyps) + acq_test = acquisition.pure_explore(sigma_test.flatten()) + acq_test = np.expand_dims(acq_test, axis=1) + X_train = np.vstack((X_train, next_x)) + Y_train = fun_target(X_train) + utils_plotting.plot_bo_step(X_train, Y_train, X_test, fun_target(X_test), mu_test, sigma_test, path_save=PATH_SAVE, str_postfix='bo_{}_'.format(str_acq) + str(ind_), int_init=num_init) + utils_plotting.plot_bo_step_acq(X_train, Y_train, X_test, fun_target(X_test), mu_test, sigma_test, acq_test, path_save=PATH_SAVE, str_postfix='bo_{}_'.format(str_acq) + str(ind_), int_init=num_init, is_acq_axis_small=True) + + +if __name__ == '__main__': + if not os.path.isdir(PATH_SAVE): + os.makedirs(PATH_SAVE) + main() + diff --git a/examples/example_basics_bo_ucb.py b/examples/example_bo_ucb.py similarity index 88% rename from examples/example_basics_bo_ucb.py rename to examples/example_bo_ucb.py index 5d17005..d405d9b 100644 --- a/examples/example_basics_bo_ucb.py +++ b/examples/example_bo_ucb.py @@ -1,4 +1,4 @@ -# example_basics_bo_ucb +# example_bo_ucb # author: Jungtaek Kim (jtkim@postech.ac.kr) # last updated: July 12, 2018 @@ -37,8 +37,8 @@ def main(): acq_test = np.expand_dims(acq_test, axis=1) X_train = np.vstack((X_train, next_x)) Y_train = fun_target(X_train) - utils_plotting.plot_bo_step(X_train, Y_train, X_test, fun_target(X_test), mu_test, sigma_test, path_save=PATH_SAVE, str_postfix='bascis_{}_'.format(str_acq) + str(ind_), int_init=num_init) - utils_plotting.plot_bo_step_acq(X_train, Y_train, X_test, fun_target(X_test), mu_test, sigma_test, acq_test, path_save=PATH_SAVE, str_postfix='basics_{}_'.format(str_acq) + str(ind_), int_init=num_init, is_acq_axis_small=True) + utils_plotting.plot_bo_step(X_train, Y_train, X_test, fun_target(X_test), mu_test, sigma_test, path_save=PATH_SAVE, str_postfix='bo_{}_'.format(str_acq) + str(ind_), int_init=num_init) + utils_plotting.plot_bo_step_acq(X_train, Y_train, X_test, fun_target(X_test), mu_test, sigma_test, acq_test, path_save=PATH_SAVE, str_postfix='bo_{}_'.format(str_acq) + str(ind_), int_init=num_init, is_acq_axis_small=True) if __name__ == '__main__': diff --git a/setup.py b/setup.py index 641033d..f5069ac 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ setup( name='bayeso', - version='0.1.0', + version='0.2.3', author='Jungtaek Kim', author_email='jtkim@postech.ac.kr', url='https://github.com/jungtaekkim/bayeso', diff --git a/tests/__init__.py b/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/test_acquisition.py b/tests/test_acquisition.py index 17afb7a..2f4f90b 100644 --- a/tests/test_acquisition.py +++ b/tests/test_acquisition.py @@ -106,3 +106,42 @@ def test_aei(): truth_val_acq = np.array([1.16847489e-01, 2.44025364e-02, 2.48686922e-03, 1.11930407e-04, 2.09279771e-06, 1.56585558e-08, 4.57958958e-11, 5.15587486e-14, 2.21142019e-17, 3.58729395e-21]) assert (np.abs(val_acq - truth_val_acq) < TEST_EPSILON).all() +def test_pure_exploit(): + with pytest.raises(AssertionError) as error: + acquisition.pure_exploit('abc') + with pytest.raises(AssertionError) as error: + acquisition.pure_exploit(np.ones((10, 1))) + with pytest.raises(AssertionError) as error: + acquisition.pure_exploit(np.ones(10), pred_std='abc') + with pytest.raises(AssertionError) as error: + acquisition.pure_exploit(np.ones(10), Y_train='abc') + with pytest.raises(AssertionError) as error: + acquisition.pure_exploit(np.ones(10), pred_std=np.ones((10, 1))) + with pytest.raises(AssertionError) as error: + acquisition.pure_exploit(np.ones(10), pred_std=np.ones(20)) + with pytest.raises(AssertionError) as error: + acquisition.pure_exploit(np.ones(10), Y_train=np.ones(20)) + + val_acq = acquisition.pure_exploit(np.arange(0, 10)) + truth_val_acq = -np.arange(0, 10) + assert (np.abs(val_acq - truth_val_acq) < TEST_EPSILON).all() + +def test_pure_explore(): + with pytest.raises(AssertionError) as error: + acquisition.pure_explore('abc') + with pytest.raises(AssertionError) as error: + acquisition.pure_explore(np.ones((10, 1))) + with pytest.raises(AssertionError) as error: + acquisition.pure_explore(np.ones(10), pred_mean='abc') + with pytest.raises(AssertionError) as error: + acquisition.pure_explore(np.ones(10), Y_train='abc') + with pytest.raises(AssertionError) as error: + acquisition.pure_explore(np.ones(10), pred_mean=np.ones((10, 1))) + with pytest.raises(AssertionError) as error: + acquisition.pure_explore(np.ones(10), pred_mean=np.ones(20)) + with pytest.raises(AssertionError) as error: + acquisition.pure_explore(np.ones(10), Y_train=np.ones(20)) + + val_acq = acquisition.pure_explore(np.arange(0, 10)) + truth_val_acq = np.arange(0, 10) + assert (np.abs(val_acq - truth_val_acq) < TEST_EPSILON).all() diff --git a/tests/test_bo.py b/tests/test_bo.py index 04d6f13..7e1d102 100644 --- a/tests/test_bo.py +++ b/tests/test_bo.py @@ -204,3 +204,33 @@ def test_optimize(): assert next_point.shape[0] == dim_X assert next_points.shape[1] == dim_X assert next_points.shape[0] == acquisitions.shape[0] + + model_bo = bo.BO(arr_range_1, str_acq='pure_exploit') + next_point, next_points, acquisitions, cov_X_X, inv_cov_X_X, hyps = model_bo.optimize(X, Y) + assert isinstance(next_point, np.ndarray) + assert isinstance(next_points, np.ndarray) + assert isinstance(acquisitions, np.ndarray) + assert isinstance(cov_X_X, np.ndarray) + assert isinstance(inv_cov_X_X, np.ndarray) + assert isinstance(hyps, dict) + assert len(next_point.shape) == 1 + assert len(next_points.shape) == 2 + assert len(acquisitions.shape) == 1 + assert next_point.shape[0] == dim_X + assert next_points.shape[1] == dim_X + assert next_points.shape[0] == acquisitions.shape[0] + + model_bo = bo.BO(arr_range_1, str_acq='pure_explore') + next_point, next_points, acquisitions, cov_X_X, inv_cov_X_X, hyps = model_bo.optimize(X, Y) + assert isinstance(next_point, np.ndarray) + assert isinstance(next_points, np.ndarray) + assert isinstance(acquisitions, np.ndarray) + assert isinstance(cov_X_X, np.ndarray) + assert isinstance(inv_cov_X_X, np.ndarray) + assert isinstance(hyps, dict) + assert len(next_point.shape) == 1 + assert len(next_points.shape) == 2 + assert len(acquisitions.shape) == 1 + assert next_point.shape[0] == dim_X + assert next_points.shape[1] == dim_X + assert next_points.shape[0] == acquisitions.shape[0]