PanelMMM

PanelMMM is the single retained public MMM model API in Abacus.

Import it from:

from abacus.mmm.panel import PanelMMM

For conceptual guidance, see Model Overview. For data contracts, see Data Preparation.

Constructor

PanelMMM(...) is keyword-only.

The main constructor arguments are:

Argument Meaning
date_column Name of the date column in X
channel_columns Required media columns
target_column Semantic target column name
target_type "revenue" or "conversion"
adstock An AdstockTransformation instance
saturation A SaturationTransformation instance
estimator Optional named estimator declaration; time_series, fe, and cre are released
dims Optional panel dimensions such as ("geo",)
control_columns Optional non-media regressors
control_impacts Optional directional expectations for controls
control_sign_policy "soft" or "strict"
yearly_seasonality Number of yearly Fourier modes
time_varying_intercept bool or an HSGPBase instance
time_varying_media bool or an HSGPBase instance
use_mundlak_cre Add the legacy low-level Mundlak terms; this is not the named CRE preset
scaling Scaling, a dict, or None
model_config Prior and likelihood configuration
sampler_config Default sampler settings
adstock_first Whether adstock runs before saturation

Core lifecycle methods

The most commonly used methods are:

Method Purpose
build_model(X, y) Build the PyMC graph for the current configuration
fit(X, y, **kwargs) Sample the posterior and store idata
approximate_fit(X, y, ...) Fit with variational inference instead of NUTS
sample_prior_predictive(X, y, ...) Sample prior and prior predictive draws
sample_posterior_predictive(X, ...) Sample posterior predictive draws
predict(X, ...) Return posterior mean predictions
predict_posterior(X, ...) Return posterior predictive samples for output_var
save(path, **kwargs) Save idata to NetCDF
load(path, check=True) Load a saved model from NetCDF
load_from_idata(idata, check=True) Rebuild from an in-memory InferenceData

fit(...), sample_prior_predictive(...), predict(...), save(...), and the load helpers come from the shared model-builder base classes but are part of the user-facing PanelMMM surface.

Named estimator release gates apply to this public surface. Internal graph helpers are reserved for maintainer tests and statistical implementation evidence; they require an explicit internal override for a gated preset and are not a supported fitting interface.

Post-fit model methods

PanelMMM also exposes model-specific post-fit methods:

Method Purpose
add_original_scale_contribution_variable(var=[...]) Add original-scale deterministics before fitting
sample_saturation_curve(...) Sample posterior saturation curves
sample_adstock_curve(...) Sample posterior adstock curves
sample_channel_contribution_forward_pass(...) Sample channel contributions in scaled target space
channel_contribution_forward_pass(...) Evaluate channel contributions in original target units
get_channel_contribution_forward_pass_grid(...) Build a contribution grid over shared spend multipliers
new_spend_contributions(...) Simulate forward contribution paths for a spend scenario
add_lift_test_measurements(...) Add lift-test calibration measurements
add_cost_per_target_calibration(...) Add cost-per-target calibration penalties
add_events(df_events, prefix, effect) Add dated event effects before build

Bound properties

Once the model exists, these bound properties expose the retained post-fit surface:

Property Returns
plot MMMPlotSuite
data MMMIDataWrapper
summary MMMSummaryFactory
diagnostics MMMDiagnosticsFactory
efficiency_metric Default efficiency metric key for target_type
efficiency_metric_label Display label such as ROAS or CPA

See Post-Fit Facades.

Other useful attributes

Common model attributes include:

Attribute Meaning
idata The fitted arviz.InferenceData
output_var Output variable name used in predictive sampling ("y")
channel_columns Configured channel names
control_columns Configured control names
dims Configured panel dimensions
mu_effects Additive effects attached before build

Named estimator presets

Use estimator={"type": "time_series"} for one aggregate time series. This named preset builds the same single-series graph as the established no-dimension PanelMMM path for the same constructor arguments. Under the default constructor settings, that graph has one global intercept, shared media and control parameters, shared adstock and saturation parameters, and the existing Gaussian levels likelihood. Its information comes from temporal variation in the aggregate series, combined with the declared priors.

The preset does not override orthogonal PanelMMM options. For example, explicit time-varying intercept, time-varying media, or likelihood settings retain the same behaviour as the equivalent unlabelled single-series model. Those options are not estimator-level categorical time effects.

The named time_series, fe, and cre presets are released. The named re preset remains unavailable until its separate statistical implementation and verification checkpoint passes. It raises EstimatorReleaseGateError before graph construction; Abacus does not substitute the low-level dims surface.

The released CRE implementation uses an exact marginal Gaussian random-intercept likelihood and a separate correlated-effects adjustment. Its media summaries are derived from the declared transformed exposure basis, rather than raw spend means. Eligible time-varying controls use centred unit means. Pipeline evidence keeps that adjustment on the baseline/non-incremental side of decomposition and records pre-fit and post-fit estimability diagnostics.

This adjustment is not a general remedy for confounding. It does not establish causal identification, prove that the random-effects assumptions are adequate, or address omitted time-varying confounding, measurement error, or response-function misspecification. The released preset also rejects unseen units, fitted-unit subsets, budget optimisation, and calibration. Historical and manual scenarios are supported for the complete fitted-unit panel. They retain the fitted training-period CRE summaries instead of recomputing them from planned spend.

The CRE release verifies the declared graph, configuration boundary, estimability evidence, fitted-unit prediction contract and persistence path. It does not promise 15% point-estimate accuracy, causal validity, or general robustness across arbitrary panel designs. Analysts must inspect posterior diagnostics, prior sensitivity, and the within- and between-unit design evidence for each fitted model.

estimator and dims are mutually exclusive. Existing models that omit estimator keep their current behaviour and identity.

Minimal example

from abacus.mmm import GeometricAdstock, LogisticSaturation
from abacus.mmm.panel import PanelMMM

mmm = PanelMMM(
    date_column="date",
    target_column="revenue",
    channel_columns=["tv", "search", "social"],
    estimator={"type": "time_series"},
    adstock=GeometricAdstock(l_max=8),
    saturation=LogisticSaturation(),
)

mmm.fit(X, y, draws=500, tune=500, chains=2, progressbar=False)
mmm.sample_posterior_predictive(X=X, progressbar=False)