Skip to content

Conversation

@MarkusSagen
Copy link
Contributor

@MarkusSagen MarkusSagen commented Oct 23, 2023

This PR intends to add custom priors to the DelayedSaturation MMM model

There is an issue however and would love for some feedback and help on how to fix it.
The DelayedSaturation MMM uses priors with dims, but the CLV model I've copied from does not. I'm currious how to add that for the priors to make the code and tests pass?


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

@twiecki
Copy link
Contributor

twiecki commented Oct 23, 2023

This is neat.

I wonder, rather than specifying dists as names so that we can serialize them, couldn't we just use pm.Distribution.dist(**kwargs) and when we serialize, get str(Distribution) and kwargs, and then when unserializing we look up the right dist? Not sure that's possible @ricardoV94. I guess it's more of a PyMC issue to make pm.Distribution.dist serializable.

Anyway, I don't think we need to chase this one down all the way and focus on this implementation instead.

@ricardoV94
Copy link
Contributor

@MarkusSagen is this a duplicate of #397?

@MarkusSagen
Copy link
Contributor Author

@ricardoV94 It seems like it, yes!
It is very similar

@ricardoV94
Copy link
Contributor

Can you synchronize with @cetagostini to avoid duplicate work?

@cetagostini
Copy link
Contributor

@MarkusSagen Hey great to see you are also working on it. Before, even moving to the unit test. Did you try to run the example notebook with these changes?

Another thing, are you leaving the dims on the model_config dictionary, right? Talking with @ricardoV94 we were thinking of leaving the dims fixed, these should not be adjusted by the user. But we can debate here the approach!

@MarkusSagen
Copy link
Contributor Author

@cetagostini That sounds like a good idea! Leaving them fixed prevents users from having unintended consequences.
Yes, I started with the tests first and was then going to test the notebook example.

The thing I got stuck on was that register_rv does not seem to have a way to pass in dimensions

@cetagostini
Copy link
Contributor

@MarkusSagen great, then if we are align. What do you think if we have a session during the week? Are you available to talk maybe 45 minutes, and have a session of programming where we can compile the best of the two PR and merge it on one where each of us can modify?

Regarding adding dims, you can modify this in your code, adding the dimensions if you follow the register_rv documentation in PyMC.

self.model.register_rv(
                self.beta_channel, name="beta_channel", dims=("channel",)
            )

or how Juan apply it here.

@twiecki twiecki mentioned this pull request Oct 31, 2023
@cetagostini
Copy link
Contributor

@MarkusSagen I was able to modify everything and make it run smoothly here.

If you want you can take a look, and suggest some changes if needed 🙌🏻

@twiecki
Copy link
Contributor

twiecki commented Oct 31, 2023

Have you guys seen #415? Any way to consolidate the efforts?

@MarkusSagen
Copy link
Contributor Author

Nice! If that would work with incorporating time-varying coefficients, it seems more future proof.
Might make sense though to do one change after the other (First #397 then #415) for tracking and ensuring that all tests still pass?

Comment on lines +121 to +141
# Define custom priors
self.intercept = self._create_distribution(self.model_config["intercept"])
self.beta_channel = self._create_distribution(self.model_config["beta_channel"])
self.alpha = self._create_distribution(self.model_config["alpha"])
self.lam = self._create_distribution(self.model_config["lam"])
self.sigma = self._create_distribution(self.model_config["sigma"])
self.gamma_control = self._create_distribution(
self.model_config["gamma_control"]
)
self.gamma_fourier = self._create_distribution(
self.model_config["gamma_fourier"]
)
self._process_priors(
self.intercept,
self.beta_channel,
self.alpha,
self.lam,
self.sigma,
self.gamma_control,
self.gamma_fourier,
)
Copy link
Contributor

Choose a reason for hiding this comment

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

This should only be done in build_model

alpha=model_config["lam"]["alpha"],
beta=model_config["lam"]["beta"],
dims=model_config["lam"]["dims"],
# FIXME: Need to add the correct dims to `beta_channel`, `alpha`, `lam`,
Copy link
Contributor

Choose a reason for hiding this comment

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

The problem here is that dims no longer affect the shape of the rv by this point.
Instead of using the approach in CLVModel which works fine because we are always building scalar distributions, use a _create_model_distribution that looks like this:

    @staticmethod
    def _create_model_distribution(name: str, dist: Dict, ndim: int = 0, dims = None, model: Optional[Model]=None) -> TensorVariable:
        model = pm.modelcontext(model)
        try:
            with model:
                prior_distribution = getattr(pm, dist["dist"])(name, **dist["kwargs"], dims=dims)
        except AttributeError:
            raise ValueError(f"Distribution {dist['dist']} does not exist in PyMC")
        return prior_distribution

Then you don't need to call model.register_rv, as you are already creating a model variable

@MarkusSagen
Copy link
Contributor Author

Closing. Fixed in #397

@MarkusSagen MarkusSagen closed this Nov 2, 2023
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

Successfully merging this pull request may close these issues.

4 participants