EmuKit / emukit

A Python-based toolbox of various methods in decision making, uncertainty quantification and statistical emulation: multi-fidelity, experimental design, Bayesian optimisation, Bayesian quadrature, etc.
https://emukit.github.io/emukit/
Apache License 2.0
591 stars 128 forks source link

question on Emukit for engineering optimization #189

Closed polivucci closed 5 years ago

polivucci commented 5 years ago

Hi EmuKit team,

I'm interested in applying the Bayesian Optimization toolkit with GP regression to a problem of flow control.

I would like to kindly ask you a couple of (maybe very naive) questions:

Thank you very much for your time and advice

javiergonzalezh commented 5 years ago

Hi @polivucci,

Thanks for your interest in the library! These are some answers to your questions:

One question: do you have access to a cheaper turbulent flow simulation. If you had you could try to do some multi-fidelity optimization.

Hope this helps!

polivucci commented 5 years ago

Hi @javiergonzalezh ,

thanks a lot for your answer.

I have seen the multi-fidelity notebook and I think it is of great interest for fluid simulations as it is common practice to use a cheaper model whenever possible and then step up for the more promising cases. For my specific problem however, the cost of a simulation is not impossibly high so it makes sense to stick to the high-fidelity solver for now.

Also I know no straightforward way of guessing a dependence structure neither for the mean nor for the covariance. The only thing I know is that K is most likely anisotropic and ARD is needed. The exact function is bounded on the domain considered, but I can't say much on its smoothness.

Based on your suggestions, it seems a good start can be Matern52 (ARD) with IntegratedExpectedImprovement acquisition.

Another interesting point for me is how many initial data to provide before starting to evaluate the acquisition function. I'm using the Latin Hypercube sampling and a rule of thumb I knew was 3*n_variables. Not sure however for Bayesian Optimization and with so little information about the underlying function.

many thanks for the discussion!

polivucci commented 5 years ago

Dear Emukit team,

I have tried to add the handling of unknown constraints to my engineering optimization with EmuKit. It is a rough attempt based on the paper Gelbart et al., 2014. Is there some code already being developed along these lines?

I have defined a new acquisition called ConstrainedIntegratedExpectedImprovement (a clone of IntegratedExpectedImprovement ) that accepts two GP models, one for the objective and one for the constraints, and returns the acquisition as defined in the paper. The acquisition is just the product of the standard EI on the target function times the probability of satisfying the constraints (for which the standard PoI can be easily adapted).

However I am no sure of how to define a Bayesian Loop that can handle two (or more) models and handle them consistently. I have seen that a Multi Output model is available and perhaps can be adapted. For now I use BayesianOptimizationLoop and I manually update the constraint model at each iteration using model.set_XY(Xc,Yc)

I have tested this approach on the Branin function as seen in Gelbart et al., 2014 and I think the results loosely agree, even if the objective function regression looks a bit strange to me.

constr_full_ard

Thanks for any comment,

PO

apaleyes commented 5 years ago

Hey @polivucci . Thanks for the update.

This is not something we have right out of the box at the moment, but it should be very easy to adapt Emukit for this use case.

If you take a look at our bayes opt loop here, it isn't super sophisiticated. Basically it just instantiates a bunch of parameters and passes them to OuterLoop. At the moment it creates one model updater, however OuterLoop can accept a list of them and handle it just fine.

So all you need to do, besides using your acquisition, which sounds like it works already, is to create two model updaters, one per model. You can copy over existing bayes opt loop, rewrite the line that creates those updates, and that should do it. As a matter of fact, cost sensitive bayes opt loop which we already have, does exactly that.

Hope it helps

javiergonzalezh commented 5 years ago

Another comment on this one. This PR generalizes the integrated EI to all acquisitions in the library. You may want to look into it before building your your loop as what you probably need is some ConstrainedIntegratedAcquisition that takes the EI as input.

polivucci commented 5 years ago

Hi @apaleyes and @javiergonzalezh ,

many thanks for the precious help.

I will post back here as soon as I have the time to work out your suggestions.

PO

javiergonzalezh commented 5 years ago

Great! thanks a lot!

polivucci commented 5 years ago

Hi @apaleyes and @javiergonzalezh,

I've found some time to adjust the code, I hope it makes sense. Hopefully you have some remarks on better/smarter ways to implement this.

1) BO loop: I used a modified version of the CostSensitiveBayesianOptimizationLoop which I called ConstrainedBayesianOptimizationLoop. The only differences are the use of the constraint instead of the cost and the acquisition function that is different. I did not change anything in loop_state, I simply used the already available cost variable to store the constraint evaluations. Not sure how easily this can be generalised to more than one constraint (not strictly needed by me at the moment).

2) Integrated Acquisition: I have used IntegratedHyperParameterAcquisition straight away with no change. Since by default it runs MCMC using the evaluator of a single-model acquisition, IntegratedHyperParameterAcquisition had to be applied individually to the objective and the constraint evauators (obj and constr being independent). In summary, I defined ConstrainedExpectedImprovement such that:

acquisition_objective = IntegratedHyperParameterAcquisition(model_obj,ExpectedImprovement)
acquisition_constraint = IntegratedHyperParameterAcquisition(model_constr,ProbabilityOfFeasibility)
acquisition = ConstrainedExpectedImprovement(acquisition_objective,acquisition_constraint)

where inside ConstrainedExpectedImprovement I defined:

def evaluate(self, x: np.ndarray) -> np.ndarray:
   return acquisition_objective.evaluate(x) * acquisition_constraint.evaluate(x)

and likewise w/ gradients. ConstrainedBayesianOptimizationLoop takes in acquisition together with the two models.

I have run some Branin-Hoo tests and it seems to work as expected. Not yet tested for batch_size>1.

thanks again, PO

javiergonzalezh commented 5 years ago

This makes a lot of sense to me.

Something you can do to simplify your code is to define your acquisition as the product of EI and the constraint. If you do acquisition = acquisition_objective * acquisition_constraint everything should work as we have an internal algebra for acquisition objects. This way you don't have to hard code the ConstrainedExpectedImprovement and you don't have to worry about the gradients of the new acquisition that you are building.

If you want to do a PR we can have a look to the code in more detail.

polivucci commented 5 years ago

Hi @javiergonzalezh,

I have created the PR, I hope it's done properly. Looking forward for your feedback

cheers, PO

apaleyes commented 5 years ago

Closing, as the PR is now merged. Thanks for your contribution!

polivucci commented 5 years ago

thanks! It has been very instructive. I'm applying the code to my research and shortly some results will be available.

cheers, PO