Skip to content

NP Regression Model w/ LIG Acquisition #2683

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

Open
wants to merge 33 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
9304881
Latent Information Gain
eibarolle Jan 18, 2025
7a8e4ab
NP Regression
eibarolle Jan 18, 2025
5f0dba0
Test NP Regression
eibarolle Jan 18, 2025
c55d7a9
Test Latent Information Gain
eibarolle Jan 18, 2025
657151f
NP Regression Documentation
eibarolle Jan 18, 2025
4f35e0f
1/25 Updates
eibarolle Jan 25, 2025
280776d
1/25 Updates
eibarolle Jan 25, 2025
a811429
1/25 Updates
eibarolle Jan 25, 2025
50fe7a1
1/25 Updates
eibarolle Jan 25, 2025
9684e1d
Merge branch 'main' into np_regression
eibarolle Jan 25, 2025
4aeeeeb
Update Acquisition Dimensions
eibarolle Feb 2, 2025
be34f60
Updated Test Files
eibarolle Feb 2, 2025
204ba31
Updated LIG Parameters/Generalizability
eibarolle Mar 6, 2025
8e33fc4
Updated NPR Compatability
eibarolle Mar 6, 2025
7232725
Updated NPR Parameters
eibarolle Mar 11, 2025
d78d262
LIG WIP
eibarolle Mar 11, 2025
32916b9
Updated Tests
eibarolle Mar 11, 2025
e13f38c
Test LIG WIP
eibarolle Mar 11, 2025
bf95d41
LIG Updated Parameters
eibarolle Mar 21, 2025
046f609
NPR Updated Parameters
eibarolle Mar 21, 2025
4c037c5
LIG Updated Tests
eibarolle Mar 21, 2025
e7c964d
NPR Updated Tests
eibarolle Mar 21, 2025
96d2bb4
Update Parameters
eibarolle Mar 24, 2025
c4f5f87
Update Parameters
eibarolle Mar 24, 2025
529e36c
Update Parameters
eibarolle Mar 24, 2025
0e28077
April Updates
eibarolle Apr 29, 2025
0ceb9ca
April Updates
eibarolle Apr 29, 2025
9949ff9
April Tests
eibarolle Apr 29, 2025
2c9c958
April Tests
eibarolle Apr 29, 2025
918a4b4
5/16 Updates
eibarolle May 17, 2025
fe75f43
Recent Fixes
eibarolle May 17, 2025
badba20
Fixing merge conflicts for acquisition/models docs
eibarolle May 17, 2025
43d8c32
Merge branch 'main' into np_regression
eibarolle May 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 117 additions & 0 deletions botorch_community/acquisition/latent_information_gain.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#!/usr/bin/env python3
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

r"""
Latent Information Gain Acquisition Function for Neural Process Models.

References:

.. [Wu2023arxiv]
Wu, D., Niu, R., Chinazzi, M., Vespignani, A., Ma, Y.-A., & Yu, R. (2023).
Deep Bayesian Active Learning for Accelerating Stochastic Simulation.
arXiv preprint arXiv:2106.02770. Retrieved from https://arxiv.org/abs/2106.02770

Contributor: eibarolle
"""

from __future__ import annotations

from typing import Any, Type

import torch
from botorch.acquisition import AcquisitionFunction
from botorch_community.models.np_regression import NeuralProcessModel
from torch import Tensor
# reference: https://arxiv.org/abs/2106.02770


class LatentInformationGain(AcquisitionFunction):
def __init__(
self,
model: Type[Any],
num_samples: int = 10,
min_std: float = 0.01,
scaler: float = 0.5,
) -> None:
"""
Latent Information Gain (LIG) Acquisition Function.
Uses the model's built-in posterior function to generalize KL computation.

Args:
model: The model class to be used, defaults to NeuralProcessModel.
num_samples: Int showing the # of samples for calculation, defaults to 10.
min_std: Float representing the minimum possible standardized std,
defaults to 0.01.
scaler: Float scaling the std, defaults to 0.5.
"""
super().__init__(model)
self.model = model
self.num_samples = num_samples
self.min_std = min_std
self.scaler = scaler

def forward(self, candidate_x: Tensor) -> Tensor:
"""
Conduct the Latent Information Gain acquisition function for the inputs.

Args:
candidate_x: Candidate input points, as a Tensor. Ideally in the shape
(N, q, D).

Returns:
torch.Tensor: The LIG scores of computed KLDs, in the shape (N, q).
"""
device = candidate_x.device
candidate_x = candidate_x.to(device)
N, q, D = candidate_x.shape
kl = torch.zeros(N, device=device, dtype=torch.float32)

if isinstance(self.model, NeuralProcessModel):
x_c, y_c, _, _ = self.model.random_split_context_target(
self.model.train_X, self.model.train_Y, self.model.n_context
)
self.model.z_mu_context, self.model.z_logvar_context = (
self.model.data_to_z_params(x_c, y_c)
)

for i in range(N):
Copy link
Contributor

Choose a reason for hiding this comment

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

Can this for loop be eliminated using batched computation?

x_i = candidate_x[i]
kl_i = 0.0

for _ in range(self.num_samples):
Copy link
Contributor

Choose a reason for hiding this comment

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

Same with this for loop

sample_z = self.model.sample_z(
self.model.z_mu_context, self.model.z_logvar_context
)
if sample_z.dim() == 1:
sample_z = sample_z.unsqueeze(0)

y_pred = self.model.decoder(x_i, sample_z)

combined_x = torch.cat([x_c, x_i], dim=0)
combined_y = torch.cat([y_c, y_pred], dim=0)

self.model.z_mu_all, self.model.z_logvar_all = (
self.model.data_to_z_params(combined_x, combined_y)
)
kl_sample = self.model.KLD_gaussian(self.min_std, self.scaler)
kl_i += kl_sample

kl[i] = kl_i / self.num_samples

else:
for i in range(N):
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we replace these loops with batched computation too?

x_i = candidate_x[i]
kl_i = 0.0
for _ in range(self.num_samples):
posterior_prior = self.model.posterior(self.model.train_X)
posterior_candidate = self.model.posterior(x_i)

Check warning on line 110 in botorch_community/acquisition/latent_information_gain.py

View check run for this annotation

Codecov / codecov/patch

botorch_community/acquisition/latent_information_gain.py#L105-L110

Added lines #L105 - L110 were not covered by tests

kl_i += torch.distributions.kl_divergence(

Check warning on line 112 in botorch_community/acquisition/latent_information_gain.py

View check run for this annotation

Codecov / codecov/patch

botorch_community/acquisition/latent_information_gain.py#L112

Added line #L112 was not covered by tests
posterior_candidate.mvn, posterior_prior.mvn
).sum()

kl[i] = kl_i / self.num_samples

Check warning on line 116 in botorch_community/acquisition/latent_information_gain.py

View check run for this annotation

Codecov / codecov/patch

botorch_community/acquisition/latent_information_gain.py#L116

Added line #L116 was not covered by tests
return kl
Loading