【python因果库实战5】使用银行营销数据集研究营销决策的效果5

目录

接触次数的效应

重新定义治疗变量和潜在混杂因素

更深入地审视干预情景

逆概率加权

标准化

总结及与非因果分析的比较


接触次数的效应

我们现在转而研究当前营销活动中接触次数的数量('campaign')对积极结果发生率的影响。具体来说,我们将估计如果所有客户都被接触多次与只被接触一次相比的成功率。这是一个相关的问题,因为接触客户需要资源(比如员工的时间)。结合其他输入,效果估计可以为员工提供是否在第一次尝试后继续联系客户,还是将时间更有利可图地用于其他任务的指导。

重新定义治疗变量和潜在混杂因素

相应地,我们将治疗变量a重新定义为:如果'campaign'大于1则为1,如果'campaign'等于1则为0。我们还需要重新定义y以恢复之前考虑接触方式时排除的非重叠群体。

y = pd.Series(le.fit_transform(data['y']))
a = (data['campaign'] > 1).astype(int)
print(y.mean())
print(a.mean())
0.11265417111780131
0.5716713605904632

至于混杂因素,我们继续使用之前包括的客户特征、之前的营销活动特点以及经济指标。 

confounders = ['age', 'job', 'marital', 'education', 'default', 'housing', 'loan', 'pdays','previous', 'poutcome', 'emp.var.rate', 'cons.price.idx', 'cons.conf.idx', 'euribor3m', 'nr.employed']

以'campaign'作为治疗变量,我们设想在首次与客户接触后决定停止还是继续。在这种情况下,最后一次接触的特点('contact'、'day_of_week',当然还有'duration')可能还不知道,所以它们不应该被视为潜在的混杂因素。因此,我们只会添加'month'。

confounders += ['month']

 重新提取混杂因素:

X = data[confounders]
X = pd.get_dummies(X, prefix_sep='=', drop_first=True)

更深入地审视干预情景

让我们停下来更仔细地思考一下决策情景:我们首先联系所有客户一次,然后决定是否继续联系还是停止。第一个观察是,通过继续联系,积极结果的发生率只能增加,因此治疗效果的正负符号是没有疑问的。相反,目标是估计在决定继续联系的情况下,积极结果的发生率有多大,以供成本效益分析参考。

第二,因果效应估计的主要挑战(也就是所谓的“因果推断的基本问题”)是我们通常不能观察到反事实结果:对于被给予a=0干预的个体,我们无法观察他们在a=1下的结果,反之亦然。然而,在当前的情景中,我们实际上可以推断出一些反事实结果。让我们定义Y0为客户仅被联系一次时可能出现的结果。对于实际上只被联系一次的客户(分配a=0),他们的观察结果y与潜在结果Y0相同。对于被联系多次的客户(分配a=1),如果我们选择在第一次联系后停止,则他们的潜在结果应该是Y0 = 0,否则银行员工不会持续联系他们。因此,对于所有客户,Y0可以根据以下方式推断:

y0 = y * (a == 0)
y0.mean()
0.05584150723511702

这个5.6%的成功率实际上是仅联系一次这一干预措施下的成功率。我们稍后会回到这个数值上来。

此外,潜在结果Y0在银行员工第一次联系后作出决策时是已知的。实际上,它可以被视为一种特殊类型的混杂因素,因为它具有确定性影响:如果Y0=1(成功),那么a=0是确定性的,因为继续联系没有益处,并且y=1。由于Y0=1的客户只接受a=0的处理,它们构成了一个完全非重叠的治疗群体。因此,应该将它们从因果分析中排除,就像我们之前在分析'contact'时所做的那样。所以我们把它们移除:

y = y.loc[y0 == 0]
a = a.loc[y0 == 0]
X = X.loc[y0 == 0]
X.shape
(38888, 46)

剩下的Y0=0的客户可以接受a=0或a=1的处理,因此它们不存在完全非重叠的情况。它们可能仍然存在部分非重叠的问题,但这可以通过使用逆概率加权(IPW)模型和Causal Inference 360的评估方法来进行检查,我们将在下一小节中这样做。

还需要记住的一点是,处理a=1,即'campaign' > 1,实际上是一个复合处理:它不是一个像“恰好联系两次”那样明确定义的干预措施,而是“根据数据中的'campaign'分布进行多次联系”(换句话说,遵循银行员工集体的做法)。实际上,人们可以想象在一定数量的联系之后,成功率可能会开始下降,因为客户可能会变得恼火甚至离开银行(这是我们在数据中没有观察到的结果)。在这个笔记本中,我们不会涉及这些额外的考虑因素,而是专注于二元化处理的简化案例。

逆概率加权

如同第2节中所述,我们将使用逻辑回归模型来实例化IPW,以预测治疗分配的概率。

lr = LogisticRegression(solver='lbfgs', max_iter=1000)
#lr = LogisticRegression(penalty='l1', solver='saga', max_iter=1000)
#lr = GradientBoostingClassifier()
ipw = IPW(lr)
ipw.fit(X, a)
IPW(clip_max=None, clip_min=None, use_stabilized=False, verbose=False,learner=LogisticRegression(max_iter=1000))

让我们通过评估图表来检查IPW模型: 

eval_results = evaluate(ipw, X, a, y)
eval_results.plot_all()
eval_results.plot_covariate_balance(kind="love")

两个治疗组从一开始就相当平衡:

ROC曲线:倾向性AUC(蓝色曲线)仅为0.55,经过IPW后进一步降低到0.51。

倾向性分布:倾向性估计的分布是平衡的。

协变量平衡Love图:即使在IPW之前,标准化的平均差异也都低于0.1。

现在我们获得积极结果率和治疗效果的估计:

outcomes = ipw.estimate_population_outcome(X, a, y)
print(outcomes)
ipw.estimate_effect(outcomes[1], outcomes[0], effect_types=['diff'])
0    0.000000
1    0.100092
dtype: float64
diff    0.100092
dtype: float64

积极结果在a=0(停止)时为零,这符合该子人群的定义,即在一次接触后没有成功。在a=1下,估计的成功率为10%。接下来我们将使用标准化来分解这一比率。

标准化

回想一下,在标准化中,我们使用回归器从混杂因素X和治疗a来预测结果y。由于排除了在a=0下的积极结果Y0=1,因此现在在a=0的条件下y恒为零。因此,我们只需要为a=1拟合一个模型。为此,我们使用梯度提升分类树的StratifiedStandardization来为a=1建模,而对于a=0则使用线性回归。后者是一个“虚拟”的模型,只会返回一个全零的模型。

from sklearn.linear_model import LinearRegression
std = StratifiedStandardization({0: LinearRegression(), 1: GradientBoostingClassifier()}, predict_proba=True)
std.fit(X, a, y)

我们继续估计两种干预措施下的积极结果发生率。(最后两列的结果是预测的y=0和y=1的概率,是在a=1干预下的概率,因此加起来等于1。) 

outcomes = std.estimate_population_outcome(X, a)
print(outcomes)
std.estimate_effect(outcomes[(1,1)], outcomes[0], effect_types=['diff'])
campaign   
0         y    0.000000
1         0    0.9021711    0.097829
dtype: float64
diff    0.097829
dtype: float64

a=0干预(停止)下的估计结果为零,正如预期。a=1下的估计结果9.8%略低于IPW的结果。

使用标准化,我们还可以看到在继续联系所有客户的干预措施下,分配到的治疗组a=0和a=1的估计成功率是否有差异。这可以通过使用estimate_individual_outcome方法(与上面的estimate_population_outcome方法相反),提取a=1干预下的(1,1)列的成功概率,然后对两个治疗组的概率求平均来完成。

yPot = std.estimate_individual_outcome(X, a)#.xs(1, axis=1, level='y')
#print(yPot.head())
y1 = yPot[(1,1)]
print('Estimated success rates under continuing contact')
print('for the "untreated" group a=0: {}'.format(y1.loc[a == 0].mean()))
print('for the "treated" group a=1: {}'.format(y1.loc[a == 1].mean()))
Estimated success rates under continuing contact
for the "untreated" group a=0: 0.09543383555412627
for the "treated" group a=1: 0.09938921214795549

a=0组(未治疗组)的y1平均值略低于a=1组(治疗组),这解释了为什么总体的成功率9.8%略低。这意味着如果我们决定继续联系所有客户,我们可能在那些银行员工在数据中停止联系的客户(a=0)上的成功率略低于那些继续联系的客户(a=1)。这可能是由于银行员工在决定继续联系哪些客户时,有一定的能力预测哪些客户更有可能进行投资,尽管考虑到差异很小,我们不能肯定地说这一点。

我们也可以验证a=1组的估计成功率与观察到的成功率非常接近(因为这一组实际上接受了继续联系)。后者是在a=1条件下的发生率。再次说明,这可能是没有采用因果方法时所计算的结果。

print(y[a==1].mean())
0.09937993714431326

总结及与非因果分析的比较

回想一下,在因果分析中我们排除了第一次接触后就有积极结果的客户(Y0=1)。对于这些客户,我们可以假设(或者说定义)他们的反事实结果为Y1=1,如果我们继续联系他们的话。然后我们可以构建在a=1干预下的完整潜在结果集y1All:

y1All = y0.copy()
y1All[y1All == 0] = y1
print('Estimated success rate under one contact for all clients: {}'.format(y0.mean()))
print('Estimated success rate under more than one contact for all clients: {}'.format(y1All.mean()))
Estimated success rate under one contact for all clients: 0.05584150723511702
Estimated success rate under more than one contact for all clients: 0.1482073490897146

总结来说,从数据中我们观察到一次接触后的成功率为5.6%,而从因果分析中,我们预测如果所有客户都接受继续联系,成功率为14.8%。观察到的成功率11.3%介于两者之间,因为银行员工选择了一些客户继续联系,而停止了对其他客户的联系。

我们同样以与非因果分析的比较来结束,简单地查看基于治疗分配a=0、a=1的成功率。我们首先重新定义y和a,以带回被排除的Y0=1的人群。

y = pd.Series(le.fit_transform(data['y']))
a = (data['campaign'] > 1).astype(int)
y[a==0].mean(), y[a==1].mean()
(0.13037070626913047, 0.09937993714431326)

我们现在看到这些条件成功率是非常误导人的。它们似乎表明,如果客户被联系多次,成功率会更低,我们知道这并不是真的(即使是常识)。我们来分别看一下这两种情况:

  • 对于a=0,13.0%的成功率仅来自于那些银行员工只联系了一次的客户。但如果他们对剩余的客户也只联系一次就停止,他们不会有额外的成功。因此,正好一次接触干预下的成功率要低得多,如上所述为5.6%。
  • 对于a=1,9.9%的成功率接近于我们使用标准化估计的9.8%,针对那些第一次接触后不是成功的客户(Y0=0)。但是,我们必须记得加上那些第一次接触后就已经同意定期存款的客户(Y0=1),这样我们得到了在超过一次接触的干预下14.8%的成功率。

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

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

相关文章

单步调试Android Framework——App冷启动

纸上得来终觉浅,绝知此事要躬行。 —— [宋]陆游 基于aosp_cf_x86_64_phone-trunk_staging-eng , 下面是具体断点位置。 第一部分,桌面launcher进程 com.android.launcher3.touch.ItemClickHandler onClickonClickAppShortcutstartAppShor…

【5G】5G的主要架构选项

最初,在3GPP讨论中考虑了所有可能的聚合和核心网络组合,共有八个架构选项。以下重点介绍option2、3、4和7。 1. 独立组网 (Standalone, SA) 架构选项 2 :Standalone architecture with 5G-core 特点: 5G核心网(5GC, …

MySQL数据库备份,恢复

备份策略不同,恢复方式也不同。 在进行数据备份的时候,能使用冷备份就使用冷备份,安全可靠, 但是冷备份自己的缺点是【每一个数据库都对应着一个前端的业务】此时前端业务停止可能带来经济损失。 一.备份类型 根据服务是否在线…

OpenCV 学习记录:首篇

最近在学习机器视觉,希望能通过记录博客的形式来鞭策自己坚持学完,同时也把重要的知识点记录下来供参考学习。 1. OpenCV 介绍与模块组成 什么是 OpenCV? OpenCV (Open Source Computer Vision Library) 是一个开源的计算机视觉和机器学习软…

基于vue框架的的校园二手市场交易平台8k655(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。

系统程序文件列表 项目功能:学生,大学,商品分类,商品信息,在线咨询 开题报告内容 基于Vue框架的校园二手市场交易平台开题报告 一、课题意义 (一)理论意义 本课题旨在研究基于Vue框架的校园二手市场交易平台的设计与实现。当前&#xff…

3D计算机视觉概述

3D计算机视觉 3D计算机视觉概述 像机标定 文章目录 3D计算机视觉前言一、人类视觉二、计算机视觉2.1 计算机视觉的研究目的2.2 计算机视觉的研究任务2.3 计算机视觉的研究方法2.4 视觉计算理论2.5 马尔框架中计算机视觉表达的四个层次2.5.1 图像(像素表达&#xff…

操作系统(13)虚拟存储器

前言 操作系统中的虚拟存储器是一项关键技术,它为用户提供了一个远大于实际物理内存容量的逻辑内存空间。 一、定义与原理 虚拟存储器是具有请求调入功能和置换功能,能从逻辑上对内存容量加以扩充的存储器系统。其逻辑容量由内存容量与外存容量之和决定&…

【实用技能】如何运用Visual Paradigm快速创建团队的项目模板

从 Visual Paradigm 17.2 ()版开始,您可以创建自己的项目模板并与团队共享。这样团队成员就可以轻松创建符合团队标准的新项目。本文将指导您完成为团队创建项目模板的过程。 Visual Paradigm v17.2试用版下载 先决条件 您的团队必须使用 …

不良人系列-复兴数据结构(栈和队列)

个人主页:爱编程的小新☆ 不良人经典语录:“相呴相济 玉汝于成 勿念 心安” 目录 一. 栈(stack) 1. 栈的概念 2. 栈的常见方法 3.栈的模拟实现 ​编辑 二. 队列 1. 队列的概念 2. 队列的使用 2.1 队列的常见方法 2.2 队列的模拟实现 2.3 队列…

【Linux网络】网络基础:IP协议

📝个人主页🌹:Eternity._ ⏩收录专栏⏪:Linux “ 登神长阶 ” 🌹🌹期待您的关注 🌹🌹 ❀ IP协议 IP协议基本概念协议头格式分片与组装网段划分子网掩码特殊的IP地址 IP地址的数量限制…

Linux正则化与三剑客速成(一)

目录 1.正则化 1.1正则表达式(RE) 1.2 正则表达式的注意事项 1.3正则表达式的分类 1.4 基本正则表达式 ^:表示匹配文本中以某个字符串开头的行。 $:表示匹配以某个字符串结尾的文件内的行 ^$:表示空行,但是在Linux中的实际的操作中一…

HarmonyOS 非线性容器LightWeightMap 常用的几个方法

LightWeightMap可用于存储具有关联关系的key-value键值对集合,存储元素中key值唯一,每个key对应一个value。 LightWeightMap依据泛型定义,采用轻量级结构,初始默认容量大小为8,每次扩容大小为原始容量的两倍。 集合中k…

Docker的容器

目录 1. 什么是容器?2. 容器的生命周期2.1 容器处理OOM事件2.2 容器异常退出2.3 容器暂停 3. 容器命令详解3.1 容器命令清单3.2 docker create命令3.3 docker run命令3.4 docker ps命令3.5 docker logs命令3.6 docker attach命令3.7 docker exec命令3.8 docker stat…

LearnOpenGL学习(高级OpenGL -> 高级GLSL,几何着色器)

完整代码见:zaizai77/Cherno-OpenGL: OpenGL 小白学习之路 高级GLSL 内建变量 顶点着色器 gl_PointSoze : float 输出变量,用于控制渲染 GL_POINTS 型图元时,点的大小。可用于粒子系统。将其设置为 gl_Position.z 时,可以使点…

Excel/VBA 正则表达式归纳汇总

1.with结构。以下语句用来提取A列中的“成品”两个字前面的部分的中文,不含成品两个字,结果存放在第2列。使用了On Error Resume Next,表示错误时继续下一条。 Sub 提取口味() Set regx CreateObject("vbscript.regexp") On Err…

CodeMirror 如何动态更新definemode

CodeMirror 如何动态更新definemode 问题描述:解决方法: 问题描述: 项目中有一部分用到了CodeMirror组件,其高亮显示的内容需要根据最新的json动态的更新,需要使用definemode自定义高亮内容。 想要的效果如下&#xf…

用户发送请求后服务端i/o工作过程

华子目录 服务端i/o介绍磁盘i/o机械磁盘的寻道时间、旋转延迟和数据传输时间常见的机械磁盘平均寻道时间值常见磁盘的平均延迟时间每秒最大IOPS的计算方法 网络i/o网络I/O处理过程磁盘和网络i/o 一次完整的请求在内部的执行过程 服务端i/o介绍 i/o在计算机中指Input/Output&am…

智能人体安全防护:3D 视觉技术原理、系统架构与代码实现剖析

随着工业化程度的提高,生产安全已成为企业关注的重点。尤其是在一些存在禁区的工业厂区和车间,人员误入或违规进入将带来严重的安全隐患。为了解决这一问题,迈尔微视推出了智能人体安全检测解决方案,为企业提供全方位的人员安全监…

暂停window11自动更新

window11 的自动更新功能,一方面在后台占用资源,容易导致电脑卡顿;另一方面,“更新并关机” 和 “更新并重启” 的设置令人极其反感。很多补丁兼容性很差,更新后极易引发电脑蓝屏、闪屏等意想不到的 bug。 1.winR打开运…

CTF-WEB: php-Session 文件利用 [第一届国城杯 n0ob_un4er 赛后学习笔记]

step 1 搭建容器 教程 A5rZ 题目 github.com Dockerfile 有点问题,手动修复一下 FROM php:7.2-apacheCOPY ./flag /root COPY ./readflag / COPY ./html/ /var/www/html/ COPY ./php.ini /usr/local/etc/php/php.ini COPY ./readflag /readsecretRUN chmod 755 /var/www…