因果推断的简易方法

原文:towardsdatascience.com/easy-methods-for-causal-inference-bb5d3da4f8ca

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/2568e30dcfe67b2dfb2ec1e0f87a9704.png

图片由 Mika BaumeisterUnsplash 提供

想象一下,你已经构建了一个出色的机器学习模型,可以非常准确地预测你的目标值。在某些情况下,你的工作可能就在这一点结束了。然而,通常业务不仅想知道会发生什么,还想知道如何影响结果。正如这句格言所说:

知道未来是银,能够改变未来是金。

这个简单的事实不言而喻,你知道它来自你的个人生活。知道下周的彩票号码是好事,但只有当你能相应地调整你的号码时。


作为商业案例,考虑客户流失问题,即停止与你进行业务往来的客户。知道客户想要离开你是好事,但真正的问题是:如何防止这位客户流失?

业务希望有一种干预方式,例如通过发放优惠券或授予这位客户某种会员升级,以降低客户流失的概率。

如果 x = “给客户发放优惠券” 和 y = 流失概率,我们希望能够做出因果陈述:如果我做 xy 会发生什么?人们也喜欢称之为假设情景x 被称为处理变量

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/90562ebc7115d4b63c18c77313214101.png

图像由作者提供。

这比做出相关性陈述要困难得多。观察到冰淇淋销量与鲨鱼攻击相关很容易。但一个导致另一个吗?可能不是。而是好天气驱使人们购买冰淇淋并在海边游泳,使他们暴露在鲨鱼面前。因此,关闭所有冰淇淋店作为减少鲨鱼攻击的方法很可能会不起作用。


在这篇文章中,我将向你展示如何得出正确的结论。我将向你展示的方法在算法层面上极其简单:只需训练模型并对它们的预测进行轻微的后处理。然而,在因果推断中,你必须小心在训练过程中包含哪些特征。不是越多越好。这就是为什么我会首先向你展示一个简单的工具来检查你应该包含哪些特征,然后才是实际的方法。

小心这些特征

让我们从我的另一篇文章中举一个例子。你可以在这里阅读,但我也会简要回顾一下:

因果推断的必要性

假设我们有一个关于公司员工的数据库。我们知道他们的责任感、他们工作的加班、他们拥有的收入以及他们的幸福感

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/19a15c3f28667fede358b1e633cdcaf1.png

作者图片。

你想回答以下问题:

加班如何影响收入?

在这里,加班是我们的处理方法,而收入是结果。如果你之前从未听说过因果推断,解决方案似乎非常明显:

  1. 训练一个包含所有特征责任感加班幸福感的模型来预测收入,然后

  2. 加班输入许多数字,看看收入如何变化。

如果模型有很好的预测能力,这应该会奏效,对吧?

很遗憾,不是。

这并不普遍适用,正如我在上面的另一篇文章中展示的那样。原因是典型的机器学习模型只学习相关性,而不是因果关系。如果你不小心,模型会学会降低冰淇淋销量以减少鲨鱼袭击的数量。

然而,通过仔细选择你的特征,上述方法仍然有效!你的特征集必须是所谓的足够调整集。让我们看看这意味着什么。

足够调整集

足够调整集的概念相当理论化,我不会在这篇文章中详细介绍,因为我可以写一个关于它的整个系列文章。我只是想指向www.dagitty.net/dags.html,你可以检查自己的特征是否形成一个足够调整集。

首先,你必须指定一个因果图,这是到目前为止进行因果推断最难的部分。这是一个告诉你哪些特征可能影响其他特征的图。对于上述数据,让我们假设以下因果关系:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/10cb7b0b3bab98a854e359f24f3ee82d.png

作者图片。来源:www.dagitty.net/

此图编码了以下假设:

  1. 责任感影响某人工作多少加班以及收入。(如果我责任感强,我可能会工作更长,也可能更努力或更勤奋,这可能会导致更高的收入。

  2. 加班影响幸福感和收入。(过多的加班让人不快乐,但会带来更多的钱。

  3. 收入也影响幸福感。(更多的钱,更多的幸福!

还有更多隐藏的假设,你可以通过箭头的缺失来识别。例如,图编码了收入不会影响加班,或者幸福感不会影响责任感。我们还假设没有其他因素影响收入或其他变量,这是一个相当强的假设。

你可以争论这些假设是否有意义。它们通常不可验证,这使得因果推理如此困难。但为了我们的目的,让我们采用这个图,因为它足够合理。

好的,所以我们已经决定了数据集的因果结构。再次强调,这是难点,你必须在这里小心。现在找到足够的调整集——即使得我们的简单方法训练模型并插入不同的处理变量值——是一个纯粹的图论任务。Dagitty 现在可以帮我们完成这个任务。

Dagitty

你可以轻松地从上面的图片中拼凑出图。然后,在左上角,你可以标记

  • 超时作为暴露(处理),即你想要玩弄以查看它如何改变结果的东西,

  • 收入作为结果

网站会告诉你,责任感是一个位于右上角的足够的调整集

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/70e8c5b5a7ce0ecbab1e8689040a6eb5.png

作者图片。

你现在可以点击责任感并将其标记为调整过,同样的框会告诉你你已经正确调整。如果你将幸福感也设置为调整过,它会告诉你调整不正确。

这对你意味着什么

你应该只使用特征来训练模型

  • 超时和

  • 责任感。

你应该不包括幸福感,你也不应该省略责任感,****如果你想就超时如何影响收入做出因果陈述。

再次强调,在因果关系中,更多的特征并不总是更好的。

在本文的剩余部分,让我们做出以下简单假设:我们数据集中的所有特征形成一个足够的调整集

元学习器

现在,最后一部分比预期的要长,对此表示歉意。然而,这是必要的,因为否则你可能会使用看似简单的方法得出错误的结论。但有了我们的足够调整集假设——在采取任何因果行动之前你应该始终考虑的——一切都会顺利。现在让我们来谈谈如何找到因果效应。

对于数据科学家来说,元学习是最容易计算因果效应的方法,请记住这一点。基本上,你可以拿任何你熟悉和喜爱的机器学习模型,并将其插入另一个算法——元学习器——该算法使用此模型来输出因果效应。

我即将向你展示的元算法很容易实现,但你也可以使用像EconMLCausalML这样的库,用更少的代码实现相同的功能。但没有什么比了解底层发生的事情更好的了,对吧?

二元处理

到目前为止,我没有具体说明处理(超时、优惠券等)是什么类型的变量。在以下内容中,我将假设处理是二元的,因为大多数元学习器只处理这些。

注意,这通常没有问题,因为你总是可以离散化连续特征,比如加班,将其表示为“每周加班少于/多于 3 小时”。像“客户获得优惠券”这样的处理已经是二进制的。

在这种情况下,我们可以看到我们的干预/处理的提升是什么:如果我们采取某种行动会发生什么,如果不采取行动会发生什么。

S-学习者

记得我提出的朴素方法,即只训练一个模型,并为你处理变量插入不同的值?这就是所谓的S-学习者,其中 S 代表单个。在二进制处理T的情况下,我们为T插入 1 和 0,然后减去结果。就是这样。

首先,训练:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/261dfb51b0b17827a2322c240ffed488.png

作者提供的图片

T只是我们的特征之一,但是我们想要切换以观察它如何影响结果的特殊特征。训练后,我们像这样使用模型:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/c94d686f68d56e3e2f8f1495d3518f7c.png

作者提供的图片

然后,对于每一行,我们得到一个提升的估计,即从 0 到 1 设置处理的结果。

T-学习者

这也很简单。当使用 T-学习者——T 代表两个——你训练两个模型。一个在T = 1 的数据集部分,另一个在T = 0 的数据集上。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/b046b1d1888cc4766cb7b195e9d00b2e.png

作者提供的图片

然后,以自然的方式使用它:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/d8b4765cc1132c17d39128a30729170d.png

作者提供的图片

如果你有了这些处理效应,你可以计算你想要的任何其他统计量,例如:

  • 所有观察的平均处理效应,

  • 观察子组的条件处理效应。

实现

让我们实现这两个学习者,这样你就能看到有多简单。首先,让我们加载数据。

!pip install polars
import polars as pl

data = pl.read_csv("https://raw.githubusercontent.com/Garve/datasets/main/causal_data.csv")

数据看起来是这样的:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/f41f11449eddd93afea5aa5f3741685c.png

作者提供的图片

S-学习者

现在,训练一个包含处理变量的单个模型。

from sklearn.ensemble import HistGradientBoostingRegressor

model = HistGradientBoostingRegressor()
X = data.select(pl.all().exclude("y"))
y = data.select("y").to_numpy().ravel()

model.fit(X.to_numpy(), y)

现在,插入训练数据——或者任何其他具有相同格式的数据集——一次替换t为所有 1,所有 0。

X_all_treatment = X.with_columns(t=1).to_numpy() # set treatment to one
X_all_control = X.with_columns(t=0).to_numpy() # set treatment to zero

treatment_effects = model.predict(X_all_treatment) - model.predict(X_all_control)

print(treatment_effects)

# Output:
# [ 0.02497236  3.95121282  4.15999904 ...  3.89655012  0.04411704
#  -0.06875453]

你可以看到,对于某些行,处理增加了输出 4,但对于某些行,则没有。通过简单的

print(treatment_effects.mean())

你会发现平均处理效应大约是 2。所以,如果你要处理你的数据集中的每一个个体,与没有人接受任何处理相比,你的结果平均会增加大约 2。

T-学习者

这里,我们将训练两个模型。

model_0 = HistGradientBoostingRegressor()
model_1 = HistGradientBoostingRegressor()

data_0 = data.filter(pl.col("t") == 0)
data_1 = data.filter(pl.col("t") == 1)

X_0 = data_0.select(["x1", "x2", "x3"]).to_numpy()
y_0 = data_0.select("y").to_numpy().ravel()
X_1 = data_1.select(["x1", "x2", "x3"]).to_numpy()
y_1 = data_1.select("y").to_numpy().ravel()

model_0.fit(X_0, y_0)
model_1.fit(X_1, y_1)

data_without_treatment = data.select(["x1", "x2", "x3"]).to_numpy()
treatment_effects = model_1.predict(data_without_treatment) - model_0.predict(data_without_treatment)

结果与 S-学习者的输出相似。

结论

在这篇文章中,我们了解到估计因果效应并不像人们想象的那样简单。S-学习者的方法论非常自然且易于实现,但它只有在训练特征形成一个足够的调整集时,才能产生有效的因果洞察。对于 T-学习者来说,这也是得出因果结论的另一种选择。

这两种方法都有其优势和劣势。在进行 S 学习时,模型可能会选择忽略处理特征,例如。在这种情况下,预测的治疗效果都将为零,即使实际情况并非如此。T 学习器的问题之一是两个数据集中可能有一个真的非常小。如果只有 10 个观察值,且处理值为 1,你可能不太能信任这个模型。

还有其他方法,例如 Künzet 等人提出的X 学习器来解决这些问题,我们可能在未来的文章中讨论它们。


我希望你在今天学到了一些新的、有趣的、有价值的东西。感谢阅读!

如果您有任何问题,请通过LinkedIn联系我!

如果你想更深入地了解算法的世界,可以尝试我的新书《All About Algorithms》!我仍在寻找作者!

All About Algorithms

课程设计报告:总体方案设计说明 一、软件开发环境配置 本系统采用C++作为核心编程语言,结合Qt 5.12.7框架进行图形用户界面开发。数据库管理系统选用MySQL,用于存储用户数据与小精灵信息。集成开发环境为Qt Creator,操作系统平台为Windows 10。 二、窗口界面架构设计 系统界面由多个功能模块构成,各模块职责明确,具体如下: 1. 起始界面模块(Widget) 作为应用程序的入口界面,提供初始导航功能。 2. 身份验证模块(Login) 负责处理用户登录与账户注册流程,实现身份认证机制。 3. 游戏主大厅模块(Lobby) 作为用户登录后的核心交互区域,集成各项功能入口。 4. 资源管理模块(BagWidget) 展示用户持有的全部小精灵资产,提供可视化资源管理界面。 5. 精灵详情模块(SpiritInfo) 呈现选定小精灵的完整属性数据与状态信息。 6. 用户名录模块(UserList) 系统内所有注册用户的基本信息列表展示界面。 7. 个人资料模块(UserInfo) 显示当前用户的详细账户资料与历史数据统计。 8. 服务器精灵选择模块(Choose) 对战准备阶段,从服务器可用精灵池中选取参战单位的专用界面。 9. 玩家精灵选择模块(Choose2) 对战准备阶段,从玩家自有精灵库中筛选参战单位的操作界面。 10. 对战演算模块(FightWidget) 实时模拟精灵对战过程,动态呈现战斗动画与状态变化。 11. 对战结算模块(ResultWidget) 对战结束后,系统生成并展示战斗结果报告与数据统计。 各模块通过统一的事件驱动机制实现数据通信与状态同步,确保系统功能的连贯性与数据一致性。界面布局遵循模块化设计原则,采用响应式视觉方案适配不同显示环境。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
D3.js作为一种基于JavaScript的数据可视化框架,通过数据驱动的方式实现对网页元素的动态控制,广泛应用于网络结构的图形化呈现。在交互式网络拓扑可视化应用中,该框架展现出卓越的适应性与功能性,能够有效处理各类复杂网络数据的视觉表达需求。 网络拓扑可视化工具借助D3.js展示节点间的关联结构。其中,节点对应于网络实体,连线则表征实体间的交互关系。这种视觉呈现模式有助于用户迅速把握网络整体架构。当数据发生变化时,D3.js支持采用动态布局策略重新计算节点分布,从而保持信息呈现的清晰度与逻辑性。 网络状态监测界面是该工具的另一个关键组成部分,能够持续反映各连接通道的运行指标,包括传输速度、响应时间及带宽利用率等参数。通过对这些指标的持续追踪,用户可以及时评估网络性能状况并采取相应优化措施。 实时数据流处理机制是提升可视化动态效果的核心技术。D3.js凭借其高效的数据绑定特性,将连续更新的数据流同步映射至图形界面。这种即时渲染方式不仅提升了数据处理效率,同时改善了用户交互体验,确保用户始终获取最新的网络状态信息。 分层拓扑展示功能通过多级视图呈现网络的层次化特征。用户既可纵览全局网络架构,也能聚焦特定层级进行细致观察。各层级视图支持展开或收起操作,便于用户开展针对性的结构分析。 可视化样式定制系统使用户能够根据实际需求调整拓扑图的视觉表现。从色彩搭配、节点造型到整体布局,所有视觉元素均可进行个性化设置,以实现最优的信息传达效果。 支持拖拽与缩放操作的交互设计显著提升了工具的使用便利性。用户通过简单的视图操控即可快速浏览不同尺度的网络结构,这一功能降低了复杂网络系统的认知门槛,使可视化工具更具实用价值。 综上所述,基于D3.js开发的交互式网络拓扑可视化系统,整合了结构展示、动态布局、状态监控、实时数据处理、分层呈现及个性化配置等多重功能,形成了一套完整的网络管理解决方案。该系统不仅协助用户高效管理网络资源,还能提供持续的状态监测与深度分析能力,在网络运维领域具有重要应用价值。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
### 因果推断的核心概念 因果推断是一种通过数据分析揭示变量之间因果关系的技术。尽管机器学习擅长于发现变量间的统计关联,但它通常无法直接提供关于因果机制的信息[^1]。为了弥补这一不足,研究者们开发了一系列专门针对因果推断方法。 --- ### 因果推断的主要方法 #### 1. **潜在结果框架 (Potential Outcomes Framework)** 该方法由 Donald Rubin 提出,假设每个个体有两种可能的结果:接受干预后的结果 \(Y(1)\) 和未接受干预的结果 \(Y(0)\)[^3]。然而,在现实中我们只能观察到其中一种结果,而另一种则被称为“反事实”。这种方法的关键在于估计这种反事实,从而计算平均处理效应(Average Treatment Effect, ATE)或其他因果度量指标。 #### 2. **结构因果模型 (Structural Causal Models, SCM)** SCM 是 Judea Pearl 提出的一种理论框架,它利用有向无环图(Directed Acyclic Graphs, DAGs)描述变量间的关系。DAG 可帮助识别混杂因素并指导调整哪些变量以消除偏差[^1]。此外,Pearl 的 do-calculus 提供了一种形式化工具,允许研究人员在复杂场景下推理因果关系。 #### 3. **倾向得分匹配 (Propensity Score Matching, PSM)** PSM 是一种常用的因果推断技术,旨在平衡实验组和对照组之间的协变量分布。其基本思路是根据观测数据拟合一个逻辑回归模型来预测某个单位被分配到处理组的概率(即倾向得分),然后按照这个分数对样本进行配对或加权[^2]。 #### 4. **双差分法 (Difference-in-Differences, DiD)** 当存在时间维度的数据时,DiD 方法可以通过比较处理前后变化率差异的方式评估政策或事件的影响。此方法特别适合面板数据设置下的因果分析[^3]。 --- ### 结合机器学习的实现方式 近年来,随着大数据时代的到来以及深度学习的发展,越来越多的研究尝试将传统因果推断技术和现代机器学习相结合: - Guo 等人在他们的工作中展示了如何借助神经网络生成半合成数据集来进行条件平均处理效应(Conditional Average Treatment Effects, CATE)估计。他们还考虑到了隐藏混淆变量的作用及其在网络环境中的传播特性。 - 使用 Meta-Learners 如 T-learner 或 S-learner 来分别建模不同子群体内的响应函数,并据此得出个性化治疗建议[^1]。 以下是 Python 中基于 scikit-learn 构造简单线性 meta learner 的代码示例: ```python from sklearn.linear_model import LinearRegression import numpy as np class TLearner: def __init__(self): self.model_treated = LinearRegression() self.model_control = LinearRegression() def fit(self, X, y, w): # w is treatment indicator {0, 1} treated_idx = np.where(w == 1) control_idx = np.where(w == 0) self.model_treated.fit(X[treated_idx], y[treated_idx]) self.model_control.fit(X[control_idx], y[control_idx]) def predict_cate(self, X_new): pred_treated = self.model_treated.predict(X_new) pred_control = self.model_control.predict(X_new) return pred_treated - pred_control ``` --- ### 面临的实际挑战 即使有了先进的算法支持,因果推断仍然面临诸多困难,例如缺失数据问题可能导致偏倚估计;高维特征空间增加了模型复杂度等等[^2]。因此,在实践过程中需要综合运用多种策略应对这些障碍。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值