Lightweight MMM

repository·main·Indexed 21 days ago

https://github.com/google/lightweight_mmm

A Python library built with Numpyro and JAX for Bayesian Marketing Mix Modeling (MMM). It enables organizations to quantify the relationship between media channel activity and KPIs, optimize budgets, and analyze media performance using standard or hierarchical (geo-level) models. The library supports various media transformations including Adstock, Hill-Adstock, and Carryover. Note: As of January 29, 2025, this library is no longer supported; users are recommended to migrate to Meridian.

Tokens
8.2K
Snippets
22
Records
40
Agent score
74%

What's inside lightweight_mmm

  1. Understand the Lightweight MMM model structure

    main

    Lightweight MMM (LMMM) is a Python library built using Numpyro and JAX that helps quantify the relationship between media channel activity and sales while controlling for other factors.

    A simplified model equation used by the library is:

    kpi = α + trend + seasonality + media_channels + other_factors

    Where:

    • kpi: Typically the volume or value of sales per time period (weekly or daily).
    • α: The model intercept.
    • trend: A flexible non-linear function capturing data trends.
    • seasonality: A sinusoidal function with configurable parameters.
    • media_channels: A matrix of media activity (e.g., impressions or costs) that undergoes transformations like saturation and lagging.
    • other_factors: A matrix of other variables influencing sales.
  2. Inform media priors in LMMM

    main

    Media priors can be informed in several ways beyond the default behavior:

    • Default: Priors are informed by costs (channels with more spend receive larger priors).
    • Experiments: Use results from (geo) experiments.
    • Heuristics: Use the "percentage of weeks a channel was used" (assuming higher usage implies higher expected contribution).
    • MTA Integration: Use outputs from Multi-Touch Attribution (MTA) as priors for the MMM.
  3. Evaluate LMMM model performance

    main

    Predictive Performance

    Because LMMM is an optimization and contribution tool rather than a forecasting model, contribution is more important than Out-of-Sample (OOS) predictive performance, though test performance should still be monitored.

    Goodness of Fit Metrics

    For evaluating goodness of fit on test data, it is recommended to use:

    • MAPE (Mean Absolute Percentage Error)
    • Median APE (Absolute Percentage Error)

    These are preferred over R-squared because they are more interpretable for business stakeholders and less sensitive to outliers.

    Defining Media Effectiveness

    Media effectiveness is defined as the percentage by which each media channel contributes to the target variable (e.g., $y := \text{Sum of sales}$)

  4. Configure Media Saturation and Lagging approaches

    main

    To capture how media effects taper off over time, the model offers three functional approaches for media transformations. It is recommended to compare all three and select the one with the best out-of-sample fit:

    • Adstock: Applies an infinite lag that decreases in weight as time passes.
    • Hill-Adstock: Applies a sigmoid-like function for diminishing returns to the output of the adstock function.
    • Carryover: Applies a causal convolution that gives more weight to recent values than distant ones.
  5. Best practices for input data and granularity

    main

    Media Channel Metrics

    You can use impressions, clicks, or cost as input. For non-digital data (like TV), you can use metrics such as TV rating points or cost. The model focuses on the variation within a channel.

    Campaign vs. Channel Level

    LMMM is a macro tool designed for the channel level. Running MMM at the campaign level is not recommended because campaigns with hard starts and stops can disrupt the Adstock memory. For granular digital insights, consider using data-driven multi-touch attribution (MTA).

    Long Sales Cycles

    For lead-generating businesses with long sales cycles, choose a target variable that reflects your goals. If a lead takes months to close, consider using more immediate action KPIs like 'number of conversions', 'number of site visits', or 'form entries'.

  6. Compare Standard vs. Hierarchical (Geo-level) models

    main

    Lightweight MMM supports two primary modeling approaches based on your data granularity:

    1. National level (Standard approach): Used when data is only available at a national aggregate (e.g., total national sales per week). This is the most common format.
    2. Geo level (Sub-national hierarchical approach): Used when data can be aggregated by sub-national dimensions (e.g., sales per state). This approach typically yields more accurate results by utilizing more data points. It is highly recommended for large countries like the US.
  7. Prepare data for LightweightMMM

    main

    To run the model, you need to prepare four primary datasets. Ensure media values do not contain negative numbers.

    • Media data: Metrics per channel and time span (e.g., impressions).
    • Extra features: Other features known ahead of time (e.g., seasonality, holidays).
    • Target: The KPI to predict (e.g., revenue, app installs).
    • Costs: Total cost per media unit per channel.

    Scaling Data

    Bayesian techniques work best with small-scale input data. Do not center variables at 0; sales and media should have a lower bound of 0. Recommended scaling methods:

    1. Target (y): y / jnp.mean(y)
    2. Media (X_m): X_m / jnp.mean(X_m, axis=0) (results in a column mean of 1).

    You can use preprocessing.CustomScaler to apply these transformations.

    import jax.numpy as jnp
    from lightweight_mmm import preprocessing
    
    # Example: Scaling using the mean
    media_scaler = preprocessing.CustomScaler(divide_operation=jnp.mean)
    extra_features_scaler = preprocessing.CustomScaler(divide_operation=jnp.mean)
    target_scaler = preprocessing.CustomScaler(divide_operation=jnp.mean)
    cost_scaler = preprocessing.CustomScaler(divide_operation=jnp.mean)
    
    # Apply transformations
    media_data_train = media_scaler.fit_transform(media_data_train)
    extra_features_train = extra_features_scaler.fit_transform(extra_features_train)
    target_train = target_scaler.fit_transform(target_train)
    costs = cost_scaler.fit_transform(unscaled_costs)
  8. Install lightweight_mmm via PyPI

    main

    The recommended way to install lightweight_mmm is through PyPI. Note that the default installation assumes a CPU setup. If you require specific CUDA/CuDNN versions for JAX, you should follow the official JAX installation instructions before installing the library.

    pip install --upgrade pip
    pip install lightweight_mmm
  9. Refresh and maintain your LMMM model

    main

    The frequency of model refreshes depends on your data frequency (daily vs. weekly) and your decision-making cycle (e.g., quarterly).

    Strategies for refreshing:

    • Expand the data window: Include older data so it continues to influence recent estimates.
    • Discard old data: If media effectiveness or strategies have changed significantly, you may choose to drop older data.
    • Use Posteriors as Priors: When refreshing, you can use the posteriors from a previous modeling cycle as the priors for the new cycle.
  10. Run media budget optimization

    main

    Optimize media spend to maximize sales while keeping the total cost constant. Optimization is performed across channels, not over time.

    Required Parameters:

    • n_time_periods: Number of future time periods to simulate.
    • media_mix_model: The trained model instance.
    • budget: Total budget to allocate.
    • extra_features: Future extra features (must be scaled).
    • prices: Array of price per media unit per channel.
    • media_gap (optional): The gap between training data end and prediction start to allow for correct adstock/carryover transformations.
    from lightweight_mmm import optimize_media
    import numpy as np
    
    # Setup optimization parameters
    budget = 40
    prices = np.array([0.1, 0.11, 0.12])
    extra_features_test = extra_features_scaler.transform(extra_features_test)
    
    # Run optimization
    solution = optimize_media.find_optimal_budgets(
        n_time_periods=extra_features_test.shape[0],
        media_mix_model=mmm,
        budget=budget,
        extra_features=extra_features_test,
        prices=prices)
  11. Install lightweight_mmm

    main

    You can install the recommended stable version via PyPi or the latest development version from GitHub.

    Note for Google Colab users: You must restart the runtime after installation to ensure the package is correctly loaded.

    # Recommended stable version
    pip install --upgrade pip
    pip install lightweight_mmm
    
    # Latest development version from GitHub
    pip install --upgrade git+https://github.com/google/lightweight_mmm.git