def test_zero_one_unnormalization(self):
        X_norm = np.random.rand(100, 3)
        lo = np.ones([3]) * -1
        up = np.ones([3])
        X = normalization.zero_one_unnormalization(X_norm, lo, up)

        assert X_norm.shape == X.shape
        assert np.all(np.min(X, axis=0) >= lo)
        assert np.all(np.max(X, axis=0) <= up)
    def get_incumbent(self):
        """
        Returns the best observed point and its function value

        Returns
        ----------
        incumbent: ndarray (D,)
            current incumbent
        incumbent_value: ndarray (N,)
            the observed value of the incumbent
        """
        inc, inc_value = super(GaussianProcessMCMC, self).get_incumbent()
        if self.normalize_input:
            inc = normalization.zero_one_unnormalization(inc, self.lower, self.upper)

        if self.normalize_output:
            inc_value = normalization.zero_mean_unit_var_unnormalization(inc_value, self.y_mean, self.y_std)

        return inc, inc_value
Example #3
0
    def get_incumbent(self):
        """
        Returns the best observed point and its function value

        Returns
        ----------
        incumbent: ndarray (D,)
            current incumbent
        incumbent_value: ndarray (N,)
            the observed value of the incumbent
        """
        inc, inc_value = super(GaussianProcess, self).get_incumbent()
        if self.normalize_input:
            inc = normalization.zero_one_unnormalization(inc, self.lower, self.upper)

        if self.normalize_output:
            inc_value = normalization.zero_mean_unit_var_unnormalization(inc_value, self.y_mean, self.y_std)

        return inc, inc_value
Example #4
0
File: mtbo.py Project: snpc94/RoBO
def mtbo(objective_function,
         lower,
         upper,
         n_tasks=2,
         n_init=2,
         num_iterations=30,
         burnin=100,
         chain_length=200,
         rng=None):
    """
    Interface to MTBO[1] which uses an auxiliary cheaper task to speed up the optimization
    of a more expensive but similar task.

    [1] Multi-Task Bayesian Optimization
        K. Swersky and J. Snoek and R. Adams
        Proceedings of the 27th International Conference on Advances in Neural Information Processing Systems (NIPS'13)

    Parameters
    ----------
    objective_function: function
        Objective function that will be optimized
    lower: np.array(D,)
        Lower bound of the input space
    upper: np.array(D,)
        Upper bound of the input space
    n_tasks: int
        Number of task
    n_init: int
        Number of initial design points
    num_iterations: int
        Number of iterations
    chain_length : int
        The length of the MCMC chain for each walker.
    burnin : int
        The number of burnin steps before the actual MCMC sampling starts.
    rng: numpy.random.RandomState
        Random number generator

    Returns
    -------
        dict with all results
    """

    assert n_init <= num_iterations, "Number of initial design point has to be <= than the number of iterations"
    assert lower.shape[0] == upper.shape[
        0], "Dimension miss match between upper and lower bound"

    time_start = time.time()
    if rng is None:
        rng = np.random.RandomState(np.random.randint(0, 10000))

    n_dims = lower.shape[0]

    # Bookkeeping
    time_func_eval = []
    time_overhead = []
    incumbents = []
    runtime = []

    X = []
    y = []
    c = []

    # Define model for the objective function
    cov_amp = 1  # Covariance amplitude
    kernel = cov_amp

    # ARD Kernel for the configuration space
    for d in range(n_dims):
        kernel *= george.kernels.Matern52Kernel(np.ones([1]) * 0.01,
                                                ndim=n_dims + 1,
                                                dim=d)

    task_kernel = george.kernels.TaskKernel(n_dims + 1, n_dims, n_tasks)
    kernel *= task_kernel

    # Take 3 times more samples than we have hyperparameters
    n_hypers = 3 * len(kernel)
    if n_hypers % 2 == 1:
        n_hypers += 1

    prior = MTBOPrior(len(kernel) + 1,
                      n_ls=n_dims,
                      n_kt=len(task_kernel),
                      rng=rng)

    model_objective = GaussianProcessMCMC(kernel,
                                          prior=prior,
                                          burnin_steps=burnin,
                                          chain_length=chain_length,
                                          n_hypers=n_hypers,
                                          normalize_input=False,
                                          lower=lower,
                                          upper=upper,
                                          rng=rng)

    # Define model for the cost function
    cost_cov_amp = 1

    cost_kernel = cost_cov_amp

    # ARD Kernel for the configuration space
    for d in range(n_dims):
        cost_kernel *= george.kernels.Matern52Kernel(np.ones([1]) * 0.01,
                                                     ndim=n_dims + 1,
                                                     dim=d)

    cost_task_kernel = george.kernels.TaskKernel(n_dims + 1, n_dims, n_tasks)
    cost_kernel *= cost_task_kernel

    cost_prior = MTBOPrior(len(cost_kernel) + 1,
                           n_ls=n_dims,
                           n_kt=len(task_kernel),
                           rng=rng)

    model_cost = GaussianProcessMCMC(cost_kernel,
                                     prior=cost_prior,
                                     burnin_steps=burnin,
                                     chain_length=chain_length,
                                     n_hypers=n_hypers,
                                     normalize_input=False,
                                     lower=lower,
                                     upper=upper,
                                     rng=rng)

    # Extend input space by task variable
    extend_lower = np.append(lower, 0)
    extend_upper = np.append(upper, n_tasks - 1)
    is_env = np.zeros(extend_lower.shape[0])
    is_env[-1] = 1

    # Define acquisition function and maximizer
    ig = InformationGainPerUnitCost(model_objective,
                                    model_cost,
                                    extend_lower,
                                    extend_upper,
                                    is_env_variable=is_env,
                                    n_representer=50)
    acquisition_func = MarginalizationGPMCMC(ig)

    wrapper_func = partial(transformation,
                           acq=acquisition_func,
                           lower=lower,
                           upper=upper)
    maximizer = Direct(wrapper_func, extend_lower, extend_upper, verbose=True)

    # Initial Design
    for _ in range(n_init):
        logger.info("Initial design")
        start_time_overhead = time.time()
        # Draw random configuration and evaluate it just on the auxiliary task
        task = 0
        x = init_random_uniform(lower, upper, 1, rng)[0]
        logger.info("Evaluate candidate %s", str(x))
        st = time.time()
        func_val, cost = objective_function(x, task)
        time_func_eval.append(time.time() - st)

        logger.info("Configuration achieved a performance of %f with cost %f",
                    func_val, cost)
        logger.info("Evaluation of this configuration took %f seconds",
                    time_func_eval[-1])

        # Bookkeeping
        config = np.append(x, task)
        X.append(config)
        y.append(func_val)
        c.append(cost)

        # Estimate incumbent as the best observed value so far
        best_idx = np.argmin(y)
        incumbents.append(np.append(
            X[best_idx],
            n_tasks - 1))  # Incumbent is always on the task of interest

        time_overhead.append(time.time() - start_time_overhead)
        runtime.append(time.time() - time_start)

    X = np.array(X)
    y = np.array(y)
    c = np.array(c)

    for it in range(n_init, num_iterations):
        logger.info("Start iteration %d ... ", it)

        start_time = time.time()

        # Train models
        model_objective.train(transform(X, lower, upper), y, do_optimize=True)
        model_cost.train(transform(X, lower, upper), c, do_optimize=True)

        # Estimate incumbent by projecting all observed points to the task of interest and
        # pick the point with the lowest mean prediction
        incumbent, incumbent_value = projected_incumbent_estimation(
            model_objective,
            transform(X, lower, upper)[:, :-1],
            proj_value=n_tasks - 1)
        incumbent[:-1] = normalization.zero_one_unnormalization(
            incumbent[:-1], lower, upper)
        incumbents.append(incumbent)
        logger.info("Current incumbent %s with estimated performance %f",
                    str(incumbent), incumbent_value)

        # Maximize acquisition function
        acquisition_func.update(model_objective, model_cost)

        new_x = maximizer.maximize()
        new_x[-1] = np.rint(
            new_x[-1])  # Map float value to discrete task variable

        time_overhead.append(time.time() - start_time)
        logger.info("Optimization overhead was %f seconds", time_overhead[-1])

        # Evaluate the chosen configuration
        logger.info("Evaluate candidate %s", str(new_x))
        start_time = time.time()
        new_y, new_c = objective_function(new_x[:-1], new_x[-1])
        time_func_eval.append(time.time() - start_time)

        logger.info("Configuration achieved a performance of %f with cost %f",
                    new_y, new_c)
        logger.info("Evaluation of this configuration took %f seconds",
                    time_func_eval[-1])

        # Add new observation to the data
        X = np.concatenate((X, new_x[None, :]), axis=0)
        y = np.concatenate((y, np.array([new_y])), axis=0)
        c = np.concatenate((c, np.array([new_c])), axis=0)

        runtime.append(time.time() - time_start)

    # Estimate the final incumbent
    model_objective.train(transform(X, lower, upper), y)
    incumbent, incumbent_value = projected_incumbent_estimation(
        model_objective,
        transform(X, lower, upper)[:, :-1],
        proj_value=n_tasks - 1)
    incumbent[:-1] = normalization.zero_one_unnormalization(
        incumbent[:-1], lower, upper)
    incumbents.append(incumbent)
    logger.info("Final incumbent %s with estimated performance %f",
                str(incumbent), incumbent_value)

    results = dict()
    results["x_opt"] = incumbent[:-1]
    results["trajectory"] = [inc for inc in incumbents]
    results["runtime"] = runtime
    results["overhead"] = time_overhead
    results["time_func_eval"] = time_func_eval

    return results