-
Notifications
You must be signed in to change notification settings - Fork 47
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
Dealing with zero-inflated data #368
Comments
Hi @brandon-holt. Yes, right now, we largely focus on Gaussian data at the moment (this assumption is basically hard-coded in our GP model) and with the upcoming 0.11.0 release, you'll also have the possibility to model binary targets using bandits #343. It is generally planned to make the capabilities broader in all directions, that is, we want to also
Of course, this is not just a matter of configurability but requires actual extensions of our models, such as approximate GP variants. The latter would also generally enable your zero-inflated case. That said, even with the current state of the code, nothing would block you from implementing a surrogate that is tailor-made for zero-inflated data – the necessary machinery is all there, I think. All that is needed is to write a corresponding surrogate model class that either
In such a class, you could train a specialized probabilistic machine learning model that is capable of dealing with zero-inflated data. Nowadays, this can be done rather easily with frameworks such as I'ld love to assist, but I have to be realistic: until the end of this year, I'll very much need to focus on other topics like multi-target support etc. But I'm happy to answer questions if that helps ✌🏼 |
@AdrianSosic I see, thanks for the informed response! How does this approach look for approach 1 (inherit from SurrogateModel base class): import pyro
import pyro.distributions as dist
import torch
from baybe.surrogate_model import SurrogateModel
class ZeroInflatedSurrogateModel(SurrogateModel):
def __init__(self, input_dim, output_dim):
super().__init__()
self.input_dim = input_dim
self.output_dim = output_dim
# Define your model parameters here
def model(self, x, y=None):
# Define the zero-inflated model using Pyro
zero_prob = pyro.param("zero_prob", torch.tensor(0.5))
with pyro.plate("data", x.shape[0]):
zero_inflated = pyro.sample("zero_inflated", dist.Bernoulli(zero_prob))
mean = pyro.param("mean", torch.zeros(self.output_dim))
std = pyro.param("std", torch.ones(self.output_dim))
obs = zero_inflated * 0 + (1 - zero_inflated) * pyro.sample("obs", dist.Normal(mean, std))
if y is not None:
pyro.sample("obs", dist.Normal(mean, std), obs=y)
def fit(self, x, y):
# Fit the model to the data
pyro.clear_param_store()
svi = pyro.infer.SVI(model=self.model, guide=self.guide, optim=pyro.optim.Adam({"lr": 0.01}), loss=pyro.infer.Trace_ELBO())
num_steps = 1000
for step in range(num_steps):
loss = svi.step(x, y)
if step % 100 == 0:
print(f"Step {step} : loss = {loss}")
def predict(self, x):
# Predict using the fitted model
predictive = pyro.infer.Predictive(self.model, guide=self.guide, num_samples=1000)
samples = predictive(x)
return samples["obs"].mean(0)
def guide(self, x, y=None):
# Define the guide for variational inference
zero_prob = pyro.param("zero_prob", torch.tensor(0.5))
mean = pyro.param("mean", torch.zeros(self.output_dim))
std = pyro.param("std", torch.ones(self.output_dim))
with pyro.plate("data", x.shape[0]):
zero_inflated = pyro.sample("zero_inflated", dist.Bernoulli(zero_prob))
pyro.sample("obs", dist.Normal(mean, std)) And then to use the custom model campaign.recommender.recommender.surrogate_model = ZeroInflatedSurrogateModel(input_dim, output_dim)
|
Hi @brandon-holt, please apologize the delay, I'm traveling since two weeks and will be OOO till early October. Writing from my phone, hence very limited capabilities and will not include any links/code. To answer your question:
In both cases, what will be required in the end (and what is missing in your outlined approach) is that your class is able to produce a Posterior object for an arbitrary set of candidat points. This is a mathematical requirement to enable proper batch prediction in the Bayesian optimization sense. The good news: you are almost there. Since you have coded a model that is inherently probabilistic, you already have all necessary pieces available. Just wrap your predictions in an appropriate Posterior object instead of projecting down to mean values only. Have a look at our existing GP or RandomForest model to see how it can be done or check out Botorchs doc page on posterior objects. Once this is done, you should be able to run it. And yes, you'll then completely bypass any Gaussianity assumption whatsoever. Hope that helps 👌 happy to help you further, but probably with some delay involved. But I'm sure that @Scienfitz and @AVHopp can also point you to the right pages in our or botorchs docs if needed 🙃 |
I was wondering if there are any built-in options for transforming or handling zero-inflated data? My understanding is that this process works best with gaussian-distributed data.
@AdrianSosic @Scienfitz
The text was updated successfully, but these errors were encountered: