【因果推断python】44_评估因果模型2

news2024/11/25 2:58:48

目录

累积弹性曲线

累积增益曲线

考虑差异

关键思想


累积弹性曲线

再次考虑将价格转换为二元处理的说明性示例。我们会从我们离开的地方拿走它,所以我们有弹性处理带。我们接下来可以做的是根据乐队的敏感程度对乐队进行排序。也就是说,我们把最敏感的组放在第一位,第二个最敏感的组放在第二位,依此类推。对于模型 1 和 3,无需重新订购,因为它们已经订购。对于模型 2,我们必须颠倒排序。

一旦我们有了有序的组,我们就可以构建我们称之为累积弹性曲线的东西。我们首先计算第一组的弹性;然后,第一个和第二个等等,直到我们包含所有组。最后,我们将只计算整个数据集的弹性。这是我们的说明性示例的外观。

img

请注意,累积弹性中的第一个 bin 只是根据该模型来自最敏感组的 ATE。此外,对于所有模型,累积弹性将收敛到同一点,即整个数据集的 ATE。

在数学上,我们可以将累积弹性定义为直到单位 k 之前估计的弹性。\widehat{y^{\prime}(t)}_k=\hat{\beta}_{1k}=\frac{\sum_i^k(t_i-\bar{t})(y_i-\bar{y})}{\sum_i^k(t_i-\bar{t})^2}

为了构建累积弹性曲线,我们在数据集中迭代地运行上述函数以产生以下序列。\widehat{(y^{\prime}(t)_1,\widehat{y^{\prime}(t)_2},\widehat{y^{\prime}(t)_3},\ldots,\widehat{y^{\prime}(t)_N})}

就模型评估而言,这是一个非常有趣的序列,因为我们可以对其进行偏好陈述。首先,模型更好的程度

\hat{y}'(t)k > \hat{y}'(t){k+a}

对于任何 k 和 a>0。换句话说,如果一个模型擅长对弹性进行排序,那么在前 k个样本中观察到的弹性应该高于在前 k+a 个样本中观察到的弹性。或者,简单地说,如果我查看顶部单位,它们应该比它们下面的单位具有更高的弹性。

其次,模型更好的程度

\hat{y}'(t)k - \hat{y}'(t){k+a}

是最大的,对于任何 k 和 a>0。直觉是,我们不仅希望顶部 k 单位的弹性高于其下方单位的弹性,而且我们希望这种差异尽可能大。

为了使其更具体,这是用代码表示的这个想法。

def cumulative_elast_curve(dataset, prediction, y, t, min_periods=30, steps=100):
    size = dataset.shape[0]
    
    # orders the dataset by the `prediction` column
    ordered_df = dataset.sort_values(prediction, ascending=False).reset_index(drop=True)
    
    # create a sequence of row numbers that will define our Ks
    # The last item is the sequence is all the rows (the size of the dataset)
    n_rows = list(range(min_periods, size, size // steps)) + [size]
    
    # cumulative computes the elasticity. First for the top min_periods units.
    # then for the top (min_periods + step*1), then (min_periods + step*2) and so on
    return np.array([elast(ordered_df.head(rows), y, t) for rows in n_rows])

关于此功能的一些注意事项。 它假定对弹性进行排序的事物存储在传递给“预测”参数的列中。 此外,第一组有 min_periods 单位,因此它可以与其他组不同。 原因是,由于样本量小,弹性在曲线开始时可能过于嘈杂。 为了解决这个问题,我们可以传递一个已经足够大的第一组。 最后,steps 参数定义了我们在每个后续组中包含多少额外单元。

使用此功能,我们现在可以根据每个模型产生的顺序绘制累积弹性曲线。

plt.figure(figsize=(10,6))

for m in range(3):
    cumu_elast = cumulative_elast_curve(prices_rnd_pred, f"m{m+1}_pred", "sales", "price", min_periods=100, steps=100)
    x = np.array(range(len(cumu_elast)))
    plt.plot(x/x.max(), cumu_elast, label=f"M{m+1}")

plt.hlines(elast(prices_rnd_pred, "sales", "price"), 0, 1, linestyles="--", color="black", label="Avg. Elast.")
plt.xlabel("% of Top Elast. Days")
plt.ylabel("Cumulative Elasticity")
plt.title("Cumulative Elasticity Curve")
plt.legend();

解释累积弹性曲线可能有点挑战性,但这是我的看法。同样,考虑二分类情况可能更容易。曲线的 X 轴代表我们正在处理的样本数量。在这里,我将轴归一化为数据集的比例,所以 0.4 意味着我们正在处理 40% 的样本。 Y 轴是我们在这么多样本上应该预期的弹性。因此,如果一条曲线在 40% 处的值为 -1,则意味着前 40% 单位的弹性为 -1。理想情况下,我们希望尽可能大的样本具有最高的弹性。理想的曲线将在 Y 轴上从高处开始,然后非常缓慢地下降到平均弹性,这表示我们可以处理高百分比的单位,同时仍保持高于平均弹性。

不用说,我们的模型都没有接近理想的弹性曲线。随机模型 M3 围绕平均弹性波动,并且永远不会离它太远。这意味着该模型无法找到弹性与平均弹性不同的组。至于预测模型 M1,它似乎是反向排序的弹性,因为曲线从低于平均弹性开始。不仅如此,它还在大约 50% 的样本处很快收敛到平均弹性。最后,因果模型 M2 似乎更有趣。一开始它有这种奇怪的行为,累积弹性增加远离平均值,但随后它达到了一个点,我们可以处理大约 75% 的单位,同时保持几乎为 0 的相当不错的弹性。这可能是因为这个模型可以识别非常低弹性(高价格敏感度)的日子。因此,如果我们在那些日子不提价,我们可以对大部分样本(约 75%)进行提价,同时价格敏感度仍然较低。

在模型评估方面,累积弹性曲线(Cumulative Elasticity Curve) 已经远远好于简单的分区间的弹性概念。在这里,我们设法对我们的模型做出更精确的偏好陈述。不过,这是一条复杂的曲线,难以理解。出于这个原因,我们可以做进一步的改进。

累积增益曲线

下一个想法是在累积弹性之上进行非常简单但强大的改进。我们将累积弹性乘以比例样本量。例如,如果累积弹性在 40% 时为 -0.5,那么此时我们将得到 -0.2 (-0.5 * 0.4)。然后,我们将其与随机模型产生的理论曲线进行比较。这条曲线实际上是一条从 0 到平均干预效果的直线。可以这样想:随机模型的累积弹性中的每个点都是 ATE,因为该模型只生成数据的随机代表性分区。如果在 (0,1) 线上的每一点,我们将 ATE 乘以该点,我们最终会得到一条介于 0 和 ATE 之间的直线。

img

一旦我们有了理论上的随机曲线,我们就可以将其用作基准,并将我们的其他模型与它进行比较。所有曲线将在同一点开始和结束。然而,模型的弹性排序越好,曲线在零到一之间的点处偏离随机线的程度就越大。例如,在上图中,M2 优于 M1,因为它在到达终点 ATE 之前发散得更多。对于熟悉 ROC 曲线的人,您可以将累积增益视为因果模型的 ROC。

从数学上讲,

\widehat{F(t)}_k=\hat{\beta}_{1k}*\frac kN=\frac{\sum_i^k(t_i-\bar{t})(y_i-\bar{y})}{\sum_i^k(t_i-\bar{t})^2}*\frac kN

要在代码中实现它,我们所要做的就是添加比例样本大小归一化。

def cumulative_gain(dataset, prediction, y, t, min_periods=30, steps=100):
    size = dataset.shape[0]
    ordered_df = dataset.sort_values(prediction, ascending=False).reset_index(drop=True)
    n_rows = list(range(min_periods, size, size // steps)) + [size]
    
    ## add (rows/size) as a normalizer. 
    return np.array([elast(ordered_df.head(rows), y, t) * (rows/size) for rows in n_rows])

 使用我们的冰激凌数据,我们会得到如下曲线。

plt.figure(figsize=(10,6))

for m in range(3):
    cumu_gain = cumulative_gain(prices_rnd_pred, f"m{m+1}_pred", "sales", "price", min_periods=50, steps=100)
    x = np.array(range(len(cumu_gain)))
    plt.plot(x/x.max(), cumu_gain, label=f"M{m+1}")
    
plt.plot([0, 1], [0, elast(prices_rnd_pred, "sales", "price")], linestyle="--", label="Random Model", color="black")

plt.xlabel("% of Top Elast. Days")
plt.ylabel("Cumulative Gain")
plt.title("Cumulative Gain")
plt.legend();

现在很清楚,因果模型(M2)比其他两个要好得多。它与随机线的差异远大于 M1 和 M3。此外,请注意随机模型 M3 如何非常接近理论随机模型。两者之间的区别可能只是随机噪声。

有了这个,我们介绍了一些关于如何评估因果模型的非常好的想法。仅此一项就是一件大事。即使我们没有要比较的基本事实,我们也设法评估了模型在排序弹性方面的好坏。只缺少最后一件事,即包括围绕这些测量值的置信区间。毕竟,我们不是野蛮人,不是吗?

考虑差异

当我们处理弹性曲线时,不考虑方差是错误的。特别是由于它们都使用线性回归理论,因此在它们周围添加置信区间应该相当容易。

为此,我们将首先创建一个函数,该函数返回线性回归参数的 CI。我在这里使用简单线性回归的公式,但可以随意提取 CI。s_{\hat{\beta}_1}=\sqrt{\frac{\sum_i\hat{\epsilon}_i^2}{(n-2)\sum_i(t_i-\bar{t})^2}}

def elast_ci(df, y, t, z=1.96):
    n = df.shape[0]
    t_bar = df[t].mean()
    beta1 = elast(df, y, t)
    beta0 = df[y].mean() - beta1 * t_bar
    e = df[y] - (beta0 + beta1*df[t])
    se = np.sqrt(((1/(n-2))*np.sum(e**2))/np.sum((df[t]-t_bar)**2))
    return np.array([beta1 - z*se, beta1 + z*se])

通过对我们的cumulative_elast_curve函数进行一些小的修改,我们可以输出弹性的置信区间。

def cumulative_elast_curve_ci(dataset, prediction, y, t, min_periods=30, steps=100):
    size = dataset.shape[0]
    ordered_df = dataset.sort_values(prediction, ascending=False).reset_index(drop=True)
    n_rows = list(range(min_periods, size, size // steps)) + [size]
    
    # just replacing a call to `elast` by a call to `elast_ci`
    return np.array([elast_ci(ordered_df.head(rows), y, t)  for rows in n_rows])

最后,这是因果 (M2) 模型的 95% CI 的累积弹性曲线。

plt.figure(figsize=(10,6))

cumu_gain_ci = cumulative_elast_curve_ci(prices_rnd_pred, "m2_pred", "sales", "price", min_periods=50, steps=200)
x = np.array(range(len(cumu_gain_ci)))
plt.plot(x/x.max(), cumu_gain_ci, color="C0")

plt.hlines(elast(prices_rnd_pred, "sales", "price"), 0, 1, linestyles="--", color="black", label="Avg. Elast.")

plt.xlabel("% of Top Elast. Days")
plt.ylabel("Cumulative Elasticity")
plt.title("Cumulative Elasticity for M2 with 95% CI")
plt.legend();

注意随着我们积累更多的数据集,CI 是如何变得越来越小的。 那是因为样本量增加了。

至于累积增益曲线,获取 CI 也同样简单。 同样,我们只是将调用 elast 函数替换为调用 elast_ci 函数。

def cumulative_gain_ci(dataset, prediction, y, t, min_periods=30, steps=100):
    size = dataset.shape[0]
    ordered_df = dataset.sort_values(prediction, ascending=False).reset_index(drop=True)
    n_rows = list(range(min_periods, size, size // steps)) + [size]
    return np.array([elast_ci(ordered_df.head(rows), y, t) * (rows/size) for rows in n_rows])

这是因果模型的样子。 请注意,现在 CI 开始时很小,即使曲线开始时的样本量较小。 原因是归一化因子 \frac{k}{N} 回避了 ATE 参数,并且它是 CI。 由于这条曲线应该用于比较模型,所以这应该不是问题,因为曲线会将这个推卸因子平等地应用于所有正在评估的模型。

plt.figure(figsize=(10,6))

cumu_gain = cumulative_gain_ci(prices_rnd_pred, "m2_pred", "sales", "price", min_periods=50, steps=200)
x = np.array(range(len(cumu_gain)))
plt.plot(x/x.max(), cumu_gain, color="C0")

plt.plot([0, 1], [0, elast(prices_rnd_pred, "sales", "price")], linestyle="--", label="Random Model", color="black")

plt.xlabel("% of Top Elast. Days")
plt.ylabel("Cumulative Gain")
plt.title("Cumulative Gain for M2 with 95% CI")
plt.legend();

关键思想

在这里,我们看到了三种方法来检查模型在排序弹性方面的好坏。我们使用这些方法来比较和决定具有因果关系的模型。这是非常重要的。我们已经设法检查了一个模型是否擅长识别具有不同弹性的组,即使无法看到弹性!

在这里,我们严重依赖随机数据。我们在非随机数据上训练了模型,但所有评估都是在随机处理的样本上完成的。那是因为我们需要某种方法来自信地估计弹性。如果没有随机数据,我们在这里使用的简单公式将不起作用。正如我们现在非常清楚的那样,简单的线性回归在存在混杂变量的情况下忽略了变量偏差。

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

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

相关文章

Python学习打卡:day10

day10 笔记来源于:黑马程序员python教程,8天python从入门到精通,学python看这套就够了 目录 day1073、文件的读取操作文件的操作步骤open()打开函数mode常用的三种基础访问模式读操作相关方法read()方法readlines()方法readline()方法for循…

大模型微调和RAG的应用场景

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

进入docker容器内部操作mysql数据库

文章目录 1、查询docker容器2、进入mysql容器内部3、连接mysql数据库4、查询mysql所有的数据库5、使用某个数据库6、展示数据库中所有的表7、查询某张表8、断开mysql9、退出mysql容器 1、查询docker容器 [rootlocalhost ~]# docker ps CONTAINER ID IMAGE …

聚观早报 | 苹果AI功能将分批上线;三星Galaxy Z Fold6尺寸数据

聚观早报每日整理最值得关注的行业重点事件,帮助大家及时了解最新行业动态,每日读报,就读聚观365资讯简报。 整理丨Cutie 6月18日消息 苹果AI功能将分批上线 三星Galaxy Z Fold6尺寸数据 华为智慧PC新品AI能力升级 抖音出品《三星堆&am…

Spring MVC学习记录(基础)

目录 1.SpringMVC概述1.1 MVC介绍1.2 Spring MVC介绍1.3 Spring MVC 的核心组件1.4 SpringMVC 工作原理 2.Spring MVC入门2.1 入门案例2.2 总结 3.RequestMapping注解4.controller方法返回值4.1 返回ModelAndView4.2 返回字符串4.2.1 逻辑视图名4.2.2 Redirect重定向4.2.3 forw…

六面体大米装袋机长期稳定运行原因分析

随着现代化农业生产的发展,六面体大米装袋机已成为粮食加工行业不可或缺的重要设备。然而,如何确保这些机器长期稳定运行,提高生产效率,降低维护成本,一直是广大粮食加工企业关注的焦点。星派将为您揭示六面体大米装袋…

如何在前端项目中用字体图标替换图片,方便减小打包体积和统一切换颜色

1.进入阿里妈妈矢量图标图库 地址:阿里妈妈矢量图 2.搜索自己想要的图标 3.添加自己想要的图标 4.把刚才选的图标,添加到自己要下载的项目 5.把项目下载到本地 6.引入iconfont.css 在div上增加对应的类名就可以啦 下载的所有类名都在下面的demo_index…

测速小车模块

1.用途:广泛用于电机转速检测,脉冲计数,位置限位等。 2.有遮挡,输出高电平;无遮挡,输出低电平 接线 VCC 接电源正极3.3-5V GND 接电源负极 DO TTL开关信号输出 AO 此模块不起作用 测试原理和单位换算:…

如何定制Spring的错误json信息

一,前言 相信很多同学都有遇到过这样的spring错误信息。 在我们没有做catch处理时或者做全局的exceptionHandle时,Spring遇到抛出向外的异常时,就会给我们封装返回这么个格式的异常信息。 那么问题来了,我们能否对这个返回增加错…

[Linux] vi编辑器

命令模式&文本模式 命令模式就输入命令然后执行,文本模式就是系统把你的输入都当成写进文件里的字符 切换模式: 刚进入默认是命令模式,按: i I a A o O 进入文本模式, 通过他们进入文本模式有什么不同? 然后按esc进…

PLC模拟量和数字量到底有什么区别?

PLC模拟量和数字量的区别 在工业自动化领域,可编程逻辑控制器(PLC)是控制各种机械设备和生产过程的核心组件。PLC通过处理模拟量和数字量来实现对工业过程的精确控制。了解模拟量和数字量的区别对于设计高效、可靠的自动化系统至关重要。 1. …

vue3+ts 使用vue3-ace-editor实现Json编辑器

1、效果图 输入代码,点击格式化就出现以上效果,再点击压缩,是以下效果2、安装 npm i vue3-ace-editor 3、使用 新建aceConfig.js文件 // ace配置,使用动态加载来避免第一次加载开销 import ace from ace-builds// 导入不同的主…

查看服务器接口各行代码耗时的 linux 命令

如何通过命令来查看接口具体位置的耗时情况 首先然后找到需要执行查看耗时的方法执行查询命令 trace 首先 使用这个命令 curl -O https://arthas.aliyun.com/arthas-boot.jar java -jar arthas-boot.jar然后找到需要执行查看耗时的方法 复制出来的 是 com.a.tms.api.service.…

昇思MindSpore全场景深度学习框架总结

昇思MindSpore介绍 MindSpore是一个全场景深度学习框架,旨在实现易开发、高效执行、全场景统一部署三大目标,具体包括API友好、调试难度低、计算效率、数据预处理效率和分布式训练效率高以及支持云、边缘和端侧场景。 昇思MindSpore的各个扩展功能模块&…

基于JSP的高校毕业生就业满意度调查统计系统

开头语: 你好呀,我是计算机学长猫哥!如果有相关需求,文末可以找到我的联系方式。 开发语言:JSP 数据库:MySQL 技术:JSP技术 工具:MyEclipse、Tomcat、MySQL 系统展示 首页 用…

SPI协议——读取外部SPI Flash ID

简介: 单片机型号:stm32l431rct6 SPI Flash型号:W25Q32JVSSIQ 使用软件:CubeIDE 1. W25Q32JVSSIQ简介 我们通过SPI协议来读取 SPI Flash的厂商ID和芯片独一无二的ID,查数据的芯片手册可以看到如下重要点: …

pandas中的loc和iloc

loc和iloc的比较 .loc 和 .iloc 是 pandas 提供的两种不同的索引方法,它们的主要区别在于索引数据的依据: .loc: 基于标签的索引,使用 DataFrame 或 Series 的索引标签(即行名和列名)来获取数据。可以使用…

# 消息中间件 RocketMQ 高级功能和源码分析(五)

消息中间件 RocketMQ 高级功能和源码分析(五) 一、 消息中间件 RocketMQ 源码分析:NameServer 路由元数据 1、消息中间件 RocketMQ 中,NameServer 路由管理 NameServer 的主要作用是为消息的生产者和消息消费者提供关于主题 To…

AI口语练习APP的技术难点

AI口语练习APP旨在帮助用户练习口语,因此其核心功能是语音识别和语音评测。以下是一些AI口语练习APP的主要技术难点。北京木奇移动技术有限公司,专业的软件外包开发公司,欢迎交流合作。 1. 语音识别 语音识别是将语音信号转换为文本的过程。…

怎么移除pdf文件编辑限制,有哪些方法?

PDF是我们在学习或工作中常常应用到的一种文件格式,因为它的跨平台性和文档保真度而备受欢迎。但是,有时我们会遇到PDF编辑权限被限制了,那么pdf解除编辑限制可以用什么方法呢?别急,接下来,本文将深入探讨如…