Guide: Performing Budget Optimisation¶
This guide explains how to use the budget optimisation features within the ammm library.
Overview¶
Budget optimisation aims to find the allocation of a total marketing budget across different channels that is predicted to maximise the overall contribution (e.g., sales, conversions), based on the fitted MMM and the estimated response curves for each channel. The core principle behind this is to allocate spend to channels where the marginal ROI (mROI)—the return from the next dollar spent—is highest, until the mROIs equalize across channels or budget constraints are met.
Prerequisites¶
Response Curve Parameters: You need response curve parameters for each channel (e.g.
(alpha, lam)for a sigmoid). These are typically estimated from a fitted MMM.Understanding of the Process: The optimization is a two-step process:
First, a parametric curve (e.g., sigmoid) is fitted to the channel contributions from the Bayesian model.
Second, a numerical optimizer finds the budget allocation that maximizes the sum of these curves, given a total budget and constraints.
Runnable Example¶
This example demonstrates how to run the budget optimiser in a self-contained way.
In practice, you estimate the response curve parameters from a fitted MMM (for example by using the optimisation helper methods on the model).
import core.opt as opt
print("Running a self-contained optimisation example...")
# Channels to allocate budget across
channels = ["channel_1", "channel_2", "channel_3"]
# Example sigmoid response parameters for each channel: (alpha, lam)
# In practice, you estimate these from a fitted MMM.
parameters = {
"channel_1": (50_000.0, 1.0e-5),
"channel_2": (60_000.0, 8.0e-6),
"channel_3": (40_000.0, 1.2e-5),
}
total_budget = 100_000.0
# Optional per-channel min/max bounds
budget_ranges = {
"channel_1": (0.0, 60_000.0),
"channel_2": (0.0, 70_000.0),
"channel_3": (0.0, 50_000.0),
}
results = opt.budget_allocator(
method="sigmoid",
total_budget=total_budget,
channels=channels,
parameters=parameters,
budget_ranges=budget_ranges,
)
print("Optimisation results:")
print(results)
# The output DataFrame shows the estimated contribution and the optimal budget
# for each channel, as well as the total.
Interpreting the Results¶
The output of the example script will be a DataFrame that looks something like this (values will vary):
estimated_contribution optimal_budget
channel_1 25000.00 30000.00 channel_2 35000.00 40000.00 … total 150000.00 160000.00
optimal_budget: This column shows the suggested budget allocation after optimisation. Compare this to the historical spend to see the recommended shifts.estimated_contribution: This column shows the estimated contribution from each channel based on the optimal budget.
Key Considerations¶
Approximation: The optimisation relies on the accuracy of the fitted parametric response curves (e.g., sigmoid). These are approximations of the true, non-parametric response curves from the Bayesian model.
Total Budget: The optimisation allocates a fixed total budget. It suggests how to best spend that amount, not whether to increase or decrease the total budget.
Constraints: If you provide
budget_ranges, the optimizer will respect them. This is useful for incorporating business constraints.Model Accuracy: The optimisation is only as good as the underlying MMM fit. Ensure your main model diagnostics are satisfactory before trusting the optimization results.