pymc-labs / pymc-marketing

Bayesian marketing toolbox in PyMC. Media Mix (MMM), customer lifetime value (CLV), buy-till-you-die (BTYD) models and more.
https://www.pymc-marketing.io/
Apache License 2.0
587 stars 138 forks source link

R2D2M2 prior for Saturated MMM #381

Open ferrine opened 9 months ago

ferrine commented 9 months ago

The existing MMM can be improved with variance decomposition framework, r2d2m2, which is plug and play into the existing code

r2 = pm.Beta("r2", mu=0.8, sigma=0.5*0.8)
total_sigma = pm.LogNormal("total_sigma", np.log(np.std(data.y)), 0.1)
model_sigma = r2 ** .5 * total_sigma
error_sigma = (1-r2) ** .5 * total_sigma
control_fourier_features_split = pm.Dirichlet("control_features_split", np.ones(K), dims="control_fourier")
control_features_split = model_sigma * control_fourier_features_split[:-1] ** .5
fourier_split = model_sigma * control_fourier_features_split[-1] ** .5

Reference https://arxiv.org/abs/2208.07132

juanitorduz commented 8 months ago

Thanks! yo you recommend this for the seasonality (Fourier modes) components? Or more generally, on the whole model?

wd60622 commented 3 days ago

Are the coefficients suppose to be for all betas in the model or just for a subset like the control / or fourier? @ferrine

ferrine commented 3 days ago

For control and Fourier. Each Fourier component is normalised the same way as control.

For marketing variables it would be another treatment, ideally via interactive prior predictive analysis

wd60622 commented 3 days ago

Gotcha. So in this example, the control_fourier dim is the combination of fourier and controls? i.e. [controls_dims, fourier_dims]

And then the error_sigma would be used as the prior of sigma of likelihood, right?

Think this could fit into the generalization of the Prior class I linked. I.e

gamma_control, gamma_fourier, sigma = create_r2d2_priors(
    r2=Prior("Beta", mu=0.8, sigma=0.8 * 0.5), 
    total_sigma=Prior("LogNormal", mu=np.log(np.std(y)), sigma=0.1),
    # These are the dim names in the model that will be combined
    dims=["control", "fourier_mode"], 
)

model_config = {
    "likelihood": Prior("Normal", sigma=sigma), 
    "gamma_control": gamma_control, 
    "gamma_fourier": gamma_fourier,
}
mmm = MMM(..., model_config=model_config, ...)

gamma_control, gamma_fourier, and sigma would have to work like our priors class.

Also, can you expand on the "interactive prior predictive analysis"?

wd60622 commented 3 days ago

Also, do people tend to put priors on K as well?

ferrine commented 21 hours ago

What is k

ferrine commented 21 hours ago

Ah, I see, k is better set manually, is is problematic to infer