【Python实战因果推断】29_倾向分9

目录

Outcome Is Easy to Model

Generalized Propensity Score for Continuous Treatment


Outcome Is Easy to Model

在下一个简单而又能说明问题的例子中,复杂性在于 P(T|X) 而不是 E[Y_t|X]。注意 P(T|X) 中的非线性,而结果函数是简单的线性。在这里,真正的 ATE 是-1:

 np.random.seed(123)n = 10000x = np.random.beta(1,1, n).round(2)*2e = 1/(1+np.exp(-(2*x - x**3)))t = np.random.binomial(1, e)y1 = xy0 = y1 + 1 # ate of -1y = t*(y1) + (1-t)*y0 + np.random.normal(0, 1, n)df_easy_y = pd.DataFrame(dict(y=y, x=x, t=t))print("True ATE:", np.mean(y1-y0))True ATE: -1.0

 可以用之前的同类曲线图来表示 P(T|X) 的复杂函数形式和 E[Y_t|X] 的简单函数形式:

 有了这些数据,由于倾向评分相对复杂,IPW无法恢复真正的ATE:

 est_fn = partial(est_ate_with_ps, ps_formula="x", T="t", Y="y")print("Propensity Score ATE:", est_fn(df_easy_y))print("95% CI", bootstrap(df_easy_y, est_fn))Propensity Score ATE: -1.104290027868089695% CI [-1.14326893 -1.06576358]

但回归却设法准确地纠正了它:

 m0 = smf.ols("y~x", data=df_easy_y.query("t==0")).fit()m1 = smf.ols("y~x", data=df_easy_y.query("t==1")).fit()regr_ate = (m1.predict(df_easy_y) - m0.predict(df_easy_y)).mean()print("Regression ATE:", regr_ate)Regression ATE: -1.0008783612504342

 同样,因为DR只需要正确指定一个模型,它还在这里恢复真正的ATE:

 est_fn = partial(doubly_robust, formula="x", T="t", Y="y")print("DR ATE:", est_fn(df_easy_y))print("95% CI", bootstrap(df_easy_y, est_fn))DR ATE: -1.002845934780582395% CI [-1.04156952 -0.96353366]

我希望这两个例子能更清楚地说明为什么双重稳健估计会非常有趣。最重要的一点是,它让你有两次机会获得正确。在某些情况下,建立 P(T|X) 模型很难,但建立 E[Y_t|X] 模型却很容易。而在其他情况下,情况可能正好相反。不管怎样,只要你能正确地建立其中一个模型,你就可以把 P(T|X) 模型和 E[Y_t|X] 模型结合起来,只需其中一个正确即可。这就是双重稳健估计器的真正威力。

Generalized Propensity Score for Continuous Treatment

到目前为止,只展示了如何将倾向分数用于离散干预。这是有道理的。连续干预处理起来要复杂得多。以至于我可以说,作为一门科学,因果推断对如何处理连续处理并没有很好的答案。

通过假设干预反应的函数形式,你设法摆脱了连续干预。比如 y = a + bt(线性形式)或 y = a + b t(平方根形式),然后用 OLS 对其进行估计。但就倾向加权而言,并不存在参数反应函数。通过重新加权和取平均值,可以对潜在结果进行非参数估计。如果 T 是连续的,则存在无限多的潜在结果 Yt。此外,由于连续变量的概率总是零,因此在这种情况下估计 P(T=t|X) 是不可行的。

要解决这些问题,最简单的办法就是把连续的干预离散化成一个更粗的版本,然后再把它当作离散的干预来处理。但还有另一条出路,那就是使用广义倾向得分。如果对传统的倾向得分做一些改动,就能适应任何类型的干预。请看下面的例子。

一家银行想知道贷款利率如何影响客户选择偿还贷款的期限(以月为单位)。直观地说,利息对贷款期限的影响应该是负的,因为人们喜欢尽快偿还高利率贷款,以避免支付过多的利息。

为了回答这个问题,银行可以随机调整利率,但这样做需要花费大量的金钱和时间。相反,银行希望利用已有的数据。银行知道利率是由两个机器学习模型 ml_1 和 ml_2 分配的。此外,由于银行的数据科学家非常聪明,他们在利率决策过程中加入了随机高斯噪声。这确保了政策的非确定性,也确保了不违反实在性假设。观察(非随机)利息数据以及混杂因素 ml_1 和 ml_2 和结果持续时间的信息存储在 df_cont_t 数据帧中:

 df_cont_t = pd.read_csv("./data/interest_rate.csv")df_cont_t.head()

您的任务是在调整 ml_1 和 ml_2 后,消除利率与期限之间的偏差。请注意,如果你不对任何因素进行调整,直接估计干预效果,你会发现干预效果为正。如前所述,这在商业上是不合理的,因此这一结果很可能是有偏差的:

 m_naive = smf.ols("duration ~ interest", data=df_cont_t).fit()m_naive.summary().tables[1]

要调整 ml_1 和 ml_2,可以直接将它们纳入模型中,但让我们来看看如何通过重新加权来处理同样的问题。需要解决的第一个难题是连续变量在任何地方的概率都为零,即 P(T=t)=0。这是因为概率由密度下的面积表示,而单点的面积总是零。一种可能的解决方法是用条件密度函数 f(T|X) 代替条件概率 P(T=t|X)。不过,这种方法会带来另一个问题,即指定干预的分布。

这里,为了简单起见,我们假设它是从正态分布 T\sim N(\mu_i,\sigma^2) 中提取的。这是一个相当合理的简化,尤其是因为正态分布可以用来近似其他分布。此外,我们假设方差 σ2 不变,而不是每个个体的方差都会变化。

回想一下,正态分布的密度由以下函数给出:

f(t_i)=\frac{exp\biggl(-\frac12\biggl(\frac{t_i-\mu_i}\sigma\biggr)^2\biggr)}{\sigma\sqrt{2\pi}}

现在,您需要估计这个条件高斯的参数,即均值和标准差。最简单的方法是使用 OLS 来拟合干预变量:

 model_t = smf.ols("interest~ml_1+ml_2", data=df_cont_t).fit()

然后,拟合值将作为 μi,残差的标准偏差将作为 σ。这样,就得到了条件密度的估计值。接下来,您需要评估给定干预时的条件密度,这就是为什么我在下面的代码中将 T 传递给密度函数中的 x 参数:

 def conditional_density(x, mean, std):denom = std*np.sqrt(2*np.pi)num = np.exp(-((1/2)*((x-mean)/std)**2))return (num/denom).ravel()gps = conditional_density(df_cont_t["interest"],model_t.fittedvalues,np.std(model_t.resid))gpsarray([0.1989118, 0.14524168, 0.03338421, ..., 0.07339096, 0.19365006,0.15732008])

或者,您可以(也可能应该)从scipy导入正态分布,并使用它来代替:

 from scipy.stats import normgps = norm(loc=model_t.fittedvalues,scale=np.std(model_t.resid)).pdf(df_cont_t["interest"])gpsarray([0.1989118, 0.14524168, 0.03338421, ..., 0.07339096, 0.19365006,0.15732008])

在回归模型中使用 GPS 的倒数作为权重可以调整偏差。您可以看到,现在您会发现利息对持续时间有负面影响,这在商业上更有意义:

 final_model = smf.wls("duration~interest",data=df_cont_t, weights=1/gps).fit()final_model.params["interest"]-0.6673977919925854

还有一项可以改进的地方,这将使人们对全球定位系统有更直观的了解。使用这个分数来构建权重,将赋予不太可能有干预的点更大的重要性。具体来说,在您拟合的处理模型中,您将为残差较高的单位赋予较高的权重。此外,由于正态密度的指数性质,权重将随残差的大小呈指数增长。

为了说明这一点,假设您只使用 ml_1 而不是 ml_1 和 ml_2 来拟合利率。这样的简化可以在一张图中显示所有内容。得出的权重显示在下图中。第一幅图显示的是原始数据,按混杂因素 ml_1 用颜色标示。ml_1 分数低的客户通常会选择较长的还款期限。此外,ml_1 分数低的客户会获得更高的利率。因此,利率与期限之间的关系存在向上偏差。

第二幅图显示了干预模型的拟合值以及 GPS 从该模型中得到的权重。离拟合线越远,权重越大。这是有道理的,因为 GPS 给不可能干预的处理赋予了更大的权重。但看看这些权重有多大。有些权重超过了 1000!

最后一幅图显示的是同样的权重,但却是利息和期限之间的关系。由于 ml_1 低值时的低利率和 ml_1 高值时的高利率都是不可能的,因此逆 GPS 权重对这些点给予了高度的重视。这就扭转了利息和期限之间的正向(偏向)关系。但这种估计方法的方差很大,因为它实际上只是使用了几个数据点--那些权重很高的数据点。此外,由于这个数据是模拟的,我知道真实的 ATE 是-0.8,但前面的估计值只有-0.66。

为了改进估计值,可以通过边际密度 f(t)来稳定权重。与离散干预不同,在离散干预中,权重稳定只是一个很好的条件,而在 GPS 中,我认为这是必须的。要估算 f(t),可以简单地使用平均干预值。然后,在给定的干预下评估由此得到的密度。

请注意,这样得出的权重总和(几乎)等于原始样本量。从重要性抽样的角度来考虑,这些权重将您从 f(t|x) 带到 f(t),即处理不依赖于 x 的密度:

 stabilizer = norm(loc=df_cont_t["interest"].mean(),scale=np.std(df_cont_t["interest"] - df_cont_t["interest"].mean())).pdf(df_cont_t["interest"])gipw = stabilizer/gpsprint("Original Sample Size:", len(df_cont_t))print("Effective Stable Weights Sample Size:", sum(gipw))Original Sample Size: 10000Effective Stable Weights Sample Size: 9988.19595174861

再次,假设只使用 ml_1 对 f(t|x)进行拟合,以了解发生了什么。再一次,反倾向加权给与远离干预模型拟合值的点很高的重要性,因为它们属于 f(t|x) 的低密度区域。 但此外,稳定也给与远离 f(t)  的点,即远离均值的点很低的重要性。结果是双重的。首先,稳定后的权重更小,从而降低了方差。其次,我们可以更清楚地看到,我们现在更重视 ml_1 值低和利率低的点(反之亦然)。从第一张图和第三张图之间颜色模式的变化可以看出这一点:

此外,这些稳定的权重给你的估计是更接近真实的ATE-0.8:

 final_model = smf.wls("duration ~ interest",data=df_cont_t, weights=gipw).fit()final_model.params["interest"]-0.7787046278134069

正如您所看到的,尽管体重稳定在 T 是离散的情况下没有影响,但对于连续干预来说却非常重要。它能让你更接近你试图估计的参数的真实值,还能显著减少方差。由于有些重复,我省略了计算估计值 95% CI 的代码,但这与您之前所做的差不多:只需将整个过程封装在一个函数中并进行引导。不过,为了让你自己看清楚,下面是有稳定化和没有稳定化的 95% CI:

95% CI, non-stable: [-0.81074164 -0.52605933]
95% CI, stable: [-0.85834311 -0.71001914]
请注意两者都包含-0.8的真实值,但具有稳定的值要窄得多。

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

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

相关文章

【操作系统】进程管理——调度算法(个人笔记)

学习日期:2024.7.4 内容摘要:各种调度算法的思想、规则、优缺点介绍 为什么要有调度算法? 调度算法就好比一群人在银行办理业务,准备办理业务的人就是进程/作业,银行窗口的工作人员就是CPU,进程往往是比C…

xcode配置swift使用自定义主题颜色或者使用RGB或者HEX颜色

要想在xcode中使用自定义颜色或者配置主题色,需要在Assets中配置,打开Assets文件,然后点击添加Color Set: 输入颜色的名称,然后选中这个颜色,会出现两个颜色: Any Appearance表示亮色模式下使用…

评估测试用例有效性 5个方面

评估测试用例的有效性是确保软件测试活动能够达到预期目标的关键步骤,有助于测试团队优化测试计划,提高测试效率,减少返工,节省成本。如果缺乏对测试用例的有效性评估,可能会导致测试用例无法覆盖关键功能点&#xff0…

SpringCloud代码实战

项目结构 实例实现功能:实现通过id查询用户的订单信息 OrderCommon:公共的一些模块类型,此处为一个user对象 Eureka-Service:配置Eureka的启动类,服务端 Order-Service:提供查询功能的服务端 Order-Client:查询的客户端 OrderCommon代码…

ps导入图片的方式

在Photoshop(简称PS)中导入图片是一项基础且常用的操作,无论是进行图像处理、设计创作还是编辑照片,这一步骤都至关重要。下面将详细介绍几种在Photoshop中导入图片的方法,帮助你快速上手。 方法一:通过菜…

智汇园区:为园区企业注入前沿技术与人才活力

在日新月异的时代浪潮中,树莓集团深知人才是企业发展的核心驱动力,更是推动产业升级与创新的关键要素。因此,我们致力于构建全方位的人才引进与培养体系,为园区企业输送源源不断的前沿技术与人才支持。 【人才引进:汇聚…

私活必备框架!终于找到一个前后端都有的后台管理系统了~

大家好,我是「程序视点」爱分享的小二哥~ 今天介绍一个新的Vue后台管理框架,相比其他后台功能丰富管理系统,这个后台管理系统可以用干净简洁来形容——Nova-admin Nova-admin Nova-admin 是一个基于Vue3、Vite5等最新技术的后台管理平台。用…

Selenium 中的 JUnit 注解

JUnit 是一个基于 Java 的开源框架,可帮助测试人员执行单元测试。JUnit 主要用于测试应用程序的每个单元或组件,例如类和方法。它有助于编写和运行可重复的自动化测试,以确保项目代码按预期运行。还可以使用 JUnit 执行 Selenium 自动化测试用…

【ESP32】打造全网最强esp-idf基础教程——16.SmartConfig一键配网

SmartConfig一键配网 一、SmartConfig知识扫盲 在讲STA课程的时候,我们用的是代码里面固定的SSID和密码去连接热点,但实际应用中不可能这么弄,我们得有办法把家里的WiFi SSID和密码输入到设备里面去,对于带屏带输入设备还…

C# —— Directory类

Directory 提供了目录以及子目录进行创建移动和列举的操作方法 Directory 和DirectoryInfo类 (主要操作文件目录属性列如文件是否隐藏的 或者只读等这些属性) 1目录的创建方法Directory 在桌面上查找该目录 Directory.CreateDirectory("C:\Users…

视频共享交换平台LntonCVS视频监控平台智慧加油站安全管理方案

加油站作为危化品行业的一部分,日常的加油和卸油作业安全至关重要。目前国内加油站的管理主要依赖于人为管控、监控摄像头和人工巡检,这些方法存在效率低下和反应滞后的问题。为了有效应对安全风险,急需引入人工智能、物联网和大数据技术&…

UE5 本地化多语言方案

导入插件: https://www.unrealengine.com/marketplace/zh-CN/product/07e1d9bd9ced444c9b2a7e232161f74d​www.unrealengine.com/marketplace/zh-CN/product/07e1d9bd9ced444c9b2a7e232161f74d 打开测试关卡 打开插件下图目录,csv文件可以添加多个&…

[PaddlePaddle飞桨] PaddleOCR图像小模型部署

PaddleOCR的GitHub项目地址 推荐环境: PaddlePaddle > 2.1.2 Python > 3.7 CUDA > 10.1 CUDNN > 7.6pip下载指令: python -m pip install paddlepaddle-gpu2.5.1 -i https://pypi.tuna.tsinghua.edu.cn/simple pip install paddleocr2.7…

网络编程:各协议头(数据报格式)

一、mac头 二、ip头 protocol——tcp/udp (7)TTL——生存时间 三、tcp头 四、udp头

dify/api/models/web.py文件中的数据表

源码位置:dify/api/models/web.py SavedMessage 表结构 字段英文名数据类型字段中文名字备注idStringUUIDIDUUID生成app_idStringUUID应用ID非空message_idStringUUID消息ID非空created_by_roleString创建者角色非空,默认值为’end_user’created_bySt…

uboot学习:(一)

目录 uboot是一个裸机程序(bootloader) 作用 要运行linux系统时,如何从外置的flash拷贝到DDR中,才能启动 uboot使用步骤 步骤1中的命令例子 注意 uboot源码获取方法 uboot是一个裸机程序(bootloader&#xff09…

校园外卖系统带万字文档在线外卖管理系统java项目java课程设计java毕业设计

文章目录 校园外卖系统一、项目演示二、项目介绍三、万字项目文档四、部分功能截图五、部分代码展示六、底部获取项目源码带万字文档(9.9¥带走) 校园外卖系统 一、项目演示 校园外卖服务系统 二、项目介绍 语言:java 数据库&…

【fastadmin 开发实战】select 级联选择

先看实现的效果 1、表单页面实现级联选择 2、级联选项后台可以编辑添加 前端代码&#xff08;编辑窗口&#xff09;&#xff1a; <div class"form-group"><label class"control-label col-xs-12 col-sm-2">{:__(渠道归属)}:</label><…

力扣之有序链表去重

删除链表中的重复元素&#xff0c;重复元素保留一个 p1 p2 1 -> 1 -> 2 -> 3 -> 3 -> null p1.val p2.val 那么删除 p2&#xff0c;注意 p1 此时保持不变 p1 p2 1 -> 2 -> 3 -> 3 -> null p1.val ! p2.val 那么 p1&#xff0c;p2 向后移动 p1 …

Postman API测试覆盖率:全面评估指南

&#x1f4ca; Postman API测试覆盖率&#xff1a;全面评估指南 在API测试中&#xff0c;测试覆盖率是一个关键指标&#xff0c;它衡量了测试用例对代码的覆盖程度。Postman提供了多种工具和方法来评估API测试覆盖率&#xff0c;帮助开发者和测试人员确保API的质量和稳定性。本…