SheffieldML / GPyOpt

Gaussian Process Optimization using GPy
BSD 3-Clause "New" or "Revised" License
927 stars 261 forks source link

maximize flag has no effect when f is None #180

Open mhwalker opened 6 years ago

mhwalker commented 6 years ago

Basically what title says. When using GPyOpt to optimize an externally evaluated function, the maximize flag has no effect.

I would expect this snippet to maximize based on the inputs: Snippet 1:

X_data = np.array([ [1.0, 1.5, 1.0], [1.5, 3.0, 1.0], 
                   [2.0, 5.0, 2.0]])
Y_data = np.array([ [0.7248], [0.4579],
                   [0.4192]])
bo_step = GPyOpt.methods.BayesianOptimization(f=None, domain=domain, X=X_data, Y=Y_data, maximize=True, acquisition_type='EI')
x_next = bo_step.suggest_next_locations()
x_next

array([[1.93984549, 4.90429719, 1.9519504 ]])

This snippet gives the result that I expect. Snippet 2:

X_data = np.array([ [1.0, 1.5, 1.0], [1.5, 3.0, 1.0], 
                   [2.0, 5.0, 2.0]])
Y_data = np.array([ [-0.7248], [-0.4579],
                   [-0.4192]])
bo_step = GPyOpt.methods.BayesianOptimization(f=None, domain=domain, X=X_data, Y=Y_data, maximize=False, acquisition_type='EI')
x_next = bo_step.suggest_next_locations()
x_next

array([[0.95508769, 1.42728523, 1.019358 ]])

Not sure if this is the designed behavior, but I think the naive expected behavior is that Y should be transformed to -Y internally if maximize=True

mhwalker commented 6 years ago

Also, I didn't follow the code fully, but I think that if Y_init is provided with maximize=True, the initialization is not correct (unless user is aware that -Y_init should be provided).

gdikov commented 5 years ago

GPyOpt version is 1.2.5

I also got confused by the maximize flag. The following example reproduces the unexpected behaviour:

import GPyOpt
import numpy as np
import matplotlib.pyplot as plt

def foo(val):
    return (np.sin(val * 8) * val - val ** 2 + val)

def plot_samples(samples_x, samples_y):
    xs = np.arange(-5.0, 5.0, 0.01)
    ys = foo(xs)
    plt.plot(xs, ys)
    plt.plot(samples_x, samples_y, "*r")

bounds = [{'name': 'x', 'type': 'continuous', 'domain': (-5.0, 5.0)}]
max_iter = 20

xs = np.array([[-5.0]])
ys = foo(xs)

for i in range(max_iter):
    bo_gp = GPyOpt.methods.BayesianOptimization(
        f=None, 
        domain=bounds, 
        model_type="GP", 
        acquisition_type ="EI", 
        maximize=True, 
        initial_design_numdata=len(xs),
        X=xs, 
        Y=ys,
        exact_feval=True)

    new_x = bo_gp.suggest_next_locations()
    xs = np.concatenate([xs, new_x])
    ys = np.concatenate([ys, foo(new_x)])

plot_samples(xs, ys)

resulting in:

BO

However, if you change Y=ys to Y=-ys the optimisation produces results as expected and neither of the options maximize=False and maximize=True have any noticeable effect on the quality of the samples:

BO2

dorian821 commented 5 years ago

I'm struggling with the same confusion. I've resorted to simply taking the negative of the objective value as mentioned above, but confused by the necessity for this.

LarsHH commented 5 years ago

I've also just discovered this issue after a while. Would be nice if this it was pointed out in the documentation since I've run quite a few things without being aware of this.

F-A commented 5 years ago

The problem is that GPyOpt changes a minimization problem into a maximization one by simply changing the sign of the evaluation function: https://github.com/SheffieldML/GPyOpt/blob/c9e214c49f57af4c7ee92d94ab859f46d65fd842/GPyOpt/methods/bayesian_optimization.py#L106

I guess there is no easy fix for this issue, but maybe one could issue a warning when maximize=True and f=None, so that users know the maximization will not be effective...