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

excluded _prior suffix from CLV models #1498

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
2 changes: 1 addition & 1 deletion docs/source/notebooks/clv/bg_nbd.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@
"id": "0a5fc96b-eedd-43ae-bd70-5ae388f1f636",
"metadata": {},
"source": [
"Notice the additional `phi_dropout` and `kappa_dropout` priors. These were added to the default configuration to improve performance, but can be omitted when specifying a custom `model_config` with `a_prior` and `b_prior`.\n",
"Notice the additional `phi_dropout` and `kappa_dropout` priors. These were added to the default configuration to improve performance, but can be omitted when specifying a custom `model_config` with `a` and `b`.\n",
"\n",
"The specified model structure can also be visualized:"
]
Expand Down
8 changes: 4 additions & 4 deletions docs/source/notebooks/clv/clv_quickstart.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -576,10 +576,10 @@
"outputs": [],
"source": [
"model_config = {\n",
" \"a_prior\": Prior(\"HalfNormal\", sigma=10),\n",
" \"b_prior\": Prior(\"HalfNormal\", sigma=10),\n",
" \"alpha_prior\": Prior(\"HalfNormal\", sigma=10),\n",
" \"r_prior\": Prior(\"HalfNormal\", sigma=10),\n",
" \"a\": Prior(\"HalfNormal\", sigma=10),\n",
" \"b\": Prior(\"HalfNormal\", sigma=10),\n",
" \"alpha\": Prior(\"HalfNormal\", sigma=10),\n",
" \"r\": Prior(\"HalfNormal\", sigma=10),\n",
"}"
]
},
Expand Down
8 changes: 4 additions & 4 deletions docs/source/notebooks/clv/dev/beta_geo_beta_binom.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@
],
"source": [
"model_config = {\n",
" \"alpha_prior\": Prior(\"HalfFlat\"),\n",
" \"beta_prior\": Prior(\"HalfFlat\"),\n",
" \"gamma_prior\": Prior(\"HalfFlat\"),\n",
" \"delta_prior\": Prior(\"HalfFlat\"),\n",
" \"alpha\": Prior(\"HalfFlat\"),\n",
" \"beta\": Prior(\"HalfFlat\"),\n",
" \"gamma\": Prior(\"HalfFlat\"),\n",
" \"delta\": Prior(\"HalfFlat\"),\n",
"}\n",
"\n",
"model = BetaGeoBetaBinomModel(data=data,model_config=model_config)\n",
Expand Down
2 changes: 1 addition & 1 deletion docs/source/notebooks/clv/mbg_nbd.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@
"id": "0a5fc96b-eedd-43ae-bd70-5ae388f1f636",
"metadata": {},
"source": [
"Notice the additional `phi_dropout` and `kappa_dropout` priors. These were added to the default configuration to improve performance, but can be omitted when specifying a custom `model_config` with `a_prior` and `b_prior`.\n",
"Notice the additional `phi_dropout` and `kappa_dropout` priors. These were added to the default configuration to improve performance, but can be omitted when specifying a custom `model_config` with `a` and `b`.\n",
"\n",
"The specified model structure can also be visualized:"
]
Expand Down
8 changes: 4 additions & 4 deletions docs/source/notebooks/clv/pareto_nbd.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -588,10 +588,10 @@
"outputs": [],
"source": [
"flat_config = {\n",
" \"r_prior\": Prior(\"HalfFlat\"),\n",
" \"alpha_prior\": Prior(\"HalfFlat\"),\n",
" \"s_prior\": Prior(\"HalfFlat\"),\n",
" \"beta_prior\": Prior(\"HalfFlat\"),\n",
" \"r\": Prior(\"HalfFlat\"),\n",
" \"alpha\": Prior(\"HalfFlat\"),\n",
" \"s\": Prior(\"HalfFlat\"),\n",
" \"beta\": Prior(\"HalfFlat\"),\n",
"}\n",
"\n",
"pnbd_pymc = clv.ParetoNBDModel(data=rfm_data, model_config=flat_config)"
Expand Down
46 changes: 23 additions & 23 deletions pymc_marketing/clv/models/beta_geo.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,12 @@ class BetaGeoModel(CLVModel):
* `T`: Time between the first purchase and the end of the observation period
model_config : dict, optional
Dictionary of model prior parameters:
* `alpha_prior`: Scale parameter for time between purchases; defaults to `Prior("Weibull", alpha=2, beta=10)`
* `r_prior`: Shape parameter for time between purchases; defaults to `Prior("Weibull", alpha=2, beta=1)`
* `a_prior`: Shape parameter of dropout process; defaults to `phi_purchase_prior` * `kappa_purchase_prior`
* `b_prior`: Shape parameter of dropout process; defaults to `1-phi_dropout_prior` * `kappa_dropout_prior`
* `phi_dropout_prior`: Nested prior for a and b priors; defaults to `Prior("Uniform", lower=0, upper=1)`
* `kappa_dropout_prior`: Nested prior for a and b priors; defaults to `Prior("Pareto", alpha=1, m=1)`
* `alpha`: Scale parameter for time between purchases; defaults to `Prior("Weibull", alpha=2, beta=10)`
* `r`: Shape parameter for time between purchases; defaults to `Prior("Weibull", alpha=2, beta=1)`
* `a`: Shape parameter of dropout process; defaults to `phi_purchase` * `kappa_purchase`
* `b`: Shape parameter of dropout process; defaults to `1-phi_dropout` * `kappa_dropout`
* `phi_dropout`: Nested prior for a and b priors; defaults to `Prior("Uniform", lower=0, upper=1)`
* `kappa_dropout`: Nested prior for a and b priors; defaults to `Prior("Pareto", alpha=1, m=1)`
sampler_config : dict, optional
Dictionary of sampler parameters. Defaults to *None*.

Expand Down Expand Up @@ -96,10 +96,10 @@ class BetaGeoModel(CLVModel):
model = BetaGeoModel(
data=data,
model_config={
"r_prior": Prior("Weibull", alpha=2, beta=1),
"alpha_prior": Prior("HalfFlat"),
"a_prior": Prior("Beta", alpha=2, beta=3),
"b_prior": Prior("Beta", alpha=3, beta=2),
"r": Prior("Weibull", alpha=2, beta=1),
"alpha": Prior("HalfFlat"),
"a": Prior("Beta", alpha=2, beta=3),
"b": Prior("Beta", alpha=3, beta=2),
},
sampler_config={
"draws": 1000,
Expand Down Expand Up @@ -166,10 +166,10 @@ def __init__(
def default_model_config(self) -> ModelConfig:
"""Default model configuration."""
return {
"alpha_prior": Prior("Weibull", alpha=2, beta=10),
"r_prior": Prior("Weibull", alpha=2, beta=1),
"phi_dropout_prior": Prior("Uniform", lower=0, upper=1),
"kappa_dropout_prior": Prior("Pareto", alpha=1, m=1),
"alpha": Prior("Weibull", alpha=2, beta=10),
"r": Prior("Weibull", alpha=2, beta=1),
"phi_dropout": Prior("Uniform", lower=0, upper=1),
"kappa_dropout": Prior("Pareto", alpha=1, m=1),
}

def build_model(self) -> None: # type: ignore[override]
Expand All @@ -180,21 +180,21 @@ def build_model(self) -> None: # type: ignore[override]
}
with pm.Model(coords=coords) as self.model:
# purchase rate priors
alpha = self.model_config["alpha_prior"].create_variable("alpha")
r = self.model_config["r_prior"].create_variable("r")
alpha = self.model_config["alpha"].create_variable("alpha")
r = self.model_config["r"].create_variable("r")

# dropout priors
if "a_prior" in self.model_config and "b_prior" in self.model_config:
a = self.model_config["a_prior"].create_variable("a")
b = self.model_config["b_prior"].create_variable("b")
if "a" in self.model_config and "b" in self.model_config:
a = self.model_config["a"].create_variable("a")
b = self.model_config["b"].create_variable("b")
else:
# hierarchical pooling of dropout rate priors
phi_dropout = self.model_config["phi_dropout_prior"].create_variable(
phi_dropout = self.model_config["phi_dropout"].create_variable(
"phi_dropout"
)
kappa_dropout = self.model_config[
"kappa_dropout_prior"
].create_variable("kappa_dropout")
kappa_dropout = self.model_config["kappa_dropout"].create_variable(
"kappa_dropout"
)

a = pm.Deterministic("a", phi_dropout * kappa_dropout)
b = pm.Deterministic("b", (1.0 - phi_dropout) * kappa_dropout)
Expand Down
63 changes: 30 additions & 33 deletions pymc_marketing/clv/models/beta_geo_beta_binom.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,14 @@
model_config : dict, optional
Dictionary containing model parameters:

* `alpha_prior`: Shape parameter of purchase process; defaults to `phi_purchase_prior` * `kappa_purchase_prior`
* `beta_prior`: Shape parameter of purchase process; defaults to `1-phi_purchase_prior` * `kappa_purchase_prior`
* `gamma_prior`: Shape parameter of dropout process; defaults to `phi_purchase_prior` * `kappa_purchase_prior`
* `delta_prior`: Shape parameter of dropout process; defaults to `1-phi_dropout_prior` * `kappa_dropout_prior`
* `phi_purchase_prior`: Nested prior for alpha and beta priors; defaults to `Prior("Uniform", lower=0, upper=1)`
* `kappa_purchase_prior`: Nested prior for alpha and beta priors; defaults to `Prior("Pareto", alpha=1, m=1)`
* `phi_dropout_prior`: Nested prior for gamma and delta priors; defaults to `Prior("Uniform", lower=0, upper=1)`
* `kappa_dropout_prior`: Nested prior for gamma and delta priors; defaults to `Prior("Pareto", alpha=1, m=1)`
* `alpha`: Shape parameter of purchase process; defaults to `phi_purchase` * `kappa_purchase`
* `beta`: Shape parameter of purchase process; defaults to `1-phi_purchase` * `kappa_purchase`
* `gamma`: Shape parameter of dropout process; defaults to `phi_purchase` * `kappa_purchase`
* `delta`: Shape parameter of dropout process; defaults to `1-phi_dropout` * `kappa_dropout`
* `phi_purchase`: Nested prior for alpha and beta priors; defaults to `Prior("Uniform", lower=0, upper=1)`
* `kappa_purchase`: Nested prior for alpha and beta priors; defaults to `Prior("Pareto", alpha=1, m=1)`
* `phi_dropout`: Nested prior for gamma and delta priors; defaults to `Prior("Uniform", lower=0, upper=1)`
* `kappa_dropout`: Nested prior for gamma and delta priors; defaults to `Prior("Pareto", alpha=1, m=1)`

If not provided, the model will use default priors specified in the `default_model_config` class attribute.
sampler_config : dict, optional
Expand All @@ -88,10 +88,10 @@
model = BetaGeoBetaBinomModel(
data=rfm_df,
model_config={
"alpha_prior": Prior("HalfFlat"),
"beta_prior": Prior("HalfFlat"),
"gamma_prior": Prior("HalfFlat"),
"delta_prior": Prior("HalfFlat"),
"alpha": Prior("HalfFlat"),
"beta": Prior("HalfFlat"),
"gamma": Prior("HalfFlat"),
"delta": Prior("HalfFlat"),
},
)

Expand Down Expand Up @@ -175,10 +175,10 @@
def default_model_config(self) -> ModelConfig:
"""Default model configuration."""
return {
"phi_purchase_prior": Prior("Uniform", lower=0, upper=1),
"kappa_purchase_prior": Prior("Pareto", alpha=1, m=1),
"phi_dropout_prior": Prior("Uniform", lower=0, upper=1),
"kappa_dropout_prior": Prior("Pareto", alpha=1, m=1),
"phi_purchase": Prior("Uniform", lower=0, upper=1),
"kappa_purchase": Prior("Pareto", alpha=1, m=1),
"phi_dropout": Prior("Uniform", lower=0, upper=1),
"kappa_dropout": Prior("Pareto", alpha=1, m=1),
}

def build_model(self) -> None: # type: ignore[override]
Expand All @@ -189,36 +189,33 @@
}
with pm.Model(coords=coords) as self.model:
# purchase rate priors
if "alpha_prior" in self.model_config and "beta_prior" in self.model_config:
alpha = self.model_config["alpha_prior"].create_variable("alpha")
beta = self.model_config["beta_prior"].create_variable("beta")
if "alpha" in self.model_config and "beta" in self.model_config:
alpha = self.model_config["alpha"].create_variable("alpha")
beta = self.model_config["beta"].create_variable("beta")

Check warning on line 194 in pymc_marketing/clv/models/beta_geo_beta_binom.py

View check run for this annotation

Codecov / codecov/patch

pymc_marketing/clv/models/beta_geo_beta_binom.py#L192-L194

Added lines #L192 - L194 were not covered by tests
else:
# hierarchical pooling of purchase rate priors
phi_purchase = self.model_config["phi_purchase_prior"].create_variable(
phi_purchase = self.model_config["phi_purchase"].create_variable(

Check warning on line 197 in pymc_marketing/clv/models/beta_geo_beta_binom.py

View check run for this annotation

Codecov / codecov/patch

pymc_marketing/clv/models/beta_geo_beta_binom.py#L197

Added line #L197 was not covered by tests
"phi_purchase"
)
kappa_purchase = self.model_config[
"kappa_purchase_prior"
].create_variable("kappa_purchase")
kappa_purchase = self.model_config["kappa_purchase"].create_variable(

Check warning on line 200 in pymc_marketing/clv/models/beta_geo_beta_binom.py

View check run for this annotation

Codecov / codecov/patch

pymc_marketing/clv/models/beta_geo_beta_binom.py#L200

Added line #L200 was not covered by tests
"kappa_purchase"
)

alpha = pm.Deterministic("alpha", phi_purchase * kappa_purchase)
beta = pm.Deterministic("beta", (1.0 - phi_purchase) * kappa_purchase)

# dropout priors
if (
"gamma_prior" in self.model_config
and "delta_prior" in self.model_config
):
gamma = self.model_config["gamma_prior"].create_variable("gamma")
delta = self.model_config["delta_prior"].create_variable("delta")
if "gamma" in self.model_config and "delta" in self.model_config:
gamma = self.model_config["gamma"].create_variable("gamma")
delta = self.model_config["delta"].create_variable("delta")

Check warning on line 210 in pymc_marketing/clv/models/beta_geo_beta_binom.py

View check run for this annotation

Codecov / codecov/patch

pymc_marketing/clv/models/beta_geo_beta_binom.py#L208-L210

Added lines #L208 - L210 were not covered by tests
else:
# hierarchical pooling of dropout rate priors
phi_dropout = self.model_config["phi_dropout_prior"].create_variable(
phi_dropout = self.model_config["phi_dropout"].create_variable(

Check warning on line 213 in pymc_marketing/clv/models/beta_geo_beta_binom.py

View check run for this annotation

Codecov / codecov/patch

pymc_marketing/clv/models/beta_geo_beta_binom.py#L213

Added line #L213 was not covered by tests
"phi_dropout"
)
kappa_dropout = self.model_config[
"kappa_dropout_prior"
].create_variable("kappa_dropout")
kappa_dropout = self.model_config["kappa_dropout"].create_variable(

Check warning on line 216 in pymc_marketing/clv/models/beta_geo_beta_binom.py

View check run for this annotation

Codecov / codecov/patch

pymc_marketing/clv/models/beta_geo_beta_binom.py#L216

Added line #L216 was not covered by tests
"kappa_dropout"
)

gamma = pm.Deterministic("gamma", phi_dropout * kappa_dropout)
delta = pm.Deterministic("delta", (1.0 - phi_dropout) * kappa_dropout)
Expand Down
36 changes: 18 additions & 18 deletions pymc_marketing/clv/models/gamma_gamma.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,9 +254,9 @@ class GammaGammaModel(BaseGammaGammaModel):
"frequency": [6, 8, 2, 1, ...],
}),
model_config={
"p_prior": {'dist': 'HalfNormal', kwargs: {}},
"q_prior": {'dist': 'HalfStudentT', kwargs: {"nu": 4, "sigma": 10}},
"v_prior": {'dist': 'HalfCauchy', kwargs: {"beta":1}},
"p": {'dist': 'HalfNormal', kwargs: {}},
"q": {'dist': 'HalfStudentT', kwargs: {"nu": 4, "sigma": 10}},
"v": {'dist': 'HalfCauchy', kwargs: {"beta":1}},
},
sampler_config={
"draws": 1000,
Expand Down Expand Up @@ -318,9 +318,9 @@ def __init__(
def default_model_config(self) -> ModelConfig:
"""Default model configuration."""
return {
"p_prior": Prior("HalfFlat"),
"q_prior": Prior("HalfFlat"),
"v_prior": Prior("HalfFlat"),
"p": Prior("HalfFlat"),
"q": Prior("HalfFlat"),
"v": Prior("HalfFlat"),
}

def build_model(self) -> None: # type: ignore[override]
Expand All @@ -330,9 +330,9 @@ def build_model(self) -> None: # type: ignore[override]

coords = {"customer_id": self.data["customer_id"]}
with pm.Model(coords=coords) as self.model:
p = self.model_config["p_prior"].create_variable("p")
q = self.model_config["q_prior"].create_variable("q")
v = self.model_config["v_prior"].create_variable("v")
p = self.model_config["p"].create_variable("p")
q = self.model_config["q"].create_variable("q")
v = self.model_config["v"].create_variable("v")

# Likelihood for mean_spend, marginalizing over nu
# Eq 1a from [1], p.2
Expand Down Expand Up @@ -393,9 +393,9 @@ class GammaGammaModelIndividual(BaseGammaGammaModel):
}
),
model_config={
"p_prior": {dist: 'HalfNorm', kwargs: {}},
"q_prior": {dist: 'HalfStudentT', kwargs: {"nu": 4, "sigma": 10}},
"v_prior": {dist: 'HalfCauchy', kwargs: {}},
"p": {dist: 'HalfNorm', kwargs: {}},
"q": {dist: 'HalfStudentT', kwargs: {"nu": 4, "sigma": 10}},
"v": {dist: 'HalfCauchy', kwargs: {}},
},
sampler_config={
"draws": 1000,
Expand Down Expand Up @@ -455,9 +455,9 @@ def __init__(
def default_model_config(self) -> dict:
"""Default model configuration."""
return {
"p_prior": Prior("HalfFlat"),
"q_prior": Prior("HalfFlat"),
"v_prior": Prior("HalfFlat"),
"p": Prior("HalfFlat"),
"q": Prior("HalfFlat"),
"v": Prior("HalfFlat"),
}

def build_model(self) -> None: # type: ignore[override]
Expand All @@ -469,9 +469,9 @@ def build_model(self) -> None: # type: ignore[override]
"obs": range(self.data.shape[0]),
}
with pm.Model(coords=coords) as self.model:
p = self.model_config["p_prior"].create_variable("p")
q = self.model_config["q_prior"].create_variable("q")
v = self.model_config["v_prior"].create_variable("v")
p = self.model_config["p"].create_variable("p")
q = self.model_config["q"].create_variable("q")
v = self.model_config["v"].create_variable("v")

nu = pm.Gamma("nu", q, v, dims=("customer_id",))
pm.Gamma(
Expand Down
Loading