コード例 #1
0
def get_estimated_mean_and_std(gp: GaussianProcess, array_samples_parameters,
                               X):
    functions_samples = []
    X = X.reshape((-1, gp.array_dataset.shape[1]))

    for num_samples, sample_gp_parameter in enumerate(
            array_samples_parameters):
        gp.set_kernel_parameters(*sample_gp_parameter.flatten())
        functions_samples.append(gp.get_sample(X))

        yield gp.get_sample(X)

        if num_samples % 50 == 0:
            print(f'num samples: {num_samples} \r')
コード例 #2
0
def plot_vi_gp(obj, mu, Sigma, X, y):
    gp = GaussianProcess(GaussianLinearKernel(0., 0., 0., 0., 0., 0.), X, y)

    xlim, = obj.boundaries
    x_gt = np.linspace(xlim[0], xlim[1], 100)
    xx = np.linspace(xlim[0] - 2, xlim[1] + 2, 200)

    plt.plot(x_gt, obj.evaluate_without_noise(x_gt), c='c')

    plt.title(f"Gaussian Process Regression")
    mu = mu.flatten()
    for _ in range(500):
        sample_gp_parameter = onp.random.multivariate_normal(mu, Sigma)
        gp.set_kernel_parameters(*sample_gp_parameter)
        function_sample = gp.get_sample(xx.reshape((-1, 1)))
        plt.plot(xx, function_sample, alpha=0.3, c='C0')
        plt.scatter(gp.array_dataset,
                    gp.array_objective_function_values,
                    c='m',
                    marker="+",
                    zorder=1000,
                    s=(30, ))
        plt.pause(0.01)
    plt.show()
コード例 #3
0
class BayesianOptimisation(object):

    def __init__(self,
                 kernel: Kernel,
                 objective_function: objective_functions.abstract_objective_function.ObjectiveFunction,
                 acquisition_function: AcquisitionFunction,
                 ):
        """
        :param kernel: Kernel object used by the gaussian process to perform a regression.
        :param objective_function: ObjectiveFunction object which we will try to minimise
        :param acquisition_function: AcquisitionFunction object
        """
        self._initial_kernel = copy.deepcopy(kernel)
        self._gaussian_process = GaussianProcess(kernel)
        self._objective_function = objective_function
        self._acquisition_function = acquisition_function

    def _initialise_gaussian_process(self,
                                     array_initial_dataset: np.ndarray,
                                     array_initial_objective_function_values: np.ndarray
                                     ) -> None:
        """
        Initialise the gaussian process with its initial dataset
        :param array_initial_dataset: array representing all the data points used to calculate the posterior mean and variance of the GP.
        Its dimension is n x l, there are:
        - n elements in the dataset. Each row corresponds to a data point x_i (with 1<=i<=n), at which the objective function can be evaluated
        - each one of them is of dimension l (representing the number of variables required by the objective function)
        :param array_initial_objective_function_values: array of the evaluations for all the elements in array_dataset. Its shape is hence n x 1 (it's a column vector)
        """

        self._gaussian_process.initialise_dataset(array_initial_dataset, array_initial_objective_function_values)

    def run(self,
            number_steps: int,
            array_initial_dataset: np.ndarray,
            array_initial_objective_function_values: np.ndarray,
            ) -> None:
        """
        Generator that performs a bayesian optimisation

        This method is a generator: at every step, it yields a tuple containing 3 elements:
        - the current up-to-date gaussian process
        - the acquisition function
        - the last computed argmax of the acquisition function.

        Hence, in order to use this method, you need to put it in a for loop,
            for gp, af, arg_max in bo.run(): # Here, bo is a BayesianOptimisation object
                # some code here


        :param number_steps: number of steps to execute in the Bayesian Optimisation procedure.

        :param array_initial_dataset: array_initial_dataset: array representing all the data points used to calculate the posterior mean and variance of the GP.
        Its dimension is n x l, there are:
        - n elements in the dataset. Each row corresponds to a data point x_i (with 1<=i<=n), at which the objective function can be evaluated
        - each one of them is of dimension l (representing the number of variables required by the objective function)

        :param array_initial_objective_function_values: array of the evaluations for all the elements in array_dataset. Its shape is hence n x 1 (it's a column vector)
        """

        print(f"Step {0}/{number_steps} - Initialise Gaussian Process for Provided Dataset")
        self._initialise_gaussian_process(array_initial_dataset,
                                          array_initial_objective_function_values)
        arg_max_acquisition_function = self.compute_arg_max_acquisition_function()

        for index_step in range(number_steps):
            print(f"Step {index_step}/{number_steps} - Evaluating Objective Function at position {arg_max_acquisition_function.tolist()}")
            arg_max_acquisition_function = self._bayesian_optimisation_step(arg_max_acquisition_function)

            # The yield keyword makes the method behave like a generator
            yield self._gaussian_process, self._acquisition_function, arg_max_acquisition_function

    def _bayesian_optimisation_step(self,
                                    arg_max_acquisition_function: np.ndarray
                                    ) -> np.ndarray:
        """
        :param arg_max_acquisition_function: the previously computed argmax of the acquisition function
        :return: the next computed arg_max of the acquisition function after having updated the Gaussian Process
        """
        # TODO
        arg_max_acquisition_function

        # Add new data point

        self._gaussian_process.add_data_point(arg_max_acquisition_function, self._objective_function.evaluate(arg_max_acquisition_function))

        # Update gaussian process and optimise parameters
        
        self.reinitialise_kernel()
        self._gaussian_process.optimise_parameters()

        # compute argmax

        return self.compute_arg_max_acquisition_function()

    def get_best_data_point(self) -> np.ndarray:
        index_best_data_point = np.argmin(self._gaussian_process.array_objective_function_values)
        return self._gaussian_process.array_dataset[index_best_data_point]

    def compute_arg_max_acquisition_function(self) -> np.ndarray:
        return self._acquisition_function.compute_arg_max(
            gaussian_process=self._gaussian_process,
            objective_function=self._objective_function
        )

    def reinitialise_kernel(self) -> None:
        self._gaussian_process.set_kernel_parameters(self._initial_kernel.log_amplitude,
                                                     self._initial_kernel.log_length_scale,
                                                     self._initial_kernel.log_noise_scale)