Ad Spend Time Series Attribution — Adstock 衰减 + 因果 MMM 广告效果归因
Skill-Ad-Spend-Time-Series-Attribution · 13-广告分析
1. 解决的问题
母婴跨境运营黑五大促后不知道广告效果是当周还是前 6 周积累所致,导致次日关停广告恰是最高 ROI 时段——Adstock 时序衰减模型识别各渠道 carryover 窗口,ROAS 计算准确率提升 40%,年化避免错误关停损失 20-80 万元
2. 核心算法逻辑
广告投放存在强烈的时序滞后效应(carryover effect):今天曝光的广告可能要 26 周后才完成最终转化。传统 LastClick 或周级 ROAS 完全忽略这一现象,导致大促后关停广告的决策恰好在 ROI 最高时段。
3. 业务应用场景
场景A:黑五大促 Adstock 衰减率估算(防错误关停)
- 业务问题:Momcozy 吸奶器每年黑五前 6 周在 TikTok/Amazon DSP/Google 全面铺量。大促结束次日 ROAS 数据回落,运营关停广告;但实际上前 6 周曝光的 carryover 效应在接下来 3-4 周仍持续驱动自然转化,关停导致年化损失 20-80 万元。 - 数据要求:8 周以上的渠道级周度投放金额 + 周度销售额(SKU 级),共 3-5 个渠道 - 预期产出:每个渠道的 λ(衰减率)、饱和阈值 β、当周真实贡献 vs. 累计 carryover 贡献拆分 - 业务价值:ROAS 计算准确率提升 40%,大促后正确延续投放窗口 2-3 周,年化增收 20
- 业务问题:手握 TikTok/Amazon/Google 三条渠道,预算 50 万,历史数据显示 TikTok 当周 ROAS 低但大促期间 Halo 效应明显,如何分配 Q4 预算? - 数据要求:同上 + 促销节点标记(Prime Day、黑五、圣诞) - 预期产出:基于学习到的 λ 和饱和曲线,模拟 10 种预算分配方案的预期总销售额,输出 Pareto 最优方案 - 业务价值:在相同预算下销售额提升 8-15%,Q4 增量约 15-40 万元
4. 输入数据要求
请查看原始代码模板获取输入规格。
5. 输出结果
请查看原始代码模板获取输出规格。
6. 业务价值 / ROI
- ROI 预估:ROAS 计算准确率提升 40%,大促后正确延续投放窗口 2-3 周,年化增收 20-80 万元(以 Momcozy 年广告预算 500 万元为基准,0.5% 效率提升即 = 2.5 万元)
- 实施难度:⭐⭐⭐☆☆(主要难点在历史数据清洗和渠道级日/周度归因粒度对齐)
- 优先级:⭐⭐⭐⭐⭐(黑五等大促期广告策略直接影响年度 P&L 的关键路径)
- 适用规模:月广告预算 ≥ 30 万元,3 个以上渠道,历史数据 ≥ 8 周
- 数据要求:渠道级周度花费 + SKU 级周度销售额(可从广告后台 + 财务系统导出)
7. 代码模板
代码块数量:1 · 路径:未检测到
"""
Ad Spend Time Series Attribution with Adstock + Hill Saturation + Simple MMM
场景: Momcozy 吸奶器 8 周三渠道广告数据归因
依赖: numpy, scipy (标准库,无需 deepcausalmmm)
"""
import numpy as np
from scipy.optimize import minimize
from scipy.stats import pearsonr
# ─────────────────────────────────────────
# 核心组件 1: Adstock 几何衰减
# ─────────────────────────────────────────
def adstock_transform(spend: np.ndarray, decay: float) -> np.ndarray:
"""
Adstock 几何衰减变换
Args:
spend: 周度投放金额数组 shape=(T,)
decay: 衰减率 λ ∈ [0, 1],越大持续越久
Returns:
adstocked: 衰减后的有效曝光数组 shape=(T,)
"""
T = len(spend)
adstocked = np.zeros(T)
adstocked[0] = spend[0]
for t in range(1, T):
adstocked[t] = spend[t] + decay * adstocked[t - 1]
return adstocked
# ─────────────────────────────────────────
# 核心组件 2: Hill 饱和曲线
# ─────────────────────────────────────────
def hill_saturation(x: np.ndarray, alpha: float, beta: float) -> np.ndarray:
"""
Hill 饱和曲线,捕捉边际递减效应
Args:
x: 输入投放量(已 Adstock 变换后)
alpha: 形状参数 (>0),控制 S 型曲线斜率
beta: 半饱和点 (>0),x=beta 时 Hill=0.5
Returns:
saturated: 饱和后效果值 ∈ [0, 1)
"""
x_alpha = np.power(np.maximum(x, 1e-10), alpha)
beta_alpha = np.power(beta, alpha)
return x_alpha / (x_alpha + beta_alpha)
# ─────────────────────────────────────────
# 核心组件 3: 简化 MMM 模型(OLS)
# ─────────────────────────────────────────
class SimpleMMM:
"""
简化版 Marketing Mix Model8. 论文来源
- 2510.13087