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

Use SoftPlusHSGP in multidimensional HSGP #1510

Conversation

wd60622
Copy link
Contributor

@wd60622 wd60622 commented Feb 18, 2025

Description

This might still differ from the other implementation where the HSGP intercept has a baseline which is then multiplied by HSGP:

baseline_intercept = self.model_config["intercept"].create_variable(
"baseline_intercept"
)
intercept_latent_process = create_time_varying_gp_multiplier(
name="intercept",
dims="date",
time_index=time_index,
time_index_mid=self._time_index_mid,
time_resolution=self._time_resolution,
hsgp_kwargs=self.model_config["intercept_tvp_config"],
)
intercept = pm.Deterministic(
name="intercept",
var=baseline_intercept * intercept_latent_process,
dims="date",
)

Another alternative is to build that part into the HSGP model itself. However, the mmm would require another prior for the intercept. Which I think is good to keep separate. We can always wrap that logic into a separate function like in MuEffect

class MuEffect(Protocol):
"""Protocol for arbitrary additive mu effect."""
def create_data(self, mmm: MMM) -> None:
"""Create the required data in the model."""
def create_effect(self, mmm: MMM) -> pt.TensorVariable:
"""Create the additive effect in the model."""
def set_data(self, mmm: MMM, model: pm.Model, X: xr.Dataset) -> None:
"""Set the data for new predictions."""

Thoughts?

Related Issue

  • Closes #
  • Related to #

Checklist


📚 Documentation preview 📚: https://pymc-marketing--1510.org.readthedocs.build/en/1510/

@github-actions github-actions bot added MMM bug Something isn't working labels Feb 18, 2025
Copy link

codecov bot commented Feb 18, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 92.75%. Comparing base (26e80c0) to head (b9bbcd4).
Report is 2 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1510   +/-   ##
=======================================
  Coverage   92.74%   92.75%           
=======================================
  Files          52       52           
  Lines        6120     6126    +6     
=======================================
+ Hits         5676     5682    +6     
  Misses        444      444           

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

media_latent_process = HSGP.parameterize_from_data(
media_latent_process = SoftPlusHSGP.parameterize_from_data(
Copy link
Collaborator

Choose a reason for hiding this comment

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

@wd60622 can you please explain the motivation behind the softplus transform? 🙏

Copy link
Contributor Author

Choose a reason for hiding this comment

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

  • Aligns the default hsgp with other MMM class
  • remove negative channel contributions with time varying media = True

Copy link
Collaborator

Choose a reason for hiding this comment

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

Thanks @wd60622 ! Would you mind running the time-varying parameter notebooks affected by this change just to control the expected result? 🙏

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is there a multidimensional mmm notebook already? This is just the new class

Copy link
Collaborator

Choose a reason for hiding this comment

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

Right, but in theory you could reproduce the results of the MMM basic class with this object right? The intention is not to update the docs but maybe have some experiments on the effect of this parametrization. I think you can just share some plots or experiments 9for the sake of illustrating the benefits) :) Just for future reference. It is not a blocker, but more to have a bit more intuition WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure. I can update
However, there is still slight difference in the intercept which I noted. Should that be consolidated?

Thoughts @cetagostini

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I will make sure that the baseline is in. I think without it might be too inflexible.

@wd60622
Copy link
Contributor Author

wd60622 commented Feb 19, 2025

This is an adapted version of the other MMM intercept:

import pandas as pd
import pymc as pm

import matplotlib.pyplot as plt

from pymc_marketing.mmm import SoftPlusHSGP

n_dates = 52 * 2

dates = pd.date_range("2025-01-01", periods=n_dates, freq="W-MON")

X = (dates - dates[0]).days.values

hsgp = SoftPlusHSGP.parameterize_from_data(X, ls_lower=10, ls_upper=25, dims="date")

coords = {"date": dates}
with pm.Model(coords=coords) as model:
    name = "intercept"
    intercept_baseline = pm.Gamma(f"{name}_baseline", mu=3, sigma=1)
    intercept_moving = hsgp.create_variable(f"{name}_multiplier")

    intercept = pm.Deterministic(
        name,
        intercept_baseline * intercept_moving,
        dims=hsgp.dims,
    )

    idata = pm.sample_prior_predictive()


prior = idata.prior

from pymc_marketing.plot import plot_curve

prior["intercept"].pipe(plot_curve, {"date"})
plt.show()

Results in:

intercept-example

Note

Without the baseline, the intercept is just centered around 1.

Copy link
Collaborator

@juanitorduz juanitorduz left a comment

Choose a reason for hiding this comment

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

Thanks for the example @wd60622 !

@wd60622
Copy link
Contributor Author

wd60622 commented Feb 19, 2025

Realizing that the current implementation does that have baseline and multiplier concept

baseline_intercept = self.model_config["intercept"].create_variable(
"baseline_intercept"
)
intercept_latent_process = SoftPlusHSGP.parameterize_from_data(
X=time_index, # this is
dims=("date", *self.dims),
**self.model_config["intercept_tvp_config"],
).create_variable("intercept_latent_process")
intercept = pm.Deterministic(
name="intercept_contribution",
var=baseline_intercept[None, ...] * intercept_latent_process,
dims=("date", *self.dims),
)

So merging this now!

@wd60622 wd60622 merged commit ae0b2d3 into main Feb 19, 2025
21 checks passed
@wd60622 wd60622 deleted the 1508-hsgp-not-center-at-1-and-being-positive-in-the-multidimensional-module branch February 19, 2025 20:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working MMM
Projects
None yet
Development

Successfully merging this pull request may close these issues.

HSGP Not center at 1 and being positive in the multidimensional module.
2 participants