Skip to content

Conversation

j-wilson
Copy link
Contributor

@j-wilson j-wilson commented Oct 26, 2022

This PR contains code for efficiently sampling functions from (approximate) GP priors and posteriors. The functionality introduced here is largely exposed by three high-level methods:

  • gen_kernel_features: Generates a feature map that represents (or approximates) a kernel.

  • draw_kernel_feature_paths: Draws functions from a Bayesian-linear-model-based approximation to a GP prior. By default, uses random Fourier features (RFF) to represent stationary priors.

  • draw_matheron_paths: Generates draws from an approximate GP posterior using Matheron's rule. By default, this method combines draws from an RFF-based approximate prior with exact Gaussian updates. For details, see [Wilson et al., 2020] and [Wilson et al., 2021].

Please let us know if you run into issues. As always, contributions are welcomed.

@facebook-github-bot facebook-github-bot added CLA Signed Do not delete this pull request or issue due to inactivity. fb-exported labels Oct 26, 2022
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D40662482

@codecov
Copy link

codecov bot commented Oct 26, 2022

Codecov Report

Merging #1463 (f52569c) into main (150d673) will not change coverage.
The diff coverage is 100.00%.

@@            Coverage Diff             @@
##              main     #1463    +/-   ##
==========================================
  Coverage   100.00%   100.00%            
==========================================
  Files          155       165    +10     
  Lines        13796     14277   +481     
==========================================
+ Hits         13796     14277   +481     
Impacted Files Coverage Δ
botorch/optim/utils/__init__.py 100.00% <ø> (ø)
botorch/optim/utils/common.py 100.00% <ø> (ø)
botorch/optim/closures/model_closures.py 100.00% <100.00%> (ø)
botorch/optim/fit.py 100.00% <100.00%> (ø)
botorch/optim/utils/numpy_utils.py 100.00% <100.00%> (ø)
botorch/sampling/pathwise/__init__.py 100.00% <100.00%> (ø)
botorch/sampling/pathwise/features/__init__.py 100.00% <100.00%> (ø)
botorch/sampling/pathwise/features/generators.py 100.00% <100.00%> (ø)
botorch/sampling/pathwise/features/maps.py 100.00% <100.00%> (ø)
botorch/sampling/pathwise/paths.py 100.00% <100.00%> (ø)
... and 6 more

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

@hvarfner
Copy link
Contributor

hvarfner commented Nov 3, 2022

Thanks for putting this up - it seems to work like a charm. One question regarding the sampling: It raises a NotImplementedError for FixedNoiseGaussianLikelihood - should the sampler not be used in conjunction with FixedNoiseGP?

It seems to work fine (as in that it runs if I remove the isinstance check) but I haven't checked the correctness of the samples.

@j-wilson
Copy link
Contributor Author

j-wilson commented Nov 4, 2022

@hvarfner Good catch. It should work for FixedNoiseGaussianLikelihoods/FixedNoiseGPs. I simply forgot that _GaussianLikelihoodBase is the base class, not GaussianLikelihood. I'll patch the instance check.

Other than that, there's a trivial dispatch in prior_samples/bayes_linear.py for SingleTaskGPs that simply passes model.num_outputs to a generic method intended for ExactGPs. Long story short: I've moved the model.num_outputs logic into the generic method and removed the SingleTaskGP-specific dispatch. This should ensure that num_outputs gets set correctly for multioutput FixedNoiseGPs.

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D40662482

@hvarfner
Copy link
Contributor

hvarfner commented Nov 8, 2022

@j-wilson Awesome, thanks! After some more usage, it seems like the samplers consistently expect float32. This may be my mistake, but I get a runtime error in the forward call when the input is float64, and I don't really find a way to address it without hacking.

@j-wilson
Copy link
Contributor Author

j-wilson commented Nov 8, 2022

@hvarfner Should be fixed; just needed to specify device and dtype when allocating weights in prior_samplers/bayes_linear.py.

Edge case: May fail for non-float64 ApproximateGPs because GPyTorch's internal Cholesky factor cache is not guaranteed to have the same dtype as the model.

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D40662482

dylanmkennedy added a commit to dylanmkennedy/btsampling that referenced this pull request Dec 9, 2022
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D40662482

1 similar comment
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D40662482

self.initialize(input_shape=x.shape[-1:])

x = x if self.input_transform is None else self.input_transform(x)
z = x @ self.weight.transpose(-2, -1)
Copy link
Contributor

@hvarfner hvarfner Dec 22, 2022

Choose a reason for hiding this comment

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

I'm not 100% certain, but it seems like there's a dimension too many in the weights.In the MultiOutput / FullyBayesian case, we get: self.weight: num_outputs * 1 * num_dim * num_features x: num_outputs * num_queries * num_features`
'z: x @ self.weight.transpose(-2, -1) -->
num_outputs * num_outputs * num_queries * num_features

Not sure how to actually fix this, but the result does not seem to be the desired one.

Finding: self.weight seems to have one dimension too many in these cases, both in AffinePath and GeneralizedLinearBasis. The patchwork fix:
self.weight = self.weight.squeeze(1) here
self.weight = self.weight.squeeze(2) in paths.py#34

This does not affect the single output case as far as I can tell.

Copy link
Contributor Author

@j-wilson j-wilson Dec 22, 2022

Choose a reason for hiding this comment

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

Hey! Thanks for pointing this out. I think there's a good chance you're right that there's something funny going here. Are you using the latest version of this PR (there was a bug in a previous version where num_outputs was not being passed)? If so I would sooner expect
self.weight: batch_shape x num_outputs x num_dim x num_features,
which in many cases would resolve to
self.weight: num_outputs x num_outputs x num_dim x num_features.

Basically, my code (erroneously) views model.batch_shape and multi-output dimensions as separate things whereas BoTorch absorbs the multi-output dimension as part of the batch shape. Time allowing, I'll look into this and hopefully get back to you with a fix. If you happen to have a simple example that reproduces the issue that would be helpful.

Addendum: model.batch_shape does not include the output dimension, so this part was actually correct. The issue is that, e.g., model.covar_module.batch_shape does include the output dimension. For now, I've addressed this by always relying on model.covar_module.batch_shape. @Balandat If possible, it would be nice to unify this convention.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@hvarfner This issue should be resolved in the latest version of the PR. Note that model.covar_module.batch_shape now dictates the batch shape. Among other things, this means that we no longer maintain an explicit output dimension in the non-batch setting.

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D40662482

@dylanmkennedy
Copy link

Great stuff! This is very useful for applications that my group and I at SLAC National Accelerator Laboratory are working on. Are there plans to release a version with these pathwise sampling methods included anytime soon? Thanks!

@j-wilson
Copy link
Contributor Author

j-wilson commented Jan 24, 2023

Great stuff! This is very useful for applications that my group and I at SLAC National Accelerator Laboratory are working on. Are there plans to release a version with these pathwise sampling methods included anytime soon? Thanks!

Hi @dylanmkennedy. Sorry for the delay. Yes, I plan on finalizing an initial release of the pathwise sampling code in the near future (hopefully later this week).

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D40662482

11 similar comments
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D40662482

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D40662482

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D40662482

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D40662482

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D40662482

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D40662482

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D40662482

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D40662482

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D40662482

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D40662482

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D40662482

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D40662482

4 similar comments
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D40662482

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D40662482

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D40662482

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D40662482

Summary:
Pull Request resolved: #1463

This PR contains code for efficiently sampling functions from (approximate) GP priors and posteriors. The functionality introduced here is largely exposed via three high-level methods:

- `draw_kernel_features`: Generates a feature map that represents (or approximates) a kernel.

- `draw_kernel_feature_paths`: Draws functions from a Bayesian-linear-model-based approximation to a GP prior. By default, uses random Fourier features (RFF) to represent stationary priors.

- `draw_matheron_paths`: Generates draws from an approximate GP posterior using Matheron's rule. By default, this method combines draws from an RFF-based approximate prior with exact Gaussian updates. For details, see [[Wilson et al., 2020]](https://arxiv.org/abs/2002.09309#) and [[Wilson et al., 2021]](https://arxiv.org/pdf/2011.04026.pdf).

Please let us know if you run into issues. As always, contributions are welcomed.

Reviewed By: saitcakmak

Differential Revision: D40662482

fbshipit-source-id: fdbcfc1453b2153816fdf169357ec106b6a4926a
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D40662482

@facebook-github-bot
Copy link
Contributor

This pull request has been merged in b3d3074.

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. fb-exported Merged
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants