Skip to content
Back to skills

Mmm Api Reference

ASecurity

Complete pymc-marketing API reference for writing and reviewing MMM code. Use when you need exact constructor signatures, method names, parameter lists, or code patterns for pymc-marketing v0.19.1+. Load this skill when writing new model code, debugging import errors, checking method signatures, or reviewing code that uses pymc-marketing. Also activate when you need to look up plotting methods, evaluation functions, cross-validation setup, or transformation classes.

  • 4 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added May 26, 2026
documentationpythongonodeawsdebuggingapi

Works with

  • api

Security analysis

A92/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned May 27, 2026

npx -y skills add Yakoub-ai/agent-mmm --skill mmm-api-reference --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Mmm Api Reference?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Mmm Api Reference
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/yakoub-ai-mmm-api-reference/badge)](https://www.skillsdirectory.com/skills/yakoub-ai-mmm-api-reference)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: mmm-api-reference
description: |
  Complete pymc-marketing API reference for writing and reviewing MMM code. Use when you need exact constructor signatures, method names, parameter lists, or code patterns for pymc-marketing v0.19.1+. Load this skill when writing new model code, debugging import errors, checking method signatures, or reviewing code that uses pymc-marketing. Also activate when you need to look up plotting methods, evaluation functions, cross-validation setup, or transformation classes.
---

# pymc-marketing MMM API Reference (v0.19.1+)

## 1. Imports

```python
# Core MMM class (ALWAYS use multidimensional)
from pymc_marketing.mmm.multidimensional import MMM

# Transformations
from pymc_marketing.mmm import (
    GeometricAdstock,       # Exponential decay
    DelayedAdstock,         # Weibull CDF peak-then-decay
    WeibullAdstock,         # Weibull parameterization
    NoAdstock,              # No carryover
    LogisticSaturation,     # 1 - exp(-lam * x)
    HillSaturation,         # S-curve with inflection
    MichaelisMentenSaturation,
    TanhSaturation,
    NoSaturation,
)

# Priors
from pymc_extras.prior import Prior

# Budget optimization
from pymc_marketing.mmm.budget_optimizer import BudgetOptimizer, CustomModelWrapper, Constraint

# Cross-validation
from pymc_marketing.mmm.time_slice_cross_validation import TimeSliceCrossValidator

# Evaluation
from pymc_marketing.mmm.evaluation import (
    compute_summary_metrics,
    calculate_metric_distributions,
    summarize_metric_distributions,
)

# Summary
from pymc_marketing.mmm.summary import MMMSummaryFactory, MMMIDataWrapper

# Diagnostics
import arviz as az
```

## 2. MMM Constructor

```python
model = MMM(
    date_column: str,                     # Required: datetime column name
    channel_columns: list[str],           # Required: media spend column names
    adstock: AdstockTransformation,       # Required: carryover transform
    saturation: SaturationTransformation, # Required: diminishing returns transform
    target_column: str = "y",             # Name of target column (default "y")
    control_columns: list[str] = None,    # Additional regressors
    yearly_seasonality: int = None,       # Fourier modes for yearly patterns
    time_varying_intercept: bool = False, # HSGP dynamic baseline
    time_varying_media: bool = False,     # HSGP time-dependent channel effect
    model_config: dict = None,            # Prior and likelihood config
    sampler_config: dict = None,          # PyMC sampling parameters
    adstock_first: bool = True,           # Adstock before saturation (recommended)
    scaling: Scaling|dict = None,         # Data scaling config
    dag: str = None,                      # DOT format DAG for causal ID
    treatment_nodes: list[str] = None,    # Causal treatment variables
    outcome_node: str = None,             # Causal outcome variable
    dims: dict = None,                    # Additional model dimensions
)
```

### Default model_config
```python
{
    "intercept": Prior("Normal", mu=0, sigma=2),
    "likelihood": Prior("Normal", sigma=Prior("HalfNormal", sigma=2)),
    "gamma_control": Prior("Normal", mu=0, sigma=2, dims="control"),
    "gamma_fourier": Prior("Laplace", mu=0, b=1, dims="fourier_mode"),
    "adstock_alpha": Prior("Beta", alpha=1, beta=3),
    "saturation_lam": Prior("Gamma", alpha=3, beta=1),
    "saturation_beta": Prior("HalfNormal", sigma=2),
}
```

## 3. Transformation Classes

### GeometricAdstock
```python
adstock = GeometricAdstock(l_max=5)
# alpha in [0,1]: higher = longer memory
# w_t = alpha^t (exponential decay)
```

### DelayedAdstock
```python
adstock = DelayedAdstock(l_max=12)
# Weibull CDF: w_t = 1 - exp(-(t/lam)^k)
# Peak-then-decay pattern, good for offline media
```

### LogisticSaturation
```python
saturation = LogisticSaturation()
# f(x) = 1 - exp(-lam * x)
# lam: steepness, beta: output scale
```

## 4. Fitting Methods

```python
# Prior predictive check
prior = model.sample_prior_predictive(X=X, y=y, samples=500)
# Returns xr.DataArray (combined=True, single target var)

# Fit model — sampler kwargs still work as fit() **kwargs in 0.19.1
model.fit(X, y, draws=2000, tune=3000, chains=4, target_accept=0.99)
# OR pass via constructor: MMM(..., sampler_config={"draws": 2000, "tune": 3000, ...})

# Posterior predictive (in-sample)
pp = model.sample_posterior_predictive(X, extend_idata=True)
# 0.19.1: Returns xr.DataArray with dims (date, sample) [combined=True default]
# WARNING: Values are NORMALIZED [0,1] — multiply by target_scale for original scale

# Out-of-sample prediction
pp_test = model.sample_posterior_predictive(X_test, extend_idata=False)
# Returns xr.DataArray — average over sample dim:
y_pred = pp_test.mean(dim="sample").values  # NOT mean(dim=("chain","draw")) anymore

# Get scale factor
scale = float(model.get_scales_as_xarray()["target_scale"].values)
```

## 5. Attribution Methods

```python
# Channel contributions (original scale) — VERIFIED 0.19.1 pattern
# channel_contribution IS in idata.posterior (normalized) after fit()
cc = model.idata.posterior["channel_contribution"]  # dims: (chain, draw, date, channel)
target_scale = float(model.get_scales_as_xarray()["target_scale"].values)
contrib = cc * target_scale  # original scale
# dims: (chain, draw, date, channel)

# NOTE: add_original_scale_contribution_variable() DOES exist but its result
# goes into model.model.named_vars, NOT into idata.posterior automatically.
# Use the manual scaling approach above for contribution analysis.

# Model summary
model.table()           # Rich table
summary = model.summary  # Property

# MMMSummaryFactory
wrapper = MMMIDataWrapper(model.idata)
factory = MMMSummaryFactory(data=wrapper, model=model)
factory.contributions()
factory.roas()
factory.saturation_curves()
factory.adstock_curves()
factory.total_contribution()
factory.channel_spend()
```

## 6. Curve Sampling

```python
# Saturation curves with posterior uncertainty
sat_curve = model.sample_saturation_curve(max_value=2.0, num_points=100)
# Returns xarray: dims (chain, draw, x, channel)

# Adstock curves
ads_curve = model.sample_adstock_curve()
```

## 7. Cross-Validation

```python
cv = TimeSliceCrossValidator(
    n_init=80,              # Min training observations
    forecast_horizon=13,    # Weeks to predict
    date_column="date",
    step_size=13,           # Step between folds
    sampler_config={"draws": 1000, "tune": 1500, "chains": 4, "target_accept": 0.97},
)

# Requires MMMBuilder protocol
class ModelBuilder:
    def build_model(self, X, y):
        model = create_and_fit_model(X, y)
        return model

n_folds = cv.get_n_splits(X, pd.Series(y))
combined_idata = cv.run(X, pd.Series(y), mmm=ModelBuilder())

# Per-fold results
for result in cv._cv_results:
    result.y_train, result.y_test
    result.idata.posterior_predictive
```

## 8. Budget Optimization

```python
# Wrap fitted model
wrapper = CustomModelWrapper(
    base_model=model.model,
    idata=model.idata,
    channels=channel_columns,
)

# Create optimizer
optimizer = BudgetOptimizer(model=wrapper, num_periods=len(X))

# Run optimization
opt_alloc, opt_result = optimizer.allocate_budget(
    total_budget=total_budget,
    budget_bounds=budget_bounds,  # dict: {channel: (min, max)}
)

# Custom constraints
optimizer.set_constraints([
    Constraint(type="ineq", fun=constraint_fn),
])
```

## 9. Evaluation

```python
# Per-sample metric distributions (correct approach)
dist = calculate_metric_distributions(y_true, y_pred_samples)
summary = summarize_metric_distributions(dist)
metrics = compute_summary_metrics(y_true, y_pred_samples)

# sklearn point metrics (on posterior mean -- less correct)
from sklearn.metrics import r2_score, mean_absolute_percentage_error
```

## 10. Plotting Suite (model.plot.*)

```python
# Predictive checks
model.plot.posterior_predictive()
model.plot.prior_predictive()

# Parameter diagnostics
model.plot.prior_vs_posterior(var="adstock_alpha")
model.plot.posterior_distribution(var="saturation_beta")
model.plot.channel_parameter(var="adstock_alpha")

# Decomposition
model.plot.waterfall_components_decomposition()
model.plot.contributions_over_time()
model.plot.channel_contribution_share_hdi()

# Residuals
model.plot.residuals_over_time()
model.plot.residuals_posterior_distribution()

# Curves
model.plot.saturation_curves(curve=model.sample_saturation_curve())
model.plot.saturation_curves_scatter()
model.plot.saturation_scatterplot()
model.plot.marginal_curve()
model.plot.uplift_curve()

# Cross-validation
model.plot.cv_crps()
model.plot.cv_predictions()
model.plot.param_stability()

# Budget
model.plot.budget_allocation()
model.plot.allocated_contribution_by_channel_over_time()
model.plot.sensitivity_analysis()

# Interactive (Plotly)
model.plot_interactive.posterior_predictive()
```

## 11. ArviZ Diagnostics

```python
import arviz as az

# Convergence
az.summary(model.idata)                    # rhat, ESS, mean, HDI
az.plot_trace(model.idata, var_names=[...]) # Trace plots
az.plot_energy(model.idata)                 # NUTS energy diagnostic
az.plot_posterior(model.idata, var_names=[...])
az.plot_pair(model.idata, var_names=[...])  # Parameter correlations

# Model comparison
loo = az.loo(model.idata)
waic = az.waic(model.idata)
az.compare({"model_a": idata_a, "model_b": idata_b})
```

## 12. Migration from Legacy API

| Feature | Legacy `pymc_marketing.mmm.MMM` | Multidimensional |
|---------|------|------|
| Import | `from pymc_marketing.mmm import MMM` | `from pymc_marketing.mmm.multidimensional import MMM` |
| Target column | Not a constructor param | `target_column="y"` |
| Channel priors | `adstock.function_priors["alpha"] = Prior(...)` | `model_config={"adstock_alpha": Prior(...)}` |
| Contributions | `model.compute_channel_contribution_original_scale()` | `model.add_original_scale_contribution_variable(...)` |
| Shares | `model.get_channel_contribution_share_samples()` | `contrib / contrib.sum("channel")` |
| Budget opt | `model.optimize_budget()` | `BudgetOptimizer` + `CustomModelWrapper` |
| Plots | `model.plot_posterior_predictive()` | `model.plot.posterior_predictive()` |
| Params | `model.format_recovered_transformation_parameters()` | `model.table()` |
| Forward pass | `model.get_channel_contribution_forward_pass_grid()` | `model.sample_saturation_curve()` |

## 13. Sensitivity Analysis

```python
# run_sweep REQUIRED positional arg: var_input (the pm.Data variable name)
# For standard MMM models, the channel spend variable is "channel_data"
model.sensitivity.run_sweep(
    "channel_data",                          # var_input: REQUIRED positional
    sweep_values=np.linspace(0, 1.5, 12),   # multipliers to sweep
    var_names="channel_contribution",        # var_names (plural), default is "channel_contribution"
    sweep_type="multiplicative",             # "multiplicative", "additive", or "absolute"
)
fig = model.plot.sensitivity_analysis()
```

## agent_mmm Library Quick Reference

The plugin ships `agent_mmm` at `plugins/agent-mmm/lib/agent_mmm/`. Install: `pip install -e plugins/agent-mmm`.

| Module | Key Function | Purpose |
|--------|-------------|---------|
| `data_audit` | `run_audit(spec, base)` | 11-check data quality audit |
| `controls_engine` | `recommend_controls(spec, audit_findings, base)` | External factors recommender |
| `prior_engine` | `recommend_priors(spec, audit_findings, base)` | Auto-generate model_config |
| `model_factory` | `build_mmm(spec, model_config_dict)` | Build MMM instance |
| `fit_runner` | `run_fit(spec, ..., base)` | Full fit pipeline |
| `diagnostics` | `run_diagnostics(run_id, ..., base)` | Convergence + fit + CV checks |
| `iter_loop` | `run_tournament(spec_path, ..., base)` | Tournament + refinement loop |
| `reports.cmo/cfo/mops/ds` | `generate_*_report(spec, run_id, ...)` | Stakeholder reports |

Workspace layout: all artifacts in `./mmm-workspace/` — `spec.yaml`, `audit/`, `controls/`, `priors/`, `runs/<id>/`, `leaderboard.json`, `reports/`.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.