Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Acquisition function API redesign #447

Merged
merged 25 commits into from
Jul 12, 2024

Conversation

till-m
Copy link
Member

@till-m till-m commented Oct 22, 2023

Redesign the way acquisition functions work.

Content:

  • Deletes the UtilityFunction class and replaces it with a generic AcquisitionFunction base class
  • Delete acq_max, let each acquisition function handle the maximization itself
  • Adds UpperConfidenceBound, ProbabilityOfImprovement and ExpectedImprovement as possible utility functions
  • Adds wrapper acquisition function GPHedge to find which of (a combination of) UCB/PoI/EI are best suited for a problem Implement gp_hedge acquisition function #439
  • Adds wrapper acquisition function KrigingBeliever to allow for async optimization Proper parallel optimisation #347 feat(bayesian_optimization.py): Allow registering of temporary observations #365
  • Adds wrapper acquisition function ConstantLiar to allow for async optimization Proper parallel optimisation #347 feat(bayesian_optimization.py): Allow registering of temporary observations #365. Strategies are min, max, mean and constant (latter chosen by supplying a number).
  • Disallow constrained optimization for UCB -- the constrained optimization relies on the acquisition function being lower-bounded by zero, otherwise the rescaling doesn't make so much sense. While the old implementation seems to have worked sufficiently well, this is more principled.
  • Sets default unconstrained acquisition function to GPHedge with base functions UCB(kappa=2.576), PoI(xi=0.01), EI(xi=0.01). Sets default unconstrained acquisition function to UCB(kappa=2.576)
  • Set GPHedge with base functions PoI(xi=0.01), EI(xi=0.01) as standard acquisition function for constrained improvement Sets default constrained acquisition function to EI(xi=0.01)
  • Make the acquisition function a property of the optimizer (this should mean the the optimizer as a whole is serializable, including the acquisition function, though I haven't actually tested this). This change is breaking as it means suggest, maximize etc. don't take an acquisition function argument anymore.

Why?
The old UtilityFunction and acq_max were the most inflexible part of this package and their design was somewhat convoluted (e.g. providing a xi parameter when using UCB). Now it should be much easier to add custom acquisition functions.

@codecov
Copy link

codecov bot commented Oct 22, 2023

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 96.23%. Comparing base (f2c720e) to head (3d85734).
Report is 1 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #447      +/-   ##
==========================================
+ Coverage   94.68%   96.23%   +1.54%     
==========================================
  Files           9       10       +1     
  Lines         677      849     +172     
==========================================
+ Hits          641      817     +176     
+ Misses         36       32       -4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@till-m till-m marked this pull request as draft October 22, 2023 12:03
@till-m
Copy link
Member Author

till-m commented Nov 23, 2023

Some more changes:

  • Add ConstantLiar
  • fix a bug in exploration_decay
  • fix a bug in KrigingBeliever, where the GP was fitted on the wrong data
  • Adapted the async_optimization.py script to showcase ConstantLiar
  • Reran some notebooks

@fmfn @bwheelz36 @leandrobbraga I will wait with merging this until the docstrings are finished, but if you'd like to give some feedback already, please do.
@pfebrer this contains GPHedge, if you'd like to give some feedback on it.
@Rizhiy I added the constant liar and the kriging believer for async optimization, as well as a script based on your code in examples/async_optimization_dummies.py. Ideally this will eventually become a notebook. According to this, lying is the better strategy, but I wasn't sure whether it would make sense for constrained optimization, so I added the believer for that case.

@bwheelz36
Copy link
Collaborator

Wow this is a huge amount of work. Impressive! Before we start review can you resolve the merge conflicts and make sure all the tests pass?

@till-m
Copy link
Member Author

till-m commented Jan 24, 2024

Before we start review can you resolve the merge conflicts and make sure all the tests pass?

Will do 👍 ideally I want to wait until the docs are finished to only deal with one conflict. After that I will mark the PR as ready to review :)

@till-m till-m mentioned this pull request Jan 31, 2024
3 tasks
@bwheelz36
Copy link
Collaborator

@till-m - will be a breaking redesign? Not necessarily against it, just want to be clear.

@till-m
Copy link
Member Author

till-m commented Mar 6, 2024

@till-m - will be a breaking redesign? Not necessarily against it, just want to be clear.

There will be some necessary breaking changes, primarily to workflows that change the acquisition function -- this is unavoidable, since the old UtilityFunction object has been replaced. I also (intentionally) modified the way the acquisition function is changed -- it is now a property of the optimizer (i.e. not an argument to maximize/suggest). I understand that this can be annoying for some users, but I think in the long run it will be exactly those users that will profit from this change.

If someone just calls .maximize nothing should change. Similarly, suggest-probe-register w/o messing with the acquisition function will not change either.

@till-m till-m mentioned this pull request Apr 27, 2024
@till-m till-m mentioned this pull request Jun 25, 2024
@till-m till-m marked this pull request as ready for review June 29, 2024 09:20
@till-m
Copy link
Member Author

till-m commented Jun 29, 2024

@bwheelz36 I know this is a lot. I'm sorry about that 😬

bayes_opt/bayesian_optimization.py Outdated Show resolved Hide resolved
bayes_opt/acquisition.py Show resolved Hide resolved
return x_max


class GPHedge(AcquisitionFunction):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't want to go overboard and add too many acquisition functions. GPHedge and the ConstantLiar seemed appropriate. EIpu (#393) is additionally showcased in the notebook.

bayes_opt/acquisition.py Outdated Show resolved Hide resolved
bayes_opt/acquisition.py Outdated Show resolved Hide resolved
Copy link
Collaborator

@bwheelz36 bwheelz36 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • great work @till-m. I have very few comments. I agree that this seems cleaner and more maintainable. I haven't used many different acquisition functions, so I don't have any comments on the specific implementations.
  • nitpicking, there's a number of lines if self.y_max is None: which are not covered by a test case. but coverage is >95% which is already extremely high, so if you don't think these need to be covered I'm fine with it.
  • It is a breaking change, so when we release the next version it should be 2.0.0
  • Given the significance of the change, ideally we'd get a review from multiple people before merging. But if no one else chimes in after a week or so I think you should merge.

@till-m
Copy link
Member Author

till-m commented Jun 30, 2024

Coverage is fixed now! :)

Agree on all other points. Thanks for the review! :)

@till-m till-m requested review from fmfn and perezed00 June 30, 2024 14:29
@till-m till-m mentioned this pull request Jul 8, 2024
This was referenced Jul 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants