【因果推断python】42_异质干预效应2

news2024/12/26 22:38:14

目录

预测弹性

关键思想


预测弹性

我们在这里陷入了复杂的境地。我们已经同意我们需要预测 \frac{\delta Y_i}{\delta T_i},遗憾的是这是不可观察的。因此,我们不能使用 ML 算法并将其作为目标插入。但也许我们不需要观察 \frac{\delta Y_i}{\delta T_i} 来预测它

这是一个想法。如果我们使用线性回归呢?

img

假设您将以下线性模型拟合到您的数据中。

y_i=\beta_0+\beta_1t_i+\beta_2X_i+e_i

如果你在干预变量上区分它,你最终会得到

\frac{\delta y_i}{\delta t_i}=\beta_1

既然你可以估计上面的模型得到 \hat{\beta}_{1},我们甚至可以大胆地说即使你无法观察到弹性,你也可以预测它。在上面的例子中,这是一个相当简单的预测,即我们为每个人预测常数值 \hat{\beta}_{1}。那是一些东西,但还不是我们想要的。那是ATE,不是CATE。这无助于我们根据实体对干预的反应程度对实体进行分组的任务,因为每个人都得到相同的弹性预测。但是,我们可以做以下简单的改变

y_i=\beta_0+\beta_1t_i+\beta_2X_i+\beta_3t_iX_i+e_i

这反过来会给我们以下弹性预测

\widehat{\frac{\delta y_i}{\delta t_i}}=\hat{\beta_1}+\hat{\beta_3}X_i

其中 \beta_{3} 是 X 中特征的向量系数。

现在由不同的 X_{i} 定义的每个实体将有不同的弹性预测。换句话说,弹性预测会随着 X 的变化而变化。唉,回归可以为我们提供一种估计 CATE E[y^{'}(t)|X] 的方法。

我们终于到了某个地方。上面的模型允许我们对每个实体进行弹性预测。通过这些预测,我们可以创建更多有用的组。我们可以将具有高预测弹性的单元组合在一起。我们可以对预测弹性低的那些做同样的事情。最后,通过我们的弹性预测,我们可以根据我们认为实体对干预的反应程度对它们进行分组。

理论到此为止。是时候通过一个示例来说明如何制作这种弹性模型了。让我们考虑一下我们的冰淇淋示例。每个单位 i 是一天。对于每一天,我们都知道是否是工作日,制作冰淇淋的成本是多少(您可以将成本视为质量的代表)以及当天的平均温度。这些将是我们的特征空间 X。然后,我们有我们的干预手段、价格和我们的结果,即售出的冰淇淋数量。对于这个例子,我们将考虑随机处理,这样我们现在不必担心偏差。

import pandas as pd
import numpy as np
from matplotlib import pyplot as plt

import seaborn as sns
import statsmodels.formula.api as smf
import statsmodels.api as sm

from sklearn.ensemble import GradientBoostingRegressor
from sklearn.model_selection import train_test_split
prices_rnd = pd.read_csv("./data/ice_cream_sales_rnd.csv")
print(prices_rnd.shape)
prices_rnd.head()
(5000, 5)

请记住我们的目标:我们需要根据具体的“功能”、“临时”、“工作日”和“成本”来决定何时收取更多费用以及何时收取更少费用。 如果这是目标,则需要评估干预效果异质性模型在实现该目标方面的有用性。 我们稍后会谈到这一点(下一章会详细介绍)。 现在,让我们将数据集拆分为训练和测试集。

np.random.seed(123)
train, test = train_test_split(prices_rnd)

现在我们有了训练数据,我们需要建立一个模型,让我们能够区分价格弹性高的日子和价格弹性低的日子。 我们这样做的方法是简单地预测价格弹性。 具体如何? 首先,让我们考虑使用以下线性模型

sales_i=\beta_0+\beta_1price_i+\boldsymbol{\beta_2}X_i+e_i

如果我们检查这个模型的参数,我们可以看到我们预测的弹性会是什么样子。

m1 = smf.ols("sales ~ price + temp+C(weekday)+cost", data=train).fit()
m1.summary().tables[1]

对于 m1,预测的价格弹性 \widehat{\frac{\delta y_i}{\delta t_i}}  将由 \hat{\beta_1},在我们的例子中是 -2.75。这意味着,我们为冰淇淋收取的每额外巴西雷亚尔,我们预计销售额将下降约 3 个单位。

注意这个 m1 如何为每个人预测完全相同的弹性。因此,如果我们想知道人们在哪些日子对冰淇淋价格不那么敏感,这不是一个很好的模型。当我们在这里需要的是 CATE 时,它会估计 ATE。请记住,我们的目标是以这样一种方式对实体进行分区,以便我们可以针对每个单独的分区个性化和优化我们的处理(价格)。如果每个预测都相同,我们就无法进行分区。我们没有区分敏感单位和非敏感单位。为了纠正这一点,考虑我们的第二个模型:

sales_i=\beta_0+\beta_1price_i+\beta_2price_i*temp_i*+\boldsymbol{\beta_3}X_i+e_i

第二个模型包括价格和温度之间的交互项。这意味着它允许弹性在不同温度下有所不同。我们在这里实际上要说的是,人们对价格上涨或多或少敏感,具体取决于温度。

m2 = smf.ols("sales ~ price*temp + C(weekday) + cost", data=train).fit()
m2.summary().tables[1]

一旦我们估计模型,预测的弹性由下式给出

\frac{\delta\widehat{sales}_{i}}{\delta price_{i}}=\hat{\beta_{1}}+\hat{\beta_{3}}temp_{i}

请注意,\hat{\beta}_3 为正 0,03,基线弹性 \beta_{1}(在 0C^{o} 处的弹性)为 -3.6。这意味着,平均而言,随着我们提高价格,销售额下降,这是有道理的。这也意味着温度每升高一度,人们对冰淇淋价格上涨的敏感度就会降低(尽管幅度不大)。例如,在 25C^{o},我们每多收取一次巴西雷亚尔,我们的销售额就会下降 2.8 个单位 (−3.6+(0.03∗25))(−3.6+(0.03∗25))。但是在 35C^{o},我们每多收取一次巴西雷亚尔,它们只会下降 2.5 个单位 (−3.6+(0.03∗35))(−3.6+(0.03∗35))。这也是一种直觉。随着天气越来越热,人们愿意为冰淇淋支付更多费用。

我们可以走得更远。下一个模型包括所有特征空间的交互项。这意味着弹性会随着温度、星期几和成本而变化。sales_{i}=\beta_{0}+\beta_{1}price_{i}+\boldsymbol{\beta_{2}X_{i}}*price_{i}+\boldsymbol{\beta_{3}}X_{i}+e_{i}

m3 = smf.ols("sales ~ price*cost + price*C(weekday) + price*temp", data=train).fit()

根据上述模型,单位水平弹性或 CATE 将由下式给出

其中 \beta_{1} 是价格系数,\beta_{2} 是交互系数的向量。

最后,让我们看看如何实际做出这些弹性预测。一种方法是从模型中提取弹性参数并使用上面的公式。但是,我们将采用更一般的近似值。由于弹性只不过是干预结果的导数,我们可以使用导数的定义。

\frac{\delta y}{\delta t}=\frac{y(t+\epsilon)-y(t)}{(t+\epsilon)-t}

随着 ϵ 变为零。我们可以通过将 ϵ 替换为 1 来近似这个定义。

\frac{\delta y}{\delta t} 近似 \hat{y}(t+1)-\hat{y}(t)

其中 \hat{y} 由我们模型的预测给出。换句话说,我将用我的模型做出两个预测:一个传递原始数据,另一个传递原始数据,但处理增加一个单位。这些预测之间的差异是我的 CATE 预测。

下面,您可以看到执行此操作的函数。由于我们使用了训练集来估计我们的模型,我们现在将对测试集进行预测。首先,让我们使用我们的第一个 ATE 模型 m1。

def pred_elasticity(m, df, t="price"):
    return df.assign(**{
        "pred_elast": m.predict(df.assign(**{t:df[t]+1})) - m.predict(df)
    })

pred_elasticity(m1, test).head()

使用 m1 进行弹性预测并不好玩。 我们可以看到它预测了所有日子的完全相同的值。 那是因为该模型上没有交互项。 但是,如果我们使用 m3 进行预测,它会为每天输出不同的弹性预测。 那是因为现在,弹性或干预效果取决于当天的具体特征。

pred_elast3 = pred_elasticity(m3, test)

np.random.seed(1)
pred_elast3.sample(5)

请注意预测是如何从 -9 变为 1 的数字。这些不是销售列的预测,其数量级为数百。相反,这是一个预测,如果我们将价格提高一个单位,销售额会发生多少变化。在赌注之外,我们可以看到一些奇怪的数字。例如,看一下第 4764 天。它预测的是正弹性。换句话说,我们预测如果我们提高冰淇淋的价格,销售额将会增加。这不符合我们的经济意识。可能是模型对该预测进行了一些奇怪的外推。幸运的是,您不必为此担心太多。请记住,我们的最终目标是根据单位对干预的敏感程度来划分单位。 不是提出有史以来最准确的弹性预测。对于我们的主要目标,如果弹性预测根据单元的敏感程度对单元进行排序就足够了。换句话说,即使像 1.1 或 0.5 这样的正弹性预测没有多大意义,我们所需要的只是排序正确,也就是说,我们希望预测为 1.1 的单位比单位受价格上涨的影响更小预测为 0.5。

好的,我们有弹性或 CATE 模型。但仍然存在一个潜在的问题:它们与 ML 预测模型相比如何?现在让我们试试吧。我们将使用机器学习算法,使用价格、温度、工作日和成本作为特征 X 并尝试预测冰淇淋销售。

X = ["temp", "weekday", "cost", "price"]
y = "sales"
ml = GradientBoostingRegressor()
ml.fit(train[X], train[y])

# make sure the model is not overfiting.
ml.score(test[X], test[y])
0.9124088322890127

该模型可以预测我们每天的销售额。 但它适合我们真正想要的吗? 换句话说,这个模型能区分人们对冰淇淋价格更敏感的日子吗? 它可以帮助我们根据价格敏感度决定收取多少费用吗?

要查看哪个模型更有用,让我们尝试使用它们来分割个体单元。 对于每个模型,我们将个体单元分成 2 组。 我们希望一个群体对价格上涨反应灵敏,而另一个群体则反应不大。 如果是这样的话,我们可以围绕这些群体组织我们的业务:对于属于高响应群体的日子,我们最好不要将价格定得太高。 对于低响应群体,我们可以提高价格而不会冒太大的销售风险。

bands_df = pred_elast3.assign(
    elast_band = pd.qcut(pred_elast3["pred_elast"], 2), # create two groups based on elasticity predictions 
    pred_sales = ml.predict(pred_elast3[X]),
    pred_band = pd.qcut(ml.predict(pred_elast3[X]), 2), # create two groups based on sales predictions
)

bands_df.head()

接下来,我们需要比较这两个人群分层模型哪一个是最好的。 我现在可能有点超前了,因为我们只会在下一章中讨论 CATE 模型评估。 但我觉得我可以让你尝尝它的样子。 检查这些分层模式有多好的一种非常简单的方法 - 我的意思是好用 - 就是绘制每个分区的销售价格回归线。 我们可以通过 Seaborn 的 regplot 和 FacetGrid 轻松实现这一点。

下面,我们可以看到使用弹性预测进行的分层。 请记住,所有这些都是在测试集中完成的。

g = sns.FacetGrid(bands_df, col="elast_band")
g.map_dataframe(sns.regplot, x="price", y="sales")
g.set_titles(col_template="Elast. Band {col_name}");

正如我们所看到的,看起来这种分层方案很有用。 对于第一个分层,价格敏感性很高。 随着价格的上涨,销售额下降了很多。 然而,对于第二个分层,随着价格的上涨,销售大致保持不变。 事实上,当我们提高价格时,甚至看起来销量也在上升,但这可能是噪音。

现在与使用 ML 预测模型进行的用户分层进行对比:

g = sns.FacetGrid(bands_df, col="pred_band")
g.map_dataframe(sns.regplot, x="price", y="sales")
g.set_titles(col_template="Pred. Band {col_name}");

我真的很喜欢这个图,因为它传达了一个非常重要的观点。如您所见,预测模型分层在 y 轴上分割个体单元。如第一幅图所示,在第一个分层所对应的日子里,我们没有售出很多冰淇淋,但在第二个分层对应那些日子里,我们确实卖得更多。我觉得这很神奇,因为预测模型正在做它应该做的事情:它预测销售。它可以区分冰淇淋销售量低和高的日子。

唯一的问题是预测在这里并不是特别有用。最终,我们想知道什么时候可以提高价格,什么时候不能。但是,一旦我们查看预测模型分层中线的斜率,我们就会发现它们并没有太大变化。换句话说,由预测模型定义的两个分层对价格上涨的反应大致相同。这并没有让我们深入了解哪些日子可以提高价格,因为看起来价格根本不会影响销售。

关键思想

我们最终正式确定了条件平均干预效果的概念以及它如何对个性化有用。即,如果我们能了解每个单位对一种干预的反应,即如果我们能了解干预效果的异质性,我们就可以根据单位的个体特点给予最好的干预。

我们还将这个目标与预测模型的目标进行了对比。也就是说,我们正在重新考虑估计任务,从预测原始格式的 Y 到预测 Y 如何随 T、\frac{\delta y}{\delta t} 。

可悲的是,如何为此构建模型并不明显。由于我们不能直接观察弹性,因此很难建立一个预测它的模型。但是线性回归拯救了我们。通过使用适合预测 Y 的回归模型,我们找到了一种方法来预测 \frac{\delta y}{\delta t} 。我们还必须包括干预和特征的交互项。这使得我们对每个客户的弹性预测都不同。换句话说,我们现在正在估计 E[T′(t)|X]。然后使用这些弹性预测将我们的单位分组为或多或少对干预敏感,最终帮助我们确定每组的干预水平。

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

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

相关文章

Flutter ffi iOS Failed to lookup symbol

官方文档:在 iOS 中使用 dart:ffi 调用本地代码

【SPIE独立出版 | 往届均已完成EI检索】2024云计算、性能计算与深度学习国际学术会议(CCPCDL 2024)

2024云计算、性能计算与深度学习国际学术会议(CCPCDL 2024) 2024 International conference on Cloud Computing, Performance Computing and Deep Learning *CCPCDL往届均已完成EI检索,最快会后4个半月完成! 一、重要信息 大会官网:www…

App上架和推广前的准备

众所周知,App推广的第一步是上架各大应用下载市场,然后才是其他推广渠道。所以本文主要分两部分,第一部分主要介绍的是上架各大应用市场方面的准备,第二部分主要介绍的是其他渠道推广方面的准备。 一、App上架前的准备 1.1 上架…

MySQL----表级锁行级锁排它锁和共享锁意向锁

MySQL的锁机制 锁(Locking)是数据库在并发访问时保证数据一致性和完整性的主要机制。在 MySQL 中,不同存储引擎使用不同的加锁方式;我们以 InnoDB 存储引擎为例介绍 MySQL 中的锁机制,其他存储引擎中的锁相对简单一些…

游戏开发丨基于PyGame的消消乐小游戏

文章目录 写在前面PyGame消消乐注意事项系列文章写在后面 写在前面 本期内容:基于pygame实现喜羊羊与灰太狼版消消乐小游戏 下载地址:https://download.csdn.net/download/m0_68111267/88700193 实验环境 python3.11及以上pycharmpygame 安装pygame…

【一文开启StableDiffusion】最火AIGC绘画工具SD阿里云部署指南(含踩坑经验)

Midjonery使用简单,效果出色,不过需要付费。本文将介绍完全开源的另一款产品StableDiffusion,它的社区目前非常活跃,各种插件和微调模型都非常多,而且它无需付费注册,没有速度、网络限制,非常推…

Matlab基础篇:数据输入输出

前言 数据输入和输出是 Matlab 数据分析和处理的核心部分。良好的数据输入输出能够提高工作效率,并确保数据处理的准确性。本文将详细介绍 Matlab 数据输入输出的各种方法,包括导入和导出数据、数据处理和数据可视化。 一、导入数据 Matlab 提供了多种方…

使用Tkinter创建带查找功能的文本编辑器

使用Tkinter创建带查找功能的文本编辑器 介绍效果代码解析创建主窗口添加菜单栏实现文件操作实现查找 完整代码 介绍 在这篇博客中,我将分享如何使用Python的Tkinter库创建一个带有查找功能的简单文本编辑器。 效果 代码解析 创建主窗口 import tkinter as tkcl…

第二十章 迭代器模式

目录 1 迭代器模式介绍 2 迭代器模式原理 3 迭代器模式实现 4 迭代器模式应用实例 5 迭代器模式总结 1 迭代器模式介绍 迭代器模式(Iterator pattern)又叫游标(Cursor)模式,它的原始定义是:迭代器提供一种对容器对象中的各…

supOS数据集成

为解决企业数据孤岛问题,supOS对外提供了天湖能力,APP应用集成到supOS后可以使用supOS的天湖,所有数据归集到天湖,利用supOS的ESB消息总线能力实现各个业务系统的服务注册,对外提供统一消息总线能力,从而解…

电致变色和电泳——有什么区别?

虽然电泳显示器和电致变色显示器都是反射显示器的示例,但其基础技术却截然不同。电致变色显示器采用超薄聚合物,可响应施加的电场而改变颜色。电场使电致变色材料发生化学氧化和还原。这种变化需要的能量很少,而且比较稳定,因此刷…

【尚庭公寓SpringBoot + Vue 项目实战】后台岗位管理(十六)

【尚庭公寓SpringBoot Vue 项目实战】后台岗位管理(十六) 文章目录 【尚庭公寓SpringBoot Vue 项目实战】后台岗位管理(十六)1、业务说明2、逻辑模型介绍3、接口开发3.1、分页查询岗位信息3.2、保存或更新岗位信息3.3、根据ID删…

vue项目build 打包之后如何本地访问

vue项目build 打包之后如何本地访问 注意:vue项目build打包后 如果想实现本地访问 不能直接打开访问dist文件中的HTML文件(因为页面带会报错打不开。),需要启一个服务,通过服务来访问: 具体操作过程如下&am…

2024/06/18--代码随想录算法7/17|198.打家劫舍、213.打家劫舍II、337.打家劫舍III

198.打家劫舍 力扣链接 动态规划5步曲 确定dp数组(dp table)以及下标的含义: dp[i]: 下标i内(包括i)的房屋,最多可以偷到的金额为dp[i]确定递推公式 dp[i] max(dp[i-1], dp[i-2]nums[i])dp数…

磨削可以减少噪音和振动,并有助于提高电动汽车的齿轮效率

随着汽油成本的不断增加以及保护环境的愿望不断增强,电动汽车的发展势头越来越强劲也就不足为奇了。汽车制造商正在积极推动推出全电动产品,甚至比最初的目标日期 2040 年还要早。为了支持电气化的发展,支持这些车辆的供应链正在进行巨额投资…

全网最全!25届最近5年上海交通大学自动化考研院校分析

上海交通大学 目录 一、学校学院专业简介 二、考试科目指定教材 三、近5年考研分数情况 四、近5年招生录取情况 五、最新一年分数段图 六、历年真题PDF 八、学费&奖学金&就业方向 一、学校学院专业简介 二、考试科目指定教材 1、考试科目介绍 2、指定教材介绍…

Windows CSC 服务特权提升漏洞复现(CVE-2024-26229)

漏洞信息 Windows CSC服务特权提升漏洞。 当程序向缓冲区写入的数据超出其处理能力时,就会发生基于堆的缓冲区溢出,从而导致多余的数据溢出到相邻的内存区域。这种溢出会损坏内存,并可能使攻击者能够执行任意代码或未经授权访问系统。本质上…

html5 draggable组件拖动自由布局的实现

如何使元素支持拖动 实现组件的自由拖动的核心就是 html5 中新添加的全局属性 draggable 属性,该属性规定了元素是否可进行拖动。属性值如下所示: true:规定元素的可拖动的false:规定元素不可拖动auto:使用浏览器的默…

【数据结构与算法】循环队列 重要知识点详解

循环队列的数据结构。 struct CircularQueue {ElemType a[MaxSize];int front, rear; };这个结构体包含三个成员: a 是一个 ElemType 类型的数组,用于存储循环队列的元素。front 是一个整数,表示队列头部元素的前一个位置。rear 是一个整数…

计算机跨考现状,两极分化现象很严重

其实我觉得跨考计算机对于一些本科学过高数的同学来说有天然的优势 只要高数能学会,那计算机那几本专业课,也能很轻松的拿下,而对于本科是文科类的专业,如果想跨考计算机,难度就不是一般的大了。 现在跨考计算机呈现…