Skip to content

M1. 营销组合模型 (MMM) 决策

案例来源: Robyn (Meta) + Google-Lightweight-MMM
决策类型: 营销预算分配优化
方法论: 贝叶斯 MMM + 渠道 ROI 归因
预计阅读时间: 18 分钟


1. 决策背景

业务场景

某电商公司年度营销预算¥5 亿,面临预算分配难题: - 营销渠道:15+ (搜索/信息流/社交/视频/KOL/...) - 归因困难:用户旅程平均 5-8 个触点 - 预算浪费:约 30% 预算效果难以衡量 - 部门冲突:各渠道团队争夺预算,缺乏客观依据

决策者角色

  • 主要决策者: CMO/营销副总裁
  • 执行团队: 渠道营销团队 (50+ 人)
  • 影响对象:各渠道代理商/供应商
  • 利益相关者: 财务部门、数据分析团队、CEO

决策频率

  • 战略决策: 年度/季度预算规划
  • 战术决策: 月度预算调整
  • 运营决策: 周度/日度出价优化

当前痛点

预算分配 = 历史占比 + 部门博弈 + 直觉判断
    30% 预算浪费 + ROI 难以提升

2. 决策问题

核心问题 (5W1H)

维度 描述
What 如何科学分配¥5 亿营销预算?
Who 15+ 营销渠道
When 季度规划 + 月度调整
Where 全渠道 (线上 + 线下)
Why 提升 ROI,减少浪费
How 营销组合模型 (MMM)

决策目标

定量目标: - 整体营销 ROI: 1:3 → 1:4 - 预算浪费:30% → < 10% - 获客成本:降低 20% - 预测准确度:> 85%

定性目标: - 预算分配有据可依 - 减少部门间冲突 - 提升决策透明度

约束条件

类型 约束
数据 仅能使用聚合数据 (隐私合规)
时间 2 个月内完成首期模型
预算 ¥2M 模型建设预算
组织 需获得各渠道团队认可

3. 决策框架

方法论:贝叶斯营销组合模型

营销投入 → [饱和曲线 + 衰减效应] → 品牌认知 → 购买转化
         贝叶斯推断 + MCMC 采样
         渠道 ROI + 最优预算分配

选择贝叶斯方法理由: - ✅ 处理小样本 (相对渠道数量) - ✅ 量化不确定性 (置信区间) - ✅ 融入先验知识 (专家经验) - ✅ 输出可解释 (ROI 分布)

决策流程

graph LR
    A[历史数据] --> B[模型构建]
    B --> C[参数估计]
    C --> D[ROI 计算]
    D --> E[预算优化]
    E --> F[执行监控]
    F --> G[模型更新]
    G --> C

核心公式

广告响应函数 (Adstock + Saturation):

Adstock(t) = Σ λ^k × Spend(t-k)  # 延迟效应
Response(t) = α + β × Adstock(t)^γ  # 饱和曲线

参数含义: - λ: 衰减率 (0-1,越大持续越久) - γ: 饱和系数 (<1 表示边际收益递减) - β: 渠道效率系数

不确定性管理

不确定性 来源 处理方法
参数不确定性 数据有限 贝叶斯后验分布
模型不确定性 函数形式 多模型对比
外部因素 季节/竞争 控制变量 + 敏感性分析

4. 数据与模型

数据来源

数据 粒度 时间跨度 质量
渠道花费 周度 2 年 ✅ 95%
销售数据 周度 2 年 ✅ 98%
促销活动 周度 2 年 ✅ 90%
节假日 日度 - ✅ 100%
竞争对手 周度 1 年 ⚠️ 70%
季节性 周度 - ✅ 100%

模型规格

Robyn 模型 (Meta 开源):

library(robyn)

# 模型构建
robyn_model <- robyn(
  data = marketing_data,
  date_var = "week",
  dv = "sales",
  spend_vars = c("search", "social", "display", "video", "kOL"),
  p_expt = c("promotion", "seasonality"),
  adstock_max_lag = 8  # 最大 8 周延迟
)

# 贝叶斯推断
robyn_output <- robyn_fit(
  model = robyn_model,
  iterations = 1000,
  chains = 4
)

关键输出

1. 渠道 ROI 分布: | 渠道 | 中位数 ROI | 95% CI | 预算建议 | |------|-----------|--------|----------| | 搜索广告 | 1:4.2 | [3.8, 4.6] | 增加 30% | | 信息流 | 1:3.5 | [2.9, 4.1] | 保持 | | KOL | 1:2.8 | [2.1, 3.5] | 减少 20% | | 视频 | 1:2.5 | [1.9, 3.1] | 减少 30% | | 展示广告 | 1:1.8 | [1.2, 2.4] | 大幅削减 |

2. 饱和曲线参数: | 渠道 | 饱和点 (万元/周) | 半衰期 (周) | |------|-----------------|------------| | 搜索 | 800 | 4.2 | | 信息流 | 500 | 3.5 | | KOL | 200 | 2.8 | | 视频 | 600 | 5.1 |

3. 最优预算分配:

当前分配:搜索 25% / 信息流 30% / KOL 20% / 视频 15% / 展示 10%
最优分配:搜索 35% / 信息流 30% / KOL 15% / 视频 10% / 展示 5% / 其他 5%
预期 ROI 提升:1:3.0 → 1:4.2 (+40%)


5. 决策实施

实施路线图

阶段 1: 数据准备 (3 周)

Week 1: 数据收集与清洗
Week 2: 特征工程 (Adstock 变换)
Week 3: 数据质量验证

阶段 2: 模型开发 (5 周)

Week 4-5: 基线模型构建
Week 6-7: 贝叶斯推断 + 诊断
Week 8: 模型验证 + 回溯测试

阶段 3: 决策支持 (4 周)

Week 9: 预算优化求解器
Week 10: 情景分析工具
Week 11: Dashboard 开发
Week 12: 用户培训

工具栈

组件 工具 理由
模型 Robyn (R) Meta 开源,贝叶斯 MMM 最佳实践
替代 Lightweight MMM (Python) Google 开源,轻量级
优化 scipy.optimize 预算分配求解
Dashboard Streamlit 快速原型
调度 Airflow 自动化更新

变更管理

利益相关者沟通: - 高层: 月度 ROI 报告 + 预算建议 - 渠道团队: 周度 Dashboard + 解读培训 - 财务: 模型审计 + 合规文档

决策透明化:

每次预算调整 → 模型输出 + 人工审核 + 变更记录
         全员可见的决策日志


6. 决策结果

业务影响 (上线 6 个月后)

指标 基线 当前 改善
整体 ROI 1:3.0 1:4.1 +37%
获客成本 ¥180 ¥142 -21%
预算浪费 30% 12% -60%
预测准确度 65% 88% +35%
部门冲突 高频 显著降低 定性改善

ROI 提升分解

ROI 提升 37% = 
  预算重新分配贡献 22% +
  低效渠道削减贡献 10% +
  季节性优化贡献 5%

财务价值

年度影响: - 营销预算:¥500M - ROI 提升:1:3.0 → 1:4.1 - 增量收入:¥500M × (4.1 - 3.0) = ¥550M

投入产出: - 模型建设:¥2M - 年度收益:¥550M - ROI: 275 倍

组织影响

正面: - ✅ 预算决策从"博弈"转向"数据驱动" - ✅ 渠道团队聚焦优化而非争夺预算 - ✅ 财务部门认可模型审计结果

挑战: - ⚠️ 初期渠道团队抵触 (担心预算被砍) - ⚠️ 需要持续教育 (模型不是万能) - ⚠️ 数据质量依赖 (垃圾进垃圾出)


7. 决策改进

反馈机制

监控指标:

# 每周计算
weekly_metrics = {
    'mape': mean_absolute_percentage_error(actual, predicted),
    'roi_stability': roi_this_week / roi_last_week,
    'budget_variance': actual_spend / planned_spend
}

# 预警阈值
if mape > 0.20:
    alert("预测误差超过 20%,需要检查模型")
if roi_stability < 0.8 or roi_stability > 1.2:
    alert("ROI 波动异常")

迭代计划

V1.0 (当前): 聚合数据 + 周度更新 V2.0 (3 月): 区域细分模型 + 更细粒度 V3.0 (6 月): 实时数据 + 自动优化 V4.0 (12 月): 跨渠道归因 + 用户级建模

扩展场景

场景 优先级 预期价值
新品上市预算 P0 成功率 +30%
区域预算分配 P0 ROI +15%
促销效果评估 P1 促销 ROI +25%
品牌广告评估 P2 长期价值量化

8. 附录

Robyn 模型代码

library(robyn)

# 1. 数据准备
data <- read.csv("marketing_data.csv")

# 2. 模型配置
model_config <- robyn(
  data = data,
  date_var = "week",
  dv = "sales",
  spend_vars = c("search_branded", "search_nonbranded", 
                 "social", "display", "video", "kOL"),
  p_expt = c("promotion_flag", "seasonality_index"),
  adstock_max_lag = 8
)

# 3. 模型拟合
output <- robyn_fit(
  model = model_config,
  iterations = 1000,
  chains = 4,
  seed = 123
)

# 4. 结果提取
roi_table <- robyn_decompose(output)
budget_optimizer <- robyn_allocator(output, budget = 500000000)

# 5. 可视化
robyn_plot(output, type = "decomposition")
robyn_plot(output, type = "response_curve")

关键假设检验

# 1. 收敛性诊断 (R-hat < 1.1)
r_hat <- summary(output)$rhat
if (any(r_hat > 1.1)) {
  warning("部分参数未收敛,需要增加迭代次数")
}

# 2. 后验预测检验
pp_check(output)  # 模型拟合度检查

# 3. 敏感性分析
sensitivity_results <- lapply(c(0.5, 0.8, 0.95), function(prior) {
  robyn_fit(model, prior_weight = prior)
})

预算优化求解器

from scipy.optimize import minimize

def negative_roi(budget_allocation, roi_params):
    """负 ROI 函数 (最小化)"""
    total_roi = 0
    for i, channel in enumerate(channels):
        spend = budget_allocation[i]
        alpha, beta, gamma = roi_params[channel]
        response = alpha + beta * spend ** gamma
        total_roi += response
    return -total_roi  # 最小化负 ROI

# 约束条件
constraints = [
    {'type': 'eq', 'fun': lambda x: sum(x) - total_budget},  # 预算花完
    {'type': 'ineq', 'fun': lambda x: x - min_spend},  # 最低预算
]

# 求解
result = minimize(negative_roi, x0=initial_allocation, 
                  args=(roi_params,), constraints=constraints)
optimal_allocation = result.x

案例版本: v1.0
最后更新: 2026-06-03
维护者: 营销科学团队