别再纠结归因模型了!用Python实战Shapley Value,5分钟算出每个渠道的真实贡献
2026/4/24 9:19:41 网站建设 项目流程

破解营销归因难题:用Shapley Value量化渠道真实贡献

当你在月度营销复盘会上展示数据时,是否经常遇到这样的场景?SEM团队坚持最后一次点击的功劳最大,社交媒体团队强调首次触达的培育价值,而内容团队则认为中间环节的持续曝光才是关键。传统的归因模型就像一把钝刀,无法精准切割出每个渠道的真实价值。今天,我们将用博弈论的经典方法——Shapley Value,配合Python实战,为你提供一把科学的手术刀。

1. 为什么传统归因模型总让人不满意?

营销归因就像分蛋糕,常见的方法各有局限:

  • 最后一次点击:把100%功劳给转化前的最后一个渠道,忽视了用户旅程中的其他接触点
  • 首次点击:完全归功于最初引流的渠道,无视后续转化的关键推动
  • 线性归因:平均分配功劳,忽略了不同渠道的实际影响力差异
  • 时间衰减:越接近转化的渠道权重越高,但衰减系数的设定充满主观性

这些规则式模型的核心问题在于预先假设了分配逻辑,而非让数据自己说话。我们来看一个真实案例:

# 传统归因模型结果示例 attribution_results = { 'last_click': {'SEM': 650, 'Social': 200, 'Email': 150}, 'first_click': {'SEM': 300, 'Social': 500, 'Email': 200}, 'linear': {'SEM': 350, 'Social': 400, 'Email': 250} }

同一组数据,不同模型得出的结论可能截然相反。这就是营销分析师常说的"归因悖论"——模型选择决定了结果,而非结果验证模型。

2. Shapley Value:来自博弈论的公平分配方案

Shapley Value由诺贝尔经济学奖得主Lloyd Shapley提出,最初用于解决合作博弈中的利益分配问题。其核心思想是:每个参与者的贡献度,应该等于其在所有可能联盟组合中的边际贡献平均值

2.1 基本原理与计算公式

Shapley Value的数学表达为:

φ_i = Σ (|S|!(n-|S|-1)!)/n! * (v(S∪{i}) - v(S))

其中:

  • φ_i:渠道i的Shapley Value
  • S:不包含i的所有可能渠道子集
  • n:总渠道数
  • v(S):子集S的转化价值

这个公式可能看起来复杂,但我们可以通过一个简单例子来理解:

假设有三个营销渠道:

  • 信息流广告(A):单独转化价值=50
  • 开屏广告(B):单独转化价值=30
  • 视频贴片广告(C):单独转化价值=20
  • A+B联合价值=100
  • A+C联合价值=90
  • B+C联合价值=60
  • A+B+C联合价值=150

计算A的Shapley Value需要考虑所有包含A的可能组合:

组合边际贡献权重
A50-0 =501/3
A+B100-30=701/6
A+C90-20=701/6
A+B+C150-60=901/3

A的贡献值 = 50*(1/3) + 70*(1/6) + 70*(1/6) + 90*(1/3) = 70

同理可计算出B=45,C=35。这种分配既考虑了单独效果,也评估了协同效应。

2.2 与马尔科夫链归因的对比

两种先进归因方法的异同:

维度Shapley Value马尔科夫链
计算复杂度渠道少时简单,随渠道数指数增长需要大量路径模拟,计算成本高
顺序敏感性基础版本不考虑顺序高度关注触点顺序
结果解释性直观的贡献百分比转移概率矩阵需要专业解释
数据需求需要各渠道组合的效果数据需要完整用户路径序列

提示:当渠道数量超过10个时,建议使用简化版的Shapley算法或马尔科夫链的近似计算

3. Python实战:从数据到归因分析

让我们用真实数据实现Shapley Value归因。假设我们有一个电商平台的营销接触数据:

import pandas as pd from itertools import chain, combinations from math import factorial # 示例数据:渠道组合及其转化次数 data = { 'channel_subset': ['SEM', 'Social', 'Email', 'SEM,Social', 'SEM,Email', 'Social,Email', 'SEM,Social,Email'], 'converted': [1200, 800, 600, 2000, 1800, 1500, 2500] } df = pd.DataFrame(data) # 计算所有子集的价值函数 def v_function(subset, c_values): key = ','.join(sorted(subset)) return c_values.get(key, 0) # 生成所有可能子集 def power_set(items): return chain.from_iterable(combinations(items, r) for r in range(len(items)+1)) # 计算Shapley Value def calculate_shapley(df, channel_col='channel_subset', value_col='converted'): c_values = df.set_index(channel_col).to_dict()[value_col] channels = list(set(chain(*[x.split(',') for x in df[channel_col]]))) v_values = {} for subset in power_set(channels): v_values[','.join(sorted(subset))] = v_function(subset, c_values) shapley = {} n = len(channels) for channel in channels: sv = 0 for subset in v_values: if channel not in subset.split(','): subset_list = subset.split(',') if subset else [] cardinality = len(subset_list) weight = (factorial(cardinality)*factorial(n-cardinality-1))/factorial(n) subset_with_channel = ','.join(sorted(subset_list + [channel])) marginal_contribution = v_values[subset_with_channel] - v_values[subset] sv += weight * marginal_contribution shapley[channel] = sv return shapley shapley_values = calculate_shapley(df) print("各渠道Shapley Value贡献:", shapley_values)

执行结果可能类似于:

各渠道Shapley Value贡献: { 'SEM': 1266.67, 'Social': 833.33, 'Email': 400.00 }

4. 进阶技巧:处理现实中的复杂场景

4.1 简化计算:应对渠道爆炸问题

当渠道数量较多时(如超过10个),完全计算Shapley Value会面临组合爆炸。这时可以采用:

  1. 蒙特卡洛模拟:随机采样部分排列组合进行近似计算
  2. 分层归因:先对渠道分类(如付费渠道、自有渠道),再分层计算
  3. 有序Shapley值:考虑渠道出现顺序的改进算法
# 有序Shapley值的简化实现 def ordered_shapley(journeys): channel_values = {channel:0 for channel in set(chain(*journeys))} total = len(journeys) for journey in journeys: for pos, channel in enumerate(journey): # 位置权重:越早出现权重越高 weight = (len(journey)-pos)/sum(range(1,len(journey)+1)) channel_values[channel] += weight return {k:v/total for k,v in channel_values.items()} # 示例用户旅程数据 user_journeys = [ ['SEM', 'Social', 'Email'], ['Social', 'Email'], ['SEM', 'Email'], ['Email', 'SEM'] # 顺序不同会产生不同贡献 ] print("有序Shapley结果:", ordered_shapley(user_journeys))

4.2 异常情况处理

实际分析中常遇到的挑战及解决方案:

  • 数据稀疏问题:某些渠道组合样本量不足
    • 解决方案:使用贝叶斯平滑或合并相似渠道
  • 路径长度差异大:有的用户旅程包含20+触点
    • 解决方案:设置最大路径长度或分段处理
  • 跨设备归因:用户在不同设备间切换
    • 解决方案:结合用户ID映射或概率匹配

注意:当某个渠道的Shapley Value异常高时,需要检查是否存在刷单等作弊行为

5. 从归因到决策:优化营销预算分配

计算出各渠道的Shapley Value后,可以制作贡献-成本对比图:

import matplotlib.pyplot as plt # 假设我们有以下数据 channels = ['SEM', 'Social', 'Email'] contributions = [1266, 833, 400] # Shapley Value costs = [800, 500, 300] # 各渠道投入成本 roi = [c/costs[i] for i,c in enumerate(contributions)] plt.figure(figsize=(10,5)) plt.bar(channels, roi, color=['#FF6B6B','#4ECDC4','#45B7D1']) plt.title('各渠道ROI对比 (基于Shapley Value归因)') plt.ylabel('投资回报率(ROI)') plt.grid(axis='y', linestyle='--', alpha=0.7) plt.show()

根据分析结果,可以制定如下优化策略:

  1. 高效渠道扩容:对ROI高于平均的渠道适当增加预算
  2. 组合效果测试:识别有正向协同效应的渠道组合
  3. 低效渠道优化:对持续低贡献的渠道进行改造或淘汰
  4. 触点顺序优化:根据有序Shapley结果调整用户旅程设计

在实际项目中,我们曾帮助一个零售客户通过Shapley Value分析发现:虽然SEM的直接转化表现一般,但当它与电子邮件营销组合时,会产生1+1>2的效果。调整策略后,在总预算不变的情况下,季度GMV提升了18%。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询