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

HSGP as component #1246

Merged
merged 38 commits into from
Dec 12, 2024
Merged

HSGP as component #1246

merged 38 commits into from
Dec 12, 2024

Conversation

wd60622
Copy link
Contributor

@wd60622 wd60622 commented Nov 30, 2024

Description

Adding HSGP component which acts a bit more like Prior class than MMM
components but with some plot_curve logic as well.

Bringing back the PR that @bwengals started for better priors for the 1d HSGP

import numpy as np
import pandas as pd

import matplotlib.pyplot as plt

from pymc_marketing.mmm import HSGP

n = 52
X = np.arange(n)

hsgp = HSGP.parameterize_from_data(X=X, dims="time")

dates = pd.date_range("2024-01-01", periods=n, freq="W-MON")
coords = {"time": dates}
prior = hsgp.sample_prior(coords=coords)
curve = prior["f"]
fig, axes = hsgp.plot_curve(curve)
ax = axes[0]
ax.set(xlabel="Time", ylabel="f", title="Out of the box HSGP prior")
plt.show()

hsgp

EDIT: I've implemented this with the HSGP.parameterize_from_data class method:

We might want to refactor this to pull out the defaults instead of having them
as property of the class. Maybe like:

eta: Prior = get_recommended_eta(X)
ell: Prior = get_recommended_ell(X)
hsgp = HSGP(dims="time", eta=eta, ell=ell)

Related Issue

Checklist

Modules affected

  • MMM
  • CLV

Type of change

  • New feature / enhancement
  • Bug fix
  • Documentation
  • Maintenance
  • Other (please specify):

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

Copy link

codecov bot commented Nov 30, 2024

Codecov Report

Attention: Patch coverage is 93.43434% with 26 lines in your changes missing coverage. Please review.

Project coverage is 95.02%. Comparing base (f4d5030) to head (142b107).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
pymc_marketing/mmm/hsgp.py 91.62% 17 Missing ⚠️
pymc_marketing/plot.py 96.40% 6 Missing ⚠️
pymc_marketing/mmm/plot.py 0.00% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1246      +/-   ##
==========================================
- Coverage   95.27%   95.02%   -0.26%     
==========================================
  Files          40       42       +2     
  Lines        4234     4439     +205     
==========================================
+ Hits         4034     4218     +184     
- Misses        200      221      +21     

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

@wd60622 wd60622 linked an issue Nov 30, 2024 that may be closed by this pull request
@wd60622
Copy link
Contributor Author

wd60622 commented Nov 30, 2024

Checkout the documentation section here:
https://pymc-marketing--1246.org.readthedocs.build/en/1246/api/generated/pymc_marketing.hsgp_kwargs.HSGP.html#pymc_marketing.hsgp_kwargs.HSGP

Thoughts on using the create_variable over apply as GP is thought to be a distribution over functions wheras apply is a bit more for transformation of data.

One aspect that is tough is that the new parametrization is different than the HSGPKwargs class and conflicts a bit. This would be a breaking change and require a version increase for MMM class. However, this might be another argument for parameterizing the HSGP with distributions which might be more flexible in the long run. I think there are still some conflicts with this route due to the nature of this.

Would people want to do something like this?

from pymc_marketing.prior import Prior

eta = Prior("HalfNormal", sigma=Prior("HalfNormal"), dims="channel")
ell = Prior("HalfNormal", dims="channel")
hsgp = HSGP(dims=("time", "channel"), eta=eta, ell=ell)

TODO:

  • Add to the components notebook
  • Write test suite for the HSGP component
  • Incorporate into the MMM directly after determining relationship between HSGP and HSGPKwargs currently used.

@cetagostini I was mistaken when I talked out it being hierachical, it is not.
The coefs are draw independently but the basis are all the same which confused me.

hsgp_coefs = Prior(
"Normal",
mu=0,
sigma=sqrt_psd,
dims=hsgp_dims,
centered=self.centered,
).create_variable(f"{name}_hsgp_coefs")

@wd60622
Copy link
Contributor Author

wd60622 commented Nov 30, 2024

Question for @bwengals :
Is there a benefit of centered vs non-centered since sqrt_psd will be a vector and not a random vector of size (m, )? hsgp_coefs will potentially have more dims (*other_dims, m)

@juanitorduz
Copy link
Collaborator

This looks very nice! In the long run, this seems like a nicer approach. As we have not reached a v1.0.0 version I think it's fine that the API changes from time to time

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.

This looks great @wd60622 ! I really like the proposal! A couple of questions and comments:

  • Do we need more tests for the hsgp_kwargs? What is missing in this PR?
  • It would be great to update the GP MMM notebooks (maybe different PR) to showcase this component point of view.
  • Can we also do HSGPPeriodic? I think modeling the media time-varying coefficients as a periodic GP is something we have been asked for.



def pc_prior_1d(alpha: float = 0.1, lower: float = 1.0) -> Prior:
R"""Create a one-dimensional PC prior for GP lengthscale.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we describe what "PC" stands for?

Do we have any references we can add on this?

Copy link

Choose a reason for hiding this comment

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

Penalized complexity. Here's the reference: https://arxiv.org/abs/1503.00256

Copy link

Choose a reason for hiding this comment

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

It'd be nice to have the PC prior available, but IMO a better default prior for PyMC marketing would be InverseGamma, and then have the user give a lower and upper bound, as described here: https://betanalpha.github.io/assets/case_studies/gaussian_processes.html

I think ideally:

  • user specifies a lower bound and prior mass -> PC prior
  • user specifies a lower, upper bound and mass -> InverseGamma

)


def approx_hsgp_hyperparams(
Copy link
Collaborator

Choose a reason for hiding this comment

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

I thought this function was already available in pymc (gp.hsgp_approx.py)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@wd60622
Copy link
Contributor Author

wd60622 commented Nov 30, 2024

This looks great @wd60622 ! I really like the proposal! A couple of questions and comments:

  • Do we need more tests for the hsgp_kwargs? What is missing in this PR?

To do above

  • It would be great to update the GP MMM notebooks (maybe different PR) to showcase this component point of view.

Part of todo for the components notebook. Need to think about how this integrates into MMM and also MMM notebook

  • Can we also do HSGPPeriodic? I think modeling the media time-varying coefficients as a periodic GP is something we have been asked for.

Do you know if the heuristic still works for that one as well?

Copy link

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@github-actions github-actions bot added the docs Improvements or additions to documentation label Dec 2, 2024
Copy link

review-notebook-app bot commented Dec 2, 2024

View / edit / reply to this conversation on ReviewNB

cetagostini commented on 2024-12-02T17:40:49Z
----------------------------------------------------------------

Line #9.    media_tvp_config = {

This should change to something like:

python

edia_tvp_config = {

  "media_tvp_config": HSGPKwargs(..)

}


@cetagostini
Copy link
Contributor

Thoughts on the location of this logic? hsgp_kwargs doesn't seem like a good name and might be good in the mmm module.

Indeed, maybe something related to latent makes more sense to me, or time. If this is a component already, should be under component folders, and the name should be related to what are we trying to model.

We want to model saturation, then we have the saturation component, if we want to model adstock, then we have the adstock component, same thing if we want to model time/latent effects.

@cetagostini
Copy link
Contributor

Question for @bwengals : Is there a benefit of centered vs non-centered since sqrt_psd will be a vector and not a random vector of size (m, )? hsgp_coefs will potentially have more dims (*other_dims, m)

I think should be possible, but better to have @bwengals input here 😅

@juanitorduz
Copy link
Collaborator

hsgp_kwargs

Yes! hsgp_kwargs is a bad name (my fault). You (@wd60622 ) are much better than me at it XD Feel free to push a suggestion

@bwengals
Copy link

bwengals commented Dec 2, 2024

Is there a benefit of centered vs non-centered since sqrt_psd will be a vector and not a random vector of size (m, )? hsgp_coefs will potentially have more dims (*other_dims, m)

Sorry i missed this. Yes sometimes you might want to use the centered parameterization, though non-centered is probably the better default.

@github-actions github-actions bot added the TVPs Related to time varying parameters label Dec 3, 2024
)


def create_m_and_L_recommendations(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we add some references on where these heuristic come from (just the paper reference, ideally the section)

Copy link
Collaborator

Choose a reason for hiding this comment

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

(I think we can use the same ref as above)

).constrain(lower=lower, upper=upper, mass=mass)


def approx_hsgp_hyperparams(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not in the min pymc version that we support. How should we handle?

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.

I actually think this is great for a first iteration and I think we can improve this over time :)

I just left some comments on the references and some apparent dupplicated code from pymc

@wd60622
Copy link
Contributor Author

wd60622 commented Dec 5, 2024

Is there a benefit of centered vs non-centered since sqrt_psd will be a vector and not a random vector of size (m, )? hsgp_coefs will potentially have more dims (*other_dims, m)

Sorry i missed this. Yes sometimes you might want to use the centered parameterization, though non-centered is probably the better default.

Need to double check which I am using as the default. I will set non-centered as default

@wd60622
Copy link
Contributor Author

wd60622 commented Dec 5, 2024

What is the status on drop_first? I am getting warnings

@juanitorduz
Copy link
Collaborator

What is the status on drop_first? I am getting warnings

They will probably go after we support the latest versions (some important fixes were made)

@juanitorduz
Copy link
Collaborator

@wd60622 what is the status on this one :) ?

@wd60622
Copy link
Contributor Author

wd60622 commented Dec 11, 2024

@wd60622 what is the status on this one :) ?

Ready to merge. Will add to example notebooks later

@juanitorduz juanitorduz added this to the 0.11.0 milestone Dec 11, 2024
@wd60622
Copy link
Contributor Author

wd60622 commented Dec 12, 2024

@wd60622 what is the status on this one :) ?

Ready to merge. Will add to example notebooks later

Later like in another PR

@juanitorduz juanitorduz merged commit 45d03ea into main Dec 12, 2024
12 of 13 checks passed
@juanitorduz juanitorduz deleted the bills-hsgp-as-component branch December 12, 2024 10:48
@juanitorduz
Copy link
Collaborator

Merged ! Cool stuff @wd60622 !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs Improvements or additions to documentation enhancement New feature or request maintenance MMM plots Prior class tests TVPs Related to time varying parameters
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Move pymc_marketing.mmm.plot module to pymc_marketing.plot module Pull out TVP as component
4 participants