Marketing Mix Modeling (MMM) for Macro Budget Allocation
Skill-Marketing-Mix-Modeling · 15-营销投放分析
1. 解决的问题
品牌每个月在不同渠道(Facebook、Google、TikTok、KOL、线下)投入数百万广告费。
2. 核心算法逻辑
核心问题:品牌每个月在不同渠道(Facebook、Google、TikTok、KOL、线下)投入数百万广告费。如何量化每个渠道对销售额的真实增量贡献?如何预测下个月预算调整后的销售表现?
3. 业务应用场景
业务问题:Momcozy 2024年广告总投入600万,分布在:Facebook 240万、Google 180万、TikTok 90万、KOL合作 60万、线下展会 30万。年底复盘发现销售额增长但不知道各渠道真实贡献,2025年预算怎么分配?
| 渠道 | 2024投入 | MMM估算贡献 | 增量ROAS | 饱和状态 | |------|---------|------------|---------|---------| | Facebook | 240万 | 35% | 2.8 | 接近饱和 | | Google | 180万 | 22% | 2.2 | 已饱和(多为收割) | | TikTok | 90万 | 18% | 3.5 | 远未饱和 | | KOL合作 | 60万 | 15% | 4.0 | 中度饱和 | | 线下展会 | 30万 | 5% | 1.2 | 低效 |
关键发现: 1. Google的22%贡献中,约60%实际来自Facebook/TikTok的品牌曝光带来的品牌词搜索 2. TikTok虽投入最少,但边际ROAS最高,增量效应最强 3. 线下展会投入产出比低,建议削减
4. 输入数据要求
请查看原始代码模板获取输入规格。
5. 输出结果
请查看原始代码模板获取输出规格。
6. 业务价值 / ROI
- ROI:预算重新分配后整体销售额提升15-25%,年增收百万级
- 难度:⭐⭐⭐⭐☆(4/5)— 时间序列处理+贝叶斯推断,概念门槛较高
- 优先级:⭐⭐⭐⭐⭐(5/5)— 品牌级预算决策的核心工具
7. 代码模板
代码块数量:1 · 路径:未检测到
"""
Marketing Mix Modeling (MMM) — 营销组合模型
支持:Adstock衰减、Hill饱和、Bayesian回归、预算优化
"""
import numpy as np
import pandas as pd
from scipy.optimize import minimize
class AdstockTransformer:
"""Adstock衰减转换"""
def __init__(self, decay_rate=0.5):
self.decay_rate = decay_rate
def transform(self, spend_series):
"""对单渠道花费序列做Adstock转换"""
adstock = np.zeros(len(spend_series))
adstock[0] = spend_series[0]
for t in range(1, len(spend_series)):
adstock[t] = spend_series[t] + self.decay_rate * adstock[t-1]
return adstock
class HillSaturation:
"""Hill饱和函数"""
def __init__(self, K=0.5, eta=2.0):
self.K = K # 半饱和点
self.eta = eta # 形状参数
def transform(self, x):
"""Hill转换"""
return x ** self.eta / (x ** self.eta + self.K ** self.eta)
class SimpleMMM:
"""简化版营销组合模型"""
def __init__(self):
self.coef = {} # 渠道系数
self.adstock_params = {} # 各渠道衰减率
self.hill_params = {} # 各渠道饱和参数
self.base_sales = 0
self.seasonality_coef = {}
def _apply_transforms(self, spend_df, channels):
"""应用Adstock和Hill转换"""
transformed = pd.DataFrame(index=spend_df.index)
for ch in channels:
# Adstock
adstock = AdstockTransformer(
decay=self.adstock_params.get(ch, 0.5)
).transform(spend_df[ch].values)
# Hill饱和
hill = HillSaturation(
K=self.hill_params.get(ch, {}).get('K', spend_df[ch].median()),
eta=self.hill_params.get(ch, {}).get('eta', 2.0)
)
8. 论文来源
未自动抽取;请查看原始 Skill 卡片。