{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "J_ccrCpFyQ0A" }, "source": [ "(mmm_budget_allocation_example)=\n", "# Budget Allocation with PyMC-Marketing\n", "\n", "The purpose of this notebook is to explore the recently included function in the PyMC-Marketing library that focuses on budget allocation. This function's underpinnings are based on the methodologies inspired by Bolt's work in the article, [\"Budgeting with Bayesian Models\"](https://bolt.eu/en/blog/budgeting-with-bayesian-models-pymc-marketing/).\n", "\n", "## Prerequisite Knowledge\n", "The notebook assumes the reader has knowledge of the essential functionalities of PyMC-Marketing. If one is unfamiliar, the [\"MMM Example Notebook\"](https://www.pymc-marketing.io/en/stable/notebooks/mmm/mmm_example.html) serves as an excellent starting point, offering a comprehensive introduction to media mix models in this context.\n", "\n", "## Introducing the budget allocator\n", "This notebook instigates an examination of the function within the PyMC-Marketing library, which addresses these challenges using Bayesian models. The function intends to provide:\n", "\n", "1. Quantitative measures of the effectiveness of different media channels.\n", "2. Probabilistic ROI estimates under a range of budget scenarios." ] }, { "cell_type": "markdown", "metadata": { "id": "vWMGdRlmyjcI" }, "source": [ "## Basic Setup\n", "Like previous notebooks revolving around PyMC-Marketing, this relies on a specific library set. Here are the requisite imports necessary for executing the provided code snippets subsequently." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "ExecuteTime": { "end_time": "2025-01-15T14:30:44.969426Z", "start_time": "2025-01-15T14:30:37.851150Z" }, "id": "28_D6j7jjQTy" }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "OMP: Info #276: omp_set_nested routine deprecated, please use omp_set_max_active_levels instead.\n", "/Users/carlostrujillo/Documents/GitHub/pymc-marketing/pymc_marketing/mmm/multidimensional.py:72: FutureWarning: This functionality is experimental and subject to change. If you encounter any issues or have suggestions, please raise them at: https://github.com/pymc-labs/pymc-marketing/issues/new\n", " warnings.warn(warning_msg, FutureWarning, stacklevel=1)\n", "/var/folders/f0/rbz8xs8s17n3k3f_ccp31bvh0000gn/T/ipykernel_93500/3141621575.py:9: UserWarning: The pymc_marketing.mmm.builders module is experimental and its API may change without warning.\n", " from pymc_marketing.mmm.builders.yaml import build_mmm_from_yaml\n" ] } ], "source": [ "import warnings\n", "\n", "import arviz as az\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "import pandas as pd\n", "import xarray as xr\n", "\n", "from pymc_marketing.mmm.builders.yaml import build_mmm_from_yaml\n", "from pymc_marketing.mmm.multidimensional import (\n", " MultiDimensionalBudgetOptimizerWrapper,\n", ")\n", "from pymc_marketing.paths import data_dir\n", "\n", "warnings.filterwarnings(\"ignore\")\n", "\n", "az.style.use(\"arviz-darkgrid\")\n", "plt.rcParams[\"figure.figsize\"] = [12, 7]\n", "plt.rcParams[\"figure.dpi\"] = 100\n", "\n", "%load_ext autoreload\n", "%autoreload 2\n", "%config InlineBackend.figure_format = \"retina\"" ] }, { "cell_type": "markdown", "metadata": { "id": "9AlvbqZ6yqhs" }, "source": [ "These imports and configurations form the fundamental setup necessary for the entire span of this notebook.\n", "\n", "The expectation is that a model has already been trained using the functionalities provided in prior versions of the PyMC-Marketing library. Thus, the data generation and training processes will be replicated in a different notebook. Those unfamiliar with these procedures are advised to refer to the [\"MMM Example Notebook.\"](https://www.pymc-marketing.io/en/stable/notebooks/mmm/mmm_example.html)\n", "\n", "## Loading a Pre-Trained Model\n", "To utilize a saved model, load it into a new instance of the MMM class using the `build_mmm_from_yaml` method below." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "seed: int = sum(map(ord, \"mmm_multidimensional\"))\n", "rng: np.random.Generator = np.random.default_rng(seed=seed)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", " | date | \n", "y | \n", "x1 | \n", "x2 | \n", "event_1 | \n", "event_2 | \n", "dayofyear | \n", "t | \n", "geo | \n", "
---|---|---|---|---|---|---|---|---|---|
0 | \n", "2018-04-02 | \n", "3984.662237 | \n", "159.290009 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "92 | \n", "0 | \n", "geo_a | \n", "
1 | \n", "2018-04-09 | \n", "3762.871794 | \n", "56.194238 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "99 | \n", "1 | \n", "geo_a | \n", "
2 | \n", "2018-04-16 | \n", "4466.967388 | \n", "146.200133 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "106 | \n", "2 | \n", "geo_a | \n", "
3 | \n", "2018-04-23 | \n", "3864.219373 | \n", "35.699276 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "113 | \n", "3 | \n", "geo_a | \n", "
4 | \n", "2018-04-30 | \n", "4441.625278 | \n", "193.372577 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "120 | \n", "4 | \n", "geo_a | \n", "
\n", " | mean | \n", "sd | \n", "hdi_3% | \n", "hdi_97% | \n", "mcse_mean | \n", "mcse_sd | \n", "ess_bulk | \n", "ess_tail | \n", "r_hat | \n", "
---|---|---|---|---|---|---|---|---|---|
saturation_beta[x1] | \n", "0.371 | \n", "0.021 | \n", "0.332 | \n", "0.410 | \n", "0.000 | \n", "0.000 | \n", "2785.0 | \n", "2715.0 | \n", "1.0 | \n", "
saturation_beta[x2] | \n", "0.273 | \n", "0.062 | \n", "0.190 | \n", "0.390 | \n", "0.001 | \n", "0.002 | \n", "2107.0 | \n", "2185.0 | \n", "1.0 | \n", "
saturation_lam[x1] | \n", "4.013 | \n", "0.419 | \n", "3.166 | \n", "4.757 | \n", "0.008 | \n", "0.008 | \n", "2692.0 | \n", "2344.0 | \n", "1.0 | \n", "
saturation_lam[x2] | \n", "2.728 | \n", "0.983 | \n", "1.187 | \n", "4.665 | \n", "0.021 | \n", "0.022 | \n", "2156.0 | \n", "1996.0 | \n", "1.0 | \n", "
adstock_alpha[x1] | \n", "0.395 | \n", "0.033 | \n", "0.335 | \n", "0.458 | \n", "0.001 | \n", "0.000 | \n", "3571.0 | \n", "3268.0 | \n", "1.0 | \n", "
adstock_alpha[x2] | \n", "0.183 | \n", "0.041 | \n", "0.105 | \n", "0.257 | \n", "0.001 | \n", "0.001 | \n", "2940.0 | \n", "2526.0 | \n", "1.0 | \n", "
<xarray.DataArray (channel: 2)> Size: 16B\n", "array([2000., 2000.])\n", "Coordinates:\n", " * channel (channel) <U2 16B 'x1' 'x2'
<xarray.DataArray 'allocation' (channel: 2)> Size: 16B\n", "array([2000., 2000.])\n", "Coordinates:\n", " * channel (channel) <U2 16B 'x1' 'x2'" ], "text/plain": [ "
<xarray.DataArray 'x1' (date: 21)> Size: 168B\n", "array([2001.05516828, 1998.17680521, 2000.86259682, 2000.53354004,\n", " 2001.24720109, 2001.03767898, 2000.10398136, 2002.55438021,\n", " 2000.10373669, 1999.06157133, 2000.07774446, 2000.98811459,\n", " 2000.96803296, 0. , 0. , 0. ,\n", " 0. , 0. , 0. , 0. ,\n", " 0. ])\n", "Coordinates:\n", " * date (date) datetime64[ns] 168B 2021-09-06 2021-09-13 ... 2022-01-24" ], "text/plain": [ "
<xarray.Dataset> Size: 4MB\n", "Dimensions: (date: 21, geo: 2, sample: 4000,\n", " channel: 2)\n", "Coordinates:\n", " * date (date) datetime64[ns] 168B 2021-...\n", " * geo (geo) <U5 40B 'geo_a' 'geo_b'\n", " * channel (channel) <U2 16B 'x1' 'x2'\n", " * sample (sample) object 32kB MultiIndex\n", " * chain (sample) int64 32kB 0 0 0 ... 3 3 3\n", " * draw (sample) int64 32kB 0 1 ... 998 999\n", "Data variables:\n", " y (date, geo, sample) float64 1MB ...\n", " channel_contribution (date, geo, channel, sample) float64 3MB ...\n", " total_media_contribution_original_scale (sample) float64 32kB 1.486e+05 ...\n", " allocation (geo, channel) float64 32B 1.372...\n", " x1 (date, geo) float64 336B 1.373e+...\n", " x2 (date, geo) float64 336B 1.235e+...\n", "Attributes:\n", " created_at: 2025-07-25T14:54:53.250347+00:00\n", " arviz_version: 0.22.0\n", " inference_library: pymc\n", " inference_library_version: 5.25.1" ], "text/plain": [ "
<xarray.DataArray (geo: 2, channel: 2)> Size: 32B\n", "array([[1., 1.],\n", " [1., 1.]])\n", "Coordinates:\n", " * geo (geo) <U5 40B 'geo_a' 'geo_b'\n", " * channel (channel) <U2 16B 'x1' 'x2'