渠道归因(三)基于Shapley Value的渠道归因

news2024/11/15 16:29:01

渠道归因(三)基于Shapley Value的渠道归因

通过Shapley Value可以计算每个渠道的贡献权重,而且沙普利值的计算只需要参加的渠道总数,不考虑顺序,因此计算成本也较低。

传统的shapeley value

import itertools
from pathlib import Path
from collections import defaultdict
from itertools import combinations, permutations
import numpy as np 
import pandas as pd 
import matplotlib.pyplot as plt
import seaborn as sns

本文所有数据如果有需要的同学可关注公众号HsuHeinrich,回复【数据挖掘-渠道归因】自动获取~

# 读取数据
df_mark=pd.read_excel('./shapley/marketing.xlsx')
df_mark.head() # 渠道流转路径,该流转路径下成功转化的次数

数据格式要求:

marketing_channel_subset:渠道流转路径,英文逗号分隔

converted:成功转化次数

marketing_channel_subsetconverted
0Email110
1Email,Facebook11
2Email,Facebook,House Ads8
3Email,Facebook,House Ads,Instagram0
4Email,House Ads40
def power_set(List):
    PS = [list(j) for i in range(len(List)) for j in itertools.combinations(List, i+1)]
    return PS

def factorial(n):
    if n == 0:
        return 1
    else:
        return n * factorial(n-1)
    
def v_function(A,C_values):
    '''
    This function computes the worth of each coalition.
    inputs:
            - A : a coalition of channels.
            - C_values : A dictionnary containing the number of conversions that each subset of channels has yielded.
    '''
    subsets_of_A = subsets(A)
    worth_of_A=0
    for subset in subsets_of_A:
        if subset in C_values:
            worth_of_A += C_values[subset]
    return worth_of_A

def subsets(s):
    '''
    This function returns all the possible subsets of a set of channels.
    input :
            - s: a set of channels.
    '''
    if len(s)==1:
        return s
    else:
        sub_channels=[]
        for i in range(1,len(s)+1):
            sub_channels.extend(map(list,itertools.combinations(s, i)))
    return list(map(",".join,map(sorted,sub_channels)))
  

def calculate_shapley(df, channel_name, conv_name):
    '''
    This function returns the shapley values
            - df: A dataframe with the two columns: ['channel_subset', 'count'].
            The channel_subset column is the channel(s) associated with the conversion and the count is the sum of the conversions. 
            - channel_name: A string that is the name of the channel column 
            - conv_name: A string that is the name of the column with conversions
            **Make sure that that each value in channel_subset is in alphabetical order. Email,PPC and PPC,Email are the same 
            in regards to this analysis and should be combined under Email,PPC.
            
    '''
    # casting the subset into dict, and getting the unique channels
    c_values = df.set_index(channel_name).to_dict()[conv_name]
    df['channels'] = df[channel_name].apply(lambda x: x if len(x.split(",")) == 1 else np.nan)
    channels = list(df['channels'].dropna().unique())
    
    v_values = {}
    for A in power_set(channels): #generate all possible channel combination
        v_values[','.join(sorted(A))] = v_function(A,c_values)
    n=len(channels) #no. of channels
    shapley_values = defaultdict(int)

    for channel in channels:
        for A in v_values.keys():
            if channel not in A.split(","):
                cardinal_A=len(A.split(","))
                A_with_channel = A.split(",")
                A_with_channel.append(channel)            
                A_with_channel=",".join(sorted(A_with_channel))
                weight = (factorial(cardinal_A)*factorial(n-cardinal_A-1)/factorial(n)) # Weight = |S|!(n-|S|-1)!/n!
                contrib = (v_values[A_with_channel]-v_values[A]) # Marginal contribution = v(S U {i})-v(S)
                shapley_values[channel] += weight * contrib
        # Add the term corresponding to the empty set
        shapley_values[channel]+= v_values[channel]/n 
        
    return shapley_values
# 计算渠道shapley value--不考虑顺序
shapley_dict = calculate_shapley(df_mark, 'marketing_channel_subset', 'converted')
shapley_result = pd.DataFrame(list(shapley_dict.items()), columns=['channel', 'shapley_value'])
# 绘制条形图
plt.subplots(figsize=(15,8))
s = sns.barplot(x='channel', y='shapley_value', data=shapley_result)
sns.despine(top=True, right=True)
for idx, row in shapley_result.iterrows():
    s.text(row.name, row.shapley_value +5, round(row.shapley_value,1), ha='center', color='darkslategray', fontweight='semibold')
plt.title("ADVERTISING CHANNEL'S SHAPLEY VALUE", 
          fontdict={'fontsize': 15, 'fontweight': 'semibold', 'color':'#444444'}, 
          loc='center', pad=10)
plt.show()

output_34_0

升级版的shapeley value

import json
import os

# 加载自定义模块
import sys
sys.path.append("./shapley/")
from ordered_shapley_attribution_model import OrderedShapleyAttributionModel
from simplified_shapley_attribution_model import SimplifiedShapleyAttributionModel
# 读取数据
with open("./shapley/user_journeys.json", "r") as f:
    journeys = json.load(f)
    
journeys[:5] # 用户各渠道流转日志,数字表示渠道代号

数据格式要求:json数据,每一行为成功转化的流转路径,数字为渠道ID

[[16, 4, 3, 5, 10, 8, 6, 8, 13, 20],
 [2, 1, 9, 10, 1, 4, 3],
 [9, 13, 20, 16, 15],
 [8, 15, 20],
 [16, 9, 13, 20]]
  • 简单模式-不考虑顺序
# 简单模式计算shapley value--不考虑顺序
sab = SimplifiedShapleyAttributionModel()
result = sab.attribute(journeys)

image-20221222225808823

# 输出渠道shapley value
print(f"Total value: {len(journeys)}")
total = 0
for k, v in result.items():
    print(f"Channel {k}: {v:.2f}")
    total += v

print(f"Total of attributed values: {total:.2f}")
Total value: 2392
Channel 1: 73.73
Channel 2: 92.38
Channel 3: 118.34
Channel 4: 248.21
Channel 5: 75.04
Channel 6: 55.02
Channel 7: 33.14
Channel 8: 52.95
Channel 9: 189.29
Channel 10: 209.82
Channel 11: 106.80
Channel 12: 77.08
Channel 13: 201.28
Channel 14: 55.02
Channel 15: 64.87
Channel 16: 154.71
Channel 17: 76.80
Channel 18: 5.06
Channel 19: 12.55
Channel 20: 489.91
Total of attributed values: 2392.00
  • 有序模式-考虑顺序
# 有序模式计算shapley value--考虑顺序
# 计算时间过长,非必要可不执行
oab = OrderedShapleyAttributionModel()
result = oab.attribute(journeys)

image-20221222225954374

# 输出渠道shapley value
print(f"Total value: {len(journeys)}")
total = 0
for k, v in result.items():
    vsum = sum(v)
    print(f"Channel {k}: {vsum}")
    total += vsum

print(f"Total of attributed values: {total:.2f}")
Total value: 2392
Channel 1: 73.7267357642357
Channel 2: 92.37534687534699
Channel 3: 118.34282245532259
Channel 4: 248.20742174492216
Channel 5: 75.04331640581641
Channel 6: 55.01952491952489
Channel 7: 33.14323315573315
Channel 8: 52.95273476523473
Channel 9: 189.29054972804988
Channel 10: 209.8151168276172
Channel 11: 106.80050643800645
Channel 12: 77.07776806526806
Channel 13: 201.28108696858718
Channel 14: 55.01896853146851
Channel 15: 64.87037268287267
Channel 16: 154.71344627594635
Channel 17: 76.80483127983123
Channel 18: 5.057539682539683
Channel 19: 12.55146103896104
Channel 20: 489.9072163947167
Total of attributed values: 2392.00

可能是数据原因,两者的结果差异不大。

总结

日常业务中,可以结合多个方法看一下归因的差异。

共勉~

参考

python实现Shapley Value

Multi-Touch-Attribution_ShapleyValue官方示例

Shapley Value Methods for Attribution Modeling官方示例

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/738663.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2.带你入门matlab数理统计常见分布的概率密度函数(matlab程序)

1.简述 计算概率分布律及密度函数值 matlab直接提供了通用的计算概率密度函数值的函数,它们是pdf 和namepdf函数,使用方式如下: Ypdf(‘name’,K,A,B)或者:namepdf (K,A,…

低代码平台之流程自动化测试

随着低代码平台的快速发展,开发人员可以便捷、快速地开发流程应用程序,由于业务流程的复杂化和业务需求的不断变化,对业务流程进行优化和改进将更加频繁,在这个过程中,就要求企业的流程测试的效率和质量需要跟上低代码…

Stable Diffusion - AWPortrait 1.1 模型与 Prompts 设置

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/131565908 AWPortrait 1.1 网址:https://www.liblibai.com/modelinfo/721fa2d298b262d7c08f0337ebfe58f8 介绍:AWPortrai…

java类的静态变量

java类的静态变量称为类变量,非静态变量称为实例变量。 静态变量可以在声明时初始化,也可以不在声明时初始化。 通过下面方式可以访问类的静态变量: 类内部直接访问静态变量;通过类名访问静态变量;通过实例访问静态变…

C++数据结构X篇_08_C++实现栈的顺序存储与链式存储

本篇参考C实现栈的顺序存储与链式存储整理,先搞懂结构框架,后期根据视频利用c对内容实现,也可以对c有更高的提升。 文章目录 1. 栈的顺序存储2. 栈的链式存储 栈是一种特殊的数据结构,栈中数据先进后出,且栈中数据只能…

30张图带你弄懂 二叉树、AVL、红黑树,他们之间有什么联系,AVL树和红黑树如何平衡

树(Tree)是若干个结点组成的有限集合,其中必须有一个结点是根结点,其余结点划分为若干个互不相交的集合,每一个集合还是一棵树,但被称为根的子树。注意,当树的结点个数为0时,我们称这…

[已解决]Running setup.py install for MinkowskiEngine ... error

虚拟环境中安装MinkowskiEngine: pip install -U MinkowskiEngine --install-option"--blasopenblas" -v --no-deps 报错:“Running setup.py install for MinkowskiEngine ... error” 解决办法[链接][参考1]: (1&…

Unity 编辑器-创建模板脚本,并自动绑定属性,添加点击事件

当使用框架开发时,Prefab挂载的很多脚本都有固定的格式。从Unity的基础模板创建cs文件,再修改到应有的模板,会浪费一些时间。尤其是有大量的不同界面时,每个都改一遍,浪费时间不说,还有可能遗漏或错改。写个…

查询直播频道发起的签到记录

接口描述 1、通过直播场次id,查询签到发起记录 2、接口支持https协议 接口URL http://api.polyv.net/live/v3/channel/chat/checkin-by-sessionId 请求方式 GET 请求参数描述 参数名必选类型说明appIdtrueString账号appIdtimestamptrueLong当前13位毫秒级时间戳&…

OSPF实验2

OSPF实验2 要求: 1.如图连接,合理规划IP地址,所有路由器各自创建一个loopback接口 2.R1再创建三个接口IP地址为201.1.1.1/24、201.1.2.1/24、201.1.3.1/24 R5再创建三个接口IP地址为202.1.1.1/24、202.1.2.1/24、202.1.3.1/24 R7再创建三…

小红书如何开店,送你一份保姆级开店教程

科思创业汇 大家好,这里是科思创业汇,一个轻资产创业孵化平台。赚钱的方式有很多种,我希望在科思创业汇能够给你带来最快乐的那一种! 今天,我们来谈谈小红书的电子商务。这也是今年非常流行的电子商务平台。很多人说…

《设计模式》责任链模式

《设计模式》责任链模式 定义: 责任链模式将链中每一个节点都看成一个对象,并且将这些节点对象连成一条链,请求会沿着这条链进行传递,直到有对象处理它为止,这使得多个对象都有机会接收请求,避免了请求发送…

warp框架教程3-path, method和自定义请求方法

path, method和自定义请求方法 path 是 warp 中的路由系统, 一个 web 框架的灵魂所在, 一个优美的路由系统可以给我们带来非常良好的使用体验, 而 warp 的路由体验本身就是非常 nice 的。在本文中将展示一个 RESTful 风格的 API 设计。下面先来学习一下 path 模块。 path 模块…

从小白到大神之路之学习运维第56天--------shell脚本实例应用2.0之有趣的知识

第三阶段基础 时 间:2023年7月10日 参加人:全班人员 内 容: shell实例 目录 shell脚本应用: 一、if判断 1、if判断的类型 1)单分支 2)双分支 3)多分支 2、单分支if判断 1&#x…

Could not increase number of max_open_files to more than 5000 (request: 65535)

修改MySQL 打开文件数量限制 修改内核限制 ulimit -n //查看系统限制 修改 /etc/security/limits.conf 添加 soft nofile 65530hard nofile 65535 mysql> SHOW VARIABLES LIKE open_files_limit; 通过 MySQL 命令行检查新限制。您可以使用以下查询,确保设置了新…

vue3使用less入门使用案例(webStrom)

文章目录 简介安装less基础代码效果 less进阶代码效果 简介 less&#xff1a;css预处理语言 安装 npm i less3.0.4 -Dless打包解释器 npm i less-loader5.0.0 -Dless基础代码 <template><div class"a"></div> </template><style lang…

Java Web Servlet (1)23.7.7

Servlet 1&#xff0c; Servlet 1.1 简介 Servlet是JavaWeb最为核心的内容&#xff0c;它是Java提供的一门动态web资源开发技术。 使用Servlet就可以实现&#xff0c;根据不同的登录用户在页面上动态显示不同内容。 Servlet是JavaEE规范之一&#xff0c;其实就是一个接口&a…

【日常记录】CentOS7.5 安装tomcat放行8080端口后无法访问

环境 操作系统版本信息&#xff1a; [rootlocalhost conf]# cat /etc/redhat-release CentOS Linux release 7.5.1804 (Core)JAVA版本信息 [rootlocalhost conf]# java -version openjdk version "1.8.0_372" OpenJDK Runtime Environment (build 1.8.0_372-b07) …

闲人闲谈PS之四十四——供应链透明化

惯例闲话&#xff1a; 近期工作和天气一样&#xff0c;如火如荼&#xff0c;前面1个月&#xff0c;拼全力搞了一个新功能&#xff0c;把闲人折腾的够呛&#xff0c;现在回头看看这个过程&#xff0c;倒也回味无穷&#xff0c;如何利用信息化工具&#xff0c;搞点数字化的活&am…

ORA-39168: Object path STATISTICS was not found

上周某客户因异常断电导致lun&#xff0c;某个测试环境无法启动&#xff0c;客户只提供了一个1周前.dmp文件&#xff0c;需要在新环境中导入恢复&#xff0c;解决表空间和临时表空间问题后&#xff0c;导入报错如下 Import: Release 11.2.0.4.0 - Production on Thu Jul 6 07:…