Adstock and Saturation
PanelMMM requires one adstock transform and one saturation transform. Abacus
applies them inside the model graph rather than as a fixed preprocessing step.
For the econometrics framing of these transforms, see Adstock and Saturation for Econometricians.
How the transform path works
Abacus combines the two transforms through forward_pass(...):
- if
adstock_first=True, the order is adstock then saturation - if
adstock_first=False, the order is saturation then adstock
The transformed result becomes channel_contribution on the model scale.
Adstock options
PanelMMM accepts any AdstockTransformation. The built-in options include:
| Class | Key parameter priors by default | Notes |
|---|---|---|
GeometricAdstock |
alpha ~ Beta(1, 3) |
Standard geometric carryover |
BinomialAdstock |
alpha ~ Beta(1, 3) |
Alternative finite-lag carryover |
DelayedAdstock |
alpha ~ Beta(1, 3), theta ~ HalfNormal(1) |
Allows a delayed peak |
WeibullPDFAdstock |
lam ~ Gamma(mu=2, sigma=1), k ~ Gamma(mu=3, sigma=1) |
Flexible PDF-shaped carryover |
WeibullCDFAdstock |
lam ~ Gamma(mu=2, sigma=1), k ~ Gamma(mu=3, sigma=1) |
Flexible CDF-shaped carryover |
All adstock transforms also take:
l_max: maximum lagnormalize: whether the carryover weights are normalisedmode: convolution mode
Saturation options
PanelMMM accepts any SaturationTransformation. Common built-ins include:
| Class | Key parameter priors by default | Notes |
|---|---|---|
LogisticSaturation |
lam ~ Gamma(alpha=3, beta=1), beta ~ HalfNormal(2) |
Default retained choice |
MichaelisMentenSaturation |
alpha ~ Gamma(mu=2, sigma=1), lam ~ HalfNormal(1) |
Common diminishing-returns form |
HillSaturation |
slope ~ HalfNormal(1.5), kappa ~ HalfNormal(1.5), beta ~ HalfNormal(1.5) |
Flexible Hill curve |
HillSaturationSigmoid |
sigma ~ HalfNormal(1.5), beta ~ HalfNormal(1.5), lam ~ HalfNormal(1.5) |
Sigmoid Hill variant |
RootSaturation |
alpha ~ Beta(alpha=1, beta=2), beta ~ Gamma(mu=1, sigma=1) |
Square-root style curvature |
TanhSaturation |
b ~ HalfNormal(1), c ~ HalfNormal(1) |
Hyperbolic tangent form |
TanhSaturationBaselined |
x0, gain, r, beta all HalfNormal(1) |
Baselined tanh form |
Default prior dims
When you pass a transform to PanelMMM, Abacus assigns default prior dims for
any transform prior that does not already have explicit dims:
- adstock priors default to
(*dims, "channel") - saturation priors default to
(*dims, "channel")
If you want a different structure, set the prior dims explicitly on the transform.
Configure transforms in Python
Example with more customised transforms:
Configure transforms in YAML
Override transform priors through priors
Transform priors also appear in model_config under prefixed variable names.
For example:
adstock_alphaadstock_lamadstock_ksaturation_lamsaturation_beta
That means you can override transform priors centrally through the top-level priors
if you prefer. See Priors and Configuration.
Choose the composition order
adstock_first is part of the model specification, not a plotting choice.
The current public YAML schema does not expose adstock_first; it uses the
library default. If you need to change the composition order, use the Python
API.
Use adstock_first=True when you want the model to interpret carryover before
diminishing returns. Use False when you want each period’s spend to saturate
before the carryover step.
The code path is explicit:
True->saturation(adstock(x))False->adstock(saturation(x))
Common pitfalls
- Forgetting that
l_maxis required for adstock classes - Assuming
dimsautomatically change transform priors even when you have already set explicit incompatible dims on the transform - Using
adstock_first=Falsewithout a substantive reason - Treating transform priors as if they were on original business units rather than the model scale
Next steps
- Read Priors and Configuration to control the prior surface.
- Read Time-Varying Parameters if you want media contributions to vary over time.