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

Add TopK downselection for initial batch generation. #2636

Closed
wants to merge 22 commits into from

Conversation

CompRhys
Copy link
Contributor

@CompRhys CompRhys commented Nov 20, 2024

Motivation

In order to get facebook/Ax#2938 over the line with initial candidate generation that obey the constraints we want to use the existing tooling within botorch. The hard coded logic currently in Ax uses topk to downselect the sobol samples. To make a change there that will not impact existing users we then need to implement topk downselection in botorch.

Test Plan

TODO:

  • add tests for initialize_q_batch_topk

Related PRs

facebook/Ax#2938. (#2610 was initially intended to play part of this solution but then I realized that the pattern I wanted to use was conflating repeats and the batch dimension.)

@facebook-github-bot facebook-github-bot added the CLA Signed Do not delete this pull request or issue due to inactivity. label Nov 20, 2024
Copy link
Contributor

@Balandat Balandat left a comment

Choose a reason for hiding this comment

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

couple of small nits, o/w this looks great.

botorch/optim/initializers.py Outdated Show resolved Hide resolved
botorch/optim/initializers.py Show resolved Hide resolved
botorch/optim/initializers.py Outdated Show resolved Hide resolved
botorch/utils/sampling.py Outdated Show resolved Hide resolved
@facebook-github-bot
Copy link
Contributor

@Balandat has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

@saitcakmak
Copy link
Contributor

Other initializers use Boltzmann sampling through initialize_q_batch helper to achieve a more diverse set of ICs. The motivation is that this will hopefully lead to different local-optima, making it more likely to discover the global optimum. If you have multiple raw samples that are close by, TopK can get you ICs that all lead to the same local optima. Should we follow the same logic in initialize_q_batch instead?

@Balandat
Copy link
Contributor

That would make sense, I'd be interested in seeing a benchmark how that affects performance of SEBO

@CompRhys
Copy link
Contributor Author

I would be entirely happy to not merge this if it will end up as dead code if theres a decision to swap the ic default for SEBO to use Boltzmann sampling. The motivation here was that I want to use the polytope sampling from botorch such that I can add inequality constraints to SEBO, adding a bunch of switching logic is bad in terms of maintenance there so the minimal change to keep the same behavior for how it's currently setup is to add this here.

The longer term idea for the cleanest way to do it I had was based on this #2610 where SEBO default could just pass the X_pareto points as initial batch conditions and then have botorch just fill up the rest of the requested n_restarts without needing to call anything in Ax from botorch to do the initial sampling that currently uses topk to get 1/2 of the initial conditions.

Copy link

codecov bot commented Nov 25, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 99.98%. Comparing base (4190f74) to head (975bb29).
Report is 4 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff            @@
##             main    #2636    +/-   ##
========================================
  Coverage   99.98%   99.98%            
========================================
  Files         196      198     +2     
  Lines       17410    17910   +500     
========================================
+ Hits        17408    17908   +500     
  Misses          2        2            

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

botorch/optim/initializers.py Outdated Show resolved Hide resolved
botorch/utils/sampling.py Outdated Show resolved Hide resolved
Comment on lines 288 to 291
for dtype in (torch.float, torch.double):
bounds = bounds.to(device=self.device, dtype=dtype)
mock_acqf.X_baseline = bounds # for testing sample_around_best
mock_acqf.model = MockModel(MockPosterior(mean=bounds[:, :1]))
Copy link
Contributor

Choose a reason for hiding this comment

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

if you pull this into the product() below you can save one indent ...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

happy to change this but it matches the other testcases perhaps to avoid reassigning lines 289-291 in every iteration of the product. If I change here will change in all the equivalent tests for consistency.

Copy link
Contributor

Choose a reason for hiding this comment

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

Fair enough. I think we can go either way here. FWIW the overhead of reassigning lines 289-291 in every iteration should be negligible.

@esantorella
Copy link
Member

esantorella commented Dec 2, 2024

Thank you! The tutorial failure is unrelated.

@esantorella
Copy link
Member

Could you update the documentation for the options argument to gen_batch_initial_conditions? It might be too much work to explain all of the possible options, but it would be good to at least document the options newly added here such as topn. Thanks again for getting this in!

test/optim/test_initializers.py Outdated Show resolved Hide resolved
test/optim/test_initializers.py Outdated Show resolved Hide resolved
@CompRhys
Copy link
Contributor Author

CompRhys commented Dec 5, 2024

@saitcakmak is there anything blocking this currently or can it be merged such that facebook/Ax#2938 can hopefully be merged in short term?

@facebook-github-bot
Copy link
Contributor

@saitcakmak has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

@saitcakmak
Copy link
Contributor

Shouldn't be any blockers. I'll work with @Balandat to get this landed

@saitcakmak
Copy link
Contributor

We have a test failure when running on GPU. Looks like cuda & cpu tensors are being mixed together somewhere.

test: test_gen_batch_initial_conditions_highdim (optim.test_initializers.TestGenBatchInitialCandidates)
error: Traceback (most recent call last):
  File "/re_cwd/buck-out/v2/gen/fbcode/03967c653c571e2c/pytorch/botorch/__test_optim_cuda__/test_optim_cuda#link-tree/pytorch/botorch/test/optim/test_initializers.py", line 383, in test_gen_batch_initial_conditions_highdim
    batch_initial_conditions = gen_batch_initial_conditions(
  File "/re_cwd/buck-out/v2/gen/fbcode/03967c653c571e2c/pytorch/botorch/__test_optim_cuda__/test_optim_cuda#link-tree/botorch/optim/initializers.py", line 378, in gen_batch_initial_conditions
    X_rnd = unnormalize(
  File "/re_cwd/buck-out/v2/gen/fbcode/03967c653c571e2c/pytorch/botorch/__test_optim_cuda__/test_optim_cuda#link-tree/botorch/utils/transforms.py", line 129, in unnormalize
    return X * (bounds[1] - bounds[0]) + bounds[0]
RuntimeError: Expected all tensors to be on the same device, but found at least two devices, cuda:0 and cpu!

X & bounds must be on different devices here. Since it is a single test failure, it could just be on the specific test

)
with warnings.catch_warnings(record=True) as ws:
warnings.simplefilter("ignore", category=BadInitialCandidatesWarning)
batch_initial_conditions = gen_batch_initial_conditions(
Copy link
Contributor

Choose a reason for hiding this comment

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

The failure is on this line. X is generated internally and bounds is on the correct device above. So, the code generating X must be keeping it on CPU

@facebook-github-bot
Copy link
Contributor

@saitcakmak has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

@facebook-github-bot
Copy link
Contributor

@saitcakmak merged this pull request in c1eb255.

@CompRhys CompRhys deleted the topk-icgen branch December 14, 2024 16:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed Do not delete this pull request or issue due to inactivity. Merged
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants