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

An option to give priors & constraints #108

Open
mekazanc opened this issue Jan 29, 2025 · 1 comment
Open

An option to give priors & constraints #108

mekazanc opened this issue Jan 29, 2025 · 1 comment

Comments

@mekazanc
Copy link

Hello, I have two questions.

1- Can we give some prior info for the control variables ? e.g. I want to inform model for some variables that they may have positive or negative coefficients.

2- I observed that some simulations are giving negative predictions at beginning duration (e.g. 1st week) or at the following days at random time. This does not makes sense in terms of product output. Can we inform model to consider this constraint ?

Thank you very much

@WillianFuks
Copy link
Owner

Hi @mekazanc ,

I've experimented with "hacky" solutions to see if I could force the Linear Gaussian BSTS model to return only positive values but couldn't make it work so far. Here's the path I was experimenting with:

import pandas as pd
import numpy as np
from causalimpact import CausalImpact
import tensorflow_probability as tfp

tfd = tfp.distributions
tfb = tfp.bijectors


X = np.random.normal(loc=0, scale=1, size=100)
y = 1.2 * X
data = pd.DataFrame({'y': y, 'X': X})
data.iloc[70:, 0] += 1

pre_period = [0, 69]
post_period = [70, 99]
obs_series = data.iloc[:pre_period[1], 0].astype(np.float32)


class PositiveLocalLevel(tfp.sts.LocalLevel):
    def __init__(self, observed_time_series):
        super().__init__(observed_time_series=observed_time_series)

    def _build_initial_state_prior(self, initial_mean_prior=None, initial_scale_prior=None):
        if initial_mean_prior is None:
            initial_mean_prior = tfd.LogNormal(loc=0., scale=1.)
        if initial_scale_prior is None:
            initial_scale_prior = tfd.HalfNormal(scale=1.0)
        return super()._build_initial_state_prior(initial_mean_prior, initial_scale_prior)

    def _build_transition_noise(self, **kwargs):
        return tfd.TransformedDistribution(
            distribution=tfd.Normal(loc=0.0, scale=1.0),
            bijector=tfb.Exp()
        )


level_component = PositiveLocalLevel(observed_time_series=obs_series)

model = tfp.sts.Sum([level_component], observed_time_series=obs_series)
ci = CausalImpact(data, pre_period, post_period, model=model,
                  model_args={'standardize': False})


print(ci.summary())
print(ci.summary(output='report'))
ci.plot()

but model.prior_sample(50) returned negative values.

In summary, I'm not sure how we could force the model to only predict positive values. Maybe tensorflow probability team could give some ideas, I'll leave this one open for now until we find something that may help.

This probably answers your first question as well, as you can see in the example above, it's possible to use customized models that follows distributions that you like. Still, so far I couldn't find a way to force those constrictions on the priors used.

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

No branches or pull requests

2 participants