Optimisation API

AMMM3 exposes the retained optimisation surface through abacus.mmm.optimization.

For workflow guidance and interpretation, see Optimisation.

Primary wrapper

Recommended import path:

from abacus.mmm.optimization import PanelBudgetOptimizerWrapper

PanelBudgetOptimizerWrapper adapts a fitted PanelMMM to the generic budget optimiser.

Constructor:

wrapper = PanelBudgetOptimizerWrapper(
    model=mmm,
    start_date="2025-03-03",
    end_date="2025-03-31",
)

Main constructor arguments:

ArgumentMeaning
modelFitted PanelMMM
start_dateOptimisation window start date
end_dateOptimisation window end date
compile_kwargsOptional compilation settings

Useful attributes:

AttributeMeaning
start_dateRequested window start
end_dateRequested window end
num_periodsNumber of periods in the optimisation window
zero_dataSynthetic zero-spend future dataset
channel_columnsModelled channels
dimsBudget dims beyond date

Main methods

PanelBudgetOptimizerWrapper exposes two user-facing methods:

MethodPurpose
optimize_budget(...)Optimise allocation over the future window
sample_response_distribution(...)Simulate spend and contribution outcomes for an allocation

optimize_budget(...)

Key arguments:

ArgumentMeaning
budgetTotal spend across all optimised cells for one model period
budget_boundsOptional per-cell lower and upper bounds
response_variableObjective variable to optimise
utility_functionUtility function applied to the response distribution
constraintsExtra custom constraints
default_constraintsWhether to add the default sum constraint
budgets_to_optimizeOptional boolean mask over budget cells
budget_distribution_over_periodOptional date flighting weights
callbackWhether to return iteration diagnostics

Return values:

  • allocation, result
  • allocation, result, callback_info when callback=True

allocation is an xarray.DataArray over the non-date budget dimensions. result is SciPy OptimizeResult.

sample_response_distribution(...)

Key arguments:

ArgumentMeaning
allocation_strategyOptimised or manually supplied allocation
noise_levelRelative noise added to the synthetic future spend
additional_var_namesExtra posterior predictive variables to include
include_observationInclude the observation output and total media contribution; default True
include_last_observationsPass lag context into posterior predictive sampling
include_carryoverExtend and zero the tail to capture carryover
budget_distribution_over_periodOptional date flighting weights

It returns an xarray.Dataset containing:

  • allocation
  • one variable per channel for realised spend
  • the model output variable
  • channel_contribution
  • total_media_contribution_original_scale
  • any extra requested variables

Response evaluation without optimisation

PanelResponseDistributionWrapper accepts model, start_date, end_date and optional compile_kwargs, with the same window convention as the budget wrapper. Import it from abacus.mmm.optimization.

Its sample_response_distribution(allocation_strategy, ...) method accepts an xarray.DataArray of per-period allocations over channel and model dimensions. It returns an xarray.Dataset of spend, allocation and requested response variables. The options are shared with the method described above, including include_observation=True, which includes the observation output and total media contribution. Set include_observation=False for channel-contribution sampling without those observation outputs.

Use noise_level=0 when you need the supplied deterministic allocation. include_last_observations=False is the default; enable it when fitted lag history should inform the scenario. include_carryover=True extends the window with a zero-spend tail. Optional budget_distribution_over_period weights redistribute spend within the requested window.

This wrapper does not invoke a budget optimiser. Prediction still enforces the fitted estimator’s operation gates and unit contract. In particular, response evaluation does not make fixed-budget optimisation available for named FE or CRE. For retained FE/CRE manual scenarios, use Scenario Planning.

Merging optimiser-compatible models

BuildMergedModel(models, prefixes=None, merge_on="channel_data", use_every_n_draw=1) is exported from abacus.mmm.optimization. It combines one or more OptimizerCompatibleModelWrapper objects for use with BudgetOptimizer from abacus.mmm.budget_optimizer.

ArgumentContract
modelsNon-empty list of fitted optimiser-compatible wrappers
prefixesOne prefix per model; defaults to model1, model2 and so on
merge_onShared model variable, default channel_data; None disables this named shared variable
use_every_n_drawDraw-slice step, default 1; callers must supply a positive integer

The wrapper prefixes non-shared variables and dimensions, merges retained inference data and prepares a combined optimisation graph. It takes the period count and available adstock information from the first wrapper. It does not refit the component models or estimate their posterior dependence.

Use compatible spend units, coordinates and horizons across wrappers. Select an objective that exists in the merged graph and has the intended outcome units. Merging does not establish statistical comparability or bypass the operation gates of the wrapped models.

Advanced exported helpers

The same module also exports:

from abacus.mmm.optimization import (
    CustomModelWrapper,
    MinimizeException,
    OptimizerCompatibleModelWrapper,
    optimizer_xarray_builder,
)

These are advanced surfaces for custom optimiser integrations.

NamePurpose
CustomModelWrapperWrap a custom PyMC model for optimisation
OptimizerCompatibleModelWrapperProtocol for compatible wrappers
optimizer_xarray_builder(...)Build shaped xarray inputs for optimisation
MinimizeExceptionException raised when optimisation fails

Import-path note

abacus.mmm.panel also re-exports PanelBudgetOptimizerWrapper, but the recommended reference import path is abacus.mmm.optimization.