Example #1
0
    def test_1d_analytic_ei_edge_cases(self):
        """Test cases where analytic EI would attempt to compute 0/0 without variance lower bounds."""
        base_coord = numpy.array([0.5])
        point1 = SamplePoint(base_coord, -1.809342, 0)
        point2 = SamplePoint(base_coord * 2.0, -1.09342, 0)

        # First a symmetric case: only one historical point
        data = HistoricalData(base_coord.size, [point1])

        hyperparameters = numpy.array([0.2, 0.3])
        covariance = SquareExponential(hyperparameters)
        gaussian_process = GaussianProcess(covariance, data)

        point_to_sample = base_coord
        ei_eval = ExpectedImprovement(gaussian_process, point_to_sample)

        ei = ei_eval.compute_expected_improvement()
        grad_ei = ei_eval.compute_grad_expected_improvement()
        self.assert_scalar_within_relative(ei, 0.0, 1.0e-15)
        self.assert_vector_within_relative(grad_ei, numpy.zeros(grad_ei.shape), 1.0e-15)

        shifts = (1.0e-15, 4.0e-11, 3.14e-6, 8.89e-1, 2.71)
        self._check_ei_symmetry(ei_eval, point_to_sample, shifts)

        # Now introduce some asymmetry with a second point
        # Right side has a larger objetive value, so the EI minimum
        # is shifted *slightly* to the left of best_so_far.
        gaussian_process.add_sampled_points([point2])
        shift = 3.0e-12
        ei_eval = ExpectedImprovement(gaussian_process, point_to_sample - shift)
        ei = ei_eval.compute_expected_improvement()
        grad_ei = ei_eval.compute_grad_expected_improvement()
        self.assert_scalar_within_relative(ei, 0.0, 1.0e-15)
        self.assert_vector_within_relative(grad_ei, numpy.zeros(grad_ei.shape), 1.0e-15)
    def test_multistart_qei_expected_improvement_dfo(self):
        """Check that multistart optimization (BFGS) can find the optimum point to sample (using 2-EI)."""
        numpy.random.seed(7860)
        index = numpy.argmax(numpy.greater_equal(self.num_sampled_list, 20))
        domain, gaussian_process = self.gp_test_environments[index]

        tolerance = 6.0e-5
        num_multistarts = 3

        # Expand the domain so that we are definitely not doing constrained optimization
        expanded_domain = TensorProductDomain([ClosedInterval(-4.0, 3.0)] *
                                              self.dim)
        num_to_sample = 2
        repeated_domain = RepeatedDomain(num_to_sample, expanded_domain)

        num_mc_iterations = 100000
        # Just any random point that won't be optimal
        points_to_sample = repeated_domain.generate_random_point_in_domain()
        ei_eval = ExpectedImprovement(gaussian_process,
                                      points_to_sample,
                                      num_mc_iterations=num_mc_iterations)
        # Compute EI and its gradient for the sake of comparison
        ei_initial = ei_eval.compute_expected_improvement()

        ei_optimizer = LBFGSBOptimizer(repeated_domain, ei_eval,
                                       self.BFGS_parameters)
        best_point = multistart_expected_improvement_optimization(
            ei_optimizer, num_multistarts, num_to_sample)

        # Check that gradients are "small" or on border. MC is very inaccurate near 0, so use finite difference
        # gradient instead.
        ei_eval.current_point = best_point
        ei_final = ei_eval.compute_expected_improvement()

        finite_diff_grad = numpy.zeros(best_point.shape)
        h_value = 0.00001
        for i in range(best_point.shape[0]):
            for j in range(best_point.shape[1]):
                best_point[i, j] += h_value
                ei_eval.current_point = best_point
                ei_upper = ei_eval.compute_expected_improvement()
                best_point[i, j] -= 2 * h_value
                ei_eval.current_point = best_point
                ei_lower = ei_eval.compute_expected_improvement()
                best_point[i, j] += h_value
                finite_diff_grad[i, j] = (ei_upper - ei_lower) / (2 * h_value)

        self.assert_vector_within_relative(finite_diff_grad,
                                           numpy.zeros(finite_diff_grad.shape),
                                           tolerance)

        # Check that output is in the domain
        assert repeated_domain.check_point_inside(best_point) is True

        # Since we didn't really converge to the optimal EI (too costly), do some other sanity checks
        # EI should have improved
        assert ei_final >= ei_initial
Example #3
0
    def test_multistart_monte_carlo_expected_improvement_optimization(self):
        """Check that multistart optimization (gradient descent) can find the optimum point to sample (using 2-EI)."""
        numpy.random.seed(7858)  # TODO(271): Monte Carlo only works for this seed
        index = numpy.argmax(numpy.greater_equal(self.num_sampled_list, 20))
        domain, gaussian_process = self.gp_test_environments[index]

        max_num_steps = 75  # this is *too few* steps; we configure it this way so the test will run quickly
        max_num_restarts = 5
        num_steps_averaged = 50
        gamma = 0.2
        pre_mult = 1.5
        max_relative_change = 1.0
        tolerance = 3.0e-2  # really large tolerance b/c converging with monte-carlo (esp in Python) is expensive
        gd_parameters = GradientDescentParameters(
            max_num_steps,
            max_num_restarts,
            num_steps_averaged,
            gamma,
            pre_mult,
            max_relative_change,
            tolerance,
        )
        num_multistarts = 2

        # Expand the domain so that we are definitely not doing constrained optimization
        expanded_domain = TensorProductDomain([ClosedInterval(-4.0, 2.0)] * self.dim)
        num_to_sample = 2
        repeated_domain = RepeatedDomain(num_to_sample, expanded_domain)

        num_mc_iterations = 10000
        # Just any random point that won't be optimal
        points_to_sample = repeated_domain.generate_random_point_in_domain()
        ei_eval = ExpectedImprovement(gaussian_process, points_to_sample, num_mc_iterations=num_mc_iterations)
        # Compute EI and its gradient for the sake of comparison
        ei_initial = ei_eval.compute_expected_improvement(force_monte_carlo=True)  # TODO(271) Monte Carlo only works for this seed
        grad_ei_initial = ei_eval.compute_grad_expected_improvement()

        ei_optimizer = GradientDescentOptimizer(repeated_domain, ei_eval, gd_parameters)
        best_point = multistart_expected_improvement_optimization(ei_optimizer, num_multistarts, num_to_sample)

        # Check that gradients are "small"
        ei_eval.current_point = best_point
        ei_final = ei_eval.compute_expected_improvement(force_monte_carlo=True)  # TODO(271) Monte Carlo only works for this seed
        grad_ei_final = ei_eval.compute_grad_expected_improvement()
        self.assert_vector_within_relative(grad_ei_final, numpy.zeros(grad_ei_final.shape), tolerance)

        # Check that output is in the domain
        assert repeated_domain.check_point_inside(best_point) is True

        # Since we didn't really converge to the optimal EI (too costly), do some other sanity checks
        # EI should have improved
        assert ei_final >= ei_initial

        # grad EI should have improved
        for index in numpy.ndindex(grad_ei_final.shape):
            assert numpy.fabs(grad_ei_final[index]) <= numpy.fabs(grad_ei_initial[index])
    def test_multistart_analytic_expected_improvement_optimization(self):
        """Check that multistart optimization (gradient descent) can find the optimum point to sample (using 1D analytic EI)."""
        numpy.random.seed(3148)
        index = numpy.argmax(numpy.greater_equal(self.num_sampled_list, 20))
        domain, gaussian_process = self.gp_test_environments[index]

        max_num_steps = 200  # this is generally *too few* steps; we configure it this way so the test will run quickly
        max_num_restarts = 5
        num_steps_averaged = 0
        gamma = 0.2
        pre_mult = 1.5
        max_relative_change = 1.0
        tolerance = 1.0e-7
        gd_parameters = GradientDescentParameters(
            max_num_steps,
            max_num_restarts,
            num_steps_averaged,
            gamma,
            pre_mult,
            max_relative_change,
            tolerance,
        )
        num_multistarts = 3

        points_to_sample = domain.generate_random_point_in_domain()
        ei_eval = ExpectedImprovement(gaussian_process, points_to_sample)

        # expand the domain so that we are definitely not doing constrained optimization
        expanded_domain = TensorProductDomain([ClosedInterval(-4.0, 2.0)] *
                                              self.dim)

        num_to_sample = 1
        repeated_domain = RepeatedDomain(ei_eval.num_to_sample,
                                         expanded_domain)
        ei_optimizer = GradientDescentOptimizer(repeated_domain, ei_eval,
                                                gd_parameters)
        best_point = multistart_expected_improvement_optimization(
            ei_optimizer, num_multistarts, num_to_sample)

        # Check that gradients are small
        ei_eval.current_point = best_point
        gradient = ei_eval.compute_grad_expected_improvement()
        self.assert_vector_within_relative(gradient,
                                           numpy.zeros(gradient.shape),
                                           tolerance)

        # Check that output is in the domain
        assert repeated_domain.check_point_inside(best_point) is True
Example #5
0
 def optimize(self, all_x):
     """
     :param all_x:
     :return: (best_point, found_point_successfully)
     """
     ei_evaluator = ExpectedImprovement(self._gp)
     ei_vals = numpy.zeros(len(all_x))
     for i in range(len(ei_vals)):
         ei_evaluator.set_current_point(all_x[i, :].reshape((1, -1)))
         print ei_evaluator.num_to_sample
         ei_vals[i] = ei_evaluator.compute_expected_improvement()
     best_ei = numpy.amax(ei_vals)
     if best_ei > 0:
         return all_x[numpy.argmax(best_ei), :], True
     else:
         return all_x[numpy.random.randint(low=0, high=len(best_ei), size=1
                                           ), :], False
Example #6
0
    def test_evaluate_ei_at_points(self):
        """Check that ``evaluate_expected_improvement_at_point_list`` computes and orders results correctly (using 1D analytic EI)."""
        index = numpy.argmax(numpy.greater_equal(self.num_sampled_list, 5))
        domain, gaussian_process = self.gp_test_environments[index]

        points_to_sample = domain.generate_random_point_in_domain()
        ei_eval = ExpectedImprovement(gaussian_process, points_to_sample)

        num_to_eval = 10
        # Add in a newaxis to make num_to_sample explicitly 1
        points_to_evaluate = domain.generate_uniform_random_points_in_domain(num_to_eval)[:, numpy.newaxis, :]

        test_values = ei_eval.evaluate_at_point_list(points_to_evaluate)

        for i, value in enumerate(test_values):
            ei_eval.current_point = points_to_evaluate[i, ...]
            truth = ei_eval.compute_expected_improvement()
            assert value == truth
Example #7
0
def optimize_with_ego(gp, domain_bounds, num_multistart):
    expected_improvement_evaluator = ExpectedImprovement(gp)
    search_domain = pythonTensorProductDomain(
        [ClosedInterval(bound[0], bound[1]) for bound in domain_bounds])
    start_points = search_domain.generate_uniform_random_points_in_domain(
        num_multistart)
    min_negative_ei = numpy.inf

    def negative_ego_func(x):
        expected_improvement_evaluator.set_current_point(x.reshape((1, -1)))
        return -1.0 * expected_improvement_evaluator.compute_expected_improvement(
        )

    for start_point in start_points:
        x, f = bfgs_optimization(start_point, negative_ego_func, domain_bounds)
        if min_negative_ei > f:
            min_negative_ei = f
            point_to_sample = x
    return point_to_sample, -min_negative_ei
Example #8
0
    def test_expected_improvement_and_gradient(self):
        """Test EI by comparing the vectorized and "naive" versions.

        With the same RNG state, these two functions should return identical output.
        We use a fairly low number of monte-carlo iterations since we are not
        trying to converge; just check for consistency.

        .. Note:: this is not a particularly good test. It relies on the "naive"
          version being easier to verify manually and only checks for consistency
          between the naive and vectorized versions.

        """
        num_points_p_q_list = ((1, 0), (1, 1), (2, 1), (1, 4), (5, 3))
        ei_tolerance = 10.0 * numpy.finfo(numpy.float64).eps
        grad_ei_tolerance = 1.0e-13
        numpy.random.seed(78532)

        for test_case in self.gp_test_environments:
            domain, gaussian_process = test_case

            for num_to_sample, num_being_sampled in num_points_p_q_list:
                points_to_sample = domain.generate_uniform_random_points_in_domain(num_to_sample)
                points_being_sampled = domain.generate_uniform_random_points_in_domain(num_being_sampled)

                union_of_points = numpy.reshape(numpy.append(points_to_sample, points_being_sampled), (num_to_sample + num_being_sampled, self.dim))
                ei_eval = ExpectedImprovement(
                    gaussian_process,
                    points_to_sample,
                    points_being_sampled=points_being_sampled,
                    num_mc_iterations=self.num_mc_iterations,
                )

                # Compute quantities required for EI
                mu_star = ei_eval._gaussian_process.compute_mean_of_points(union_of_points)
                var_star = ei_eval._gaussian_process.compute_variance_of_points(union_of_points)

                # Check EI
                # Save state first to restore at the end (o/w other "random" events will get screwed up)
                rng_state = numpy.random.get_state()
                numpy.random.seed(self.rng_seed)
                ei_vectorized = ei_eval._compute_expected_improvement_monte_carlo(mu_star, var_star)
                numpy.random.seed(self.rng_seed)
                ei_naive = ei_eval._compute_expected_improvement_monte_carlo_naive(mu_star, var_star)
                self.assert_scalar_within_relative(ei_vectorized, ei_naive, ei_tolerance)

                # Compute quantities required for grad EI
                grad_mu = ei_eval._gaussian_process.compute_grad_mean_of_points(
                    union_of_points,
                    num_derivatives=num_to_sample,
                )
                grad_chol_decomp = ei_eval._gaussian_process.compute_grad_cholesky_variance_of_points(
                    union_of_points,
                    num_derivatives=num_to_sample,
                )

                # Check grad EI
                numpy.random.seed(self.rng_seed)
                grad_ei_vectorized = ei_eval._compute_grad_expected_improvement_monte_carlo(
                    mu_star,
                    var_star,
                    grad_mu,
                    grad_chol_decomp,
                )
                numpy.random.seed(self.rng_seed)
                grad_ei_naive = ei_eval._compute_grad_expected_improvement_monte_carlo_naive(
                    mu_star,
                    var_star,
                    grad_mu,
                    grad_chol_decomp,
                )
                self.assert_vector_within_relative(grad_ei_vectorized, grad_ei_naive, grad_ei_tolerance)

                # Restore state
                numpy.random.set_state(rng_state)
Example #9
0
# data containers for pickle storage
list_best = []
list_cost = []
list_sampled_IS = []
list_sampled_points = []
list_sampled_vals = []
list_noise_var = []
list_raw_voi = []
best_sampled_val = np.amin(problem.hist_data._points_sampled_value)
truth_at_init_best_sampled = problem.obj_func_min.evaluate(
    problem.truth_is, problem.hist_data.points_sampled[
        np.argmin(problem.hist_data._points_sampled_value), :])
truth_at_best_sampled = truth_at_init_best_sampled
total_cost = 0.0
for ego_n in range(problem.num_iterations):
    expected_improvement_evaluator = ExpectedImprovement(ego_gp)
    min_negative_ei = np.inf

    def negative_ego_func(x):
        expected_improvement_evaluator.set_current_point(x.reshape((1, -1)))
        return -1.0 * expected_improvement_evaluator.compute_expected_improvement(
        )

    def negative_ego_grad_func(x):
        expected_improvement_evaluator.set_current_point(x.reshape((1, -1)))
        return -1.0 * expected_improvement_evaluator.compute_grad_expected_improvement(
        )[0, :]

    def min_negative_ego_func(start_point):
        return bfgs_optimization_grad(start_point, negative_ego_func,
                                      negative_ego_grad_func,