1.介绍

在上个世纪,在各种领域的学者们探讨的决策,或者学习到系统内干预的数学。依赖于决策的一个挑战是完全不同的,更加复杂,不是一个分类问题。例如,设计一台机器从猫(分类问题)区分狗的照片是从教一个不同的建议狗与猫的照片的照片,以最大限度的关键参数(决策问题)。

当我们考虑到历史上观察到的数据来自于过去的决策时,决策问题变得更加复杂,这些决策可能是有偏见的和/或不能传达全局性的。例如,假设我们已经观察到,带伞与发生车祸的可能性高度相关。我们可以推荐干预“不带伞”以减少事故的平均次数?当然不是,考虑到带伞和车祸都是由雨引起的。

原理,一项随机试验这有望解开治疗和所有基线变量之间的独立性可以解决与观察到的数据偏差这一问题。要占用我们前面的例子,如果我们带伞随机不管天气如何,然后测量事故发生率,我们将删除的降雨对结果的影响。

然而,有许多C在随机试验不可行的情况下,这种试验可能非常昂贵,而且在某些情况下,甚至不道德。此外,即使在实验设置中,测试也不会总是顺利进行,因此可能需要进行统计调整。随机试验最大的挑战之一是依从性问题;例如,被分配执行(或)任务的人执行)任务可能不遵循指定的过程。因果推理提供了多种技术,可以帮助随机检验不可行或检验结果不可靠的情况下。

在Wayfair上,有许多业务案例面临着这些挑战,因此受益于因果推理技术的使用。例如,在客户服务中,我们想要测量不同代理商的行为对客户满意度的影响,我们通过每次接触后发送的调查来评估客户满意度。礼貌就是这些行为之一。显然,我们不能进行任何随机测试来评估这种行为的影响,因为对顾客随意无礼是不道德和不切实际的。因此,我们只能通过历史观察来进行评估。在观察数据中,相关性是很容易衡量的,这里的挑战是估计有多少相关性是由于因果关系。

为此,我们需要一个第三个变量,解释控制和目标变量。赖兴巴赫的共同事业的原则,因果推理的基础上,声称这个变量始终存在。这个原则规定:

如果两个随机变量Xÿ统计上是相关的,那么还有第三个变量吗ž该因果关系同时影响变量。(在特殊情况下ž可能与任何一致X要么ÿ) [1]

虽然我们可能并不总是观察变量ž(我将参照作为一组协变量),赖欣巴哈的原则要求它的存在,并且该权利要求已通过实验研究在许多领域[2]进行测试。当我试图说明,在因果推理的最大挑战是找到这个协变量集ž这既影响治疗和结果。

为了说明上面讨论的原则在这篇博客,我会比较已横跨学术界和工业界的多个域使用了两种已知的方法:

1)奈曼 - 鲁宾的潜在结果论(及其变体)

2)使用贝叶斯网络框架的Pearlian do-calculus

在这种比较中,我将首先评估每种方法的有效性,并介绍了使用他们的特殊挑战。然后,我将使用合成数据的两种方法进行比较。在使用每种方法应该开车回家进行因果推理当找到正确的协变量集来使用的重要性遇到的挑战。

2.方法一:内曼-鲁宾的潜在结果理论[3]

假设我们必须在两个决定之间做出选择(例如,是/否或开/关)。在内曼-鲁宾的潜在结果理论(以下称为“潜在结果”)中,我们为每一个决策设计单独的模型。用数学术语来说,假设我们有一组变量X有两个部件{X0X1},分别称为对照和治疗。把这个应用到伞的例子中,我们会说X0代表“不带伞”和X1表示“带有一把伞。”然后,我们将采取我们的观测数据,并将其分成两个水桶:X0这些谁没有带伞,和X1,那些谁把伞。

其中一个配合使用,可能结果的常用方法被称为两个模型方法。通过这两个模型的方法,我们尝试将结果变量分离ÿ分为两个型号;我们模型ÿ0对照组和ÿ1为治疗组。该目标是接近“平均处理效应(ATE)”Δ=Ë[ÿ1-ÿ0]把这个应用到伞的例子中,ÿ代表个人是否发生了交通意外。在这里,我们正在寻找,看看哪些ž变量(以我们的雨伞为例,白天与夜间,城市与乡村环境,或者是否下雨)解释了携带雨伞和发生事故的影响。

为了找到的因果影响X该变量ÿ,我们需要确定控制变量和目标变量是否为第三个变量的函数。多亏了莱辛巴赫的共同原因原理,我们知道了一组变量ž存在,可以解释两者Xÿ;为了模型ÿ1ÿ0我们需要一组变量ž,使得在给定的ž在输入的变化不会改变目标变量或X⊥ÿ0ÿ1|žXÿ0ÿ1独立GIVENž)。应用这一独立事实,联合分布将发生如下变化:

P(X,ÿ_0, Y_1| Z) = P (X|Z) P (Y_0, Y_1|Z)

与可能的结果,最大的挑战在于接近在这一假设:Xÿ0ÿ1|ž我们的因果推理的估计很大程度上依赖于这一假设究竟如何成立,但不幸的是,因为我们从来没有观察ÿ0ÿ1对同一样品,我们无法测试的假设。我们将进一步在我们的评测我们的系统知识不足的限制。这种方法不提供任何工具或指令,用于检测协变量的事实ž正确使它容易出错。一个条件,鲁宾在他的论文中提到(参见[2])的是,在没有可变ž应在应用治疗后选择。在实践中,这是困难的,因为在使用观测数据时,有时很难评估每个变量的相对时间。我将在第5节中说明,即使我们选择了一组变量ž包含正确的协变量作为子集(例如。žž)有机会的话,我们仍然不能够正确地预测干预。

在实现这两个模型方法作为潜在的结果的一部分,可以用于构建多种方法ÿ0ÿ1运用ž。最简单的方法是假设ÿ0ÿ1是的线性模型ž然后X{0,1}将不会出现在ÿ0。其他方法,包括匹配技术,也对计算因果推论使用可能的结果常用。这可以使用各种的距离度量包括倾向匹配,马氏匹配,和遗传匹配来实现。我建议在这个惊人的考虑看看博客[4]由伊恩巴尔进行更深层次的潜水和各种技术更好详细的说明写入。我已经使用了他的一些代码在我的分析如下(第5),因为它是写得很清楚,它完美地服务于这个博客的目的。

虽然有实施其他方法来弥补这一方法的缺乏正确的协检测方法的方式,事实证明这常见和流行的方法是特别容易受到这一故障强调寻找合适的协变量的因果推理的极端重要性。

3.方法二:Pearlian执行 - 微积分

现在,让我们来看看另一种方法因果推理。在Pearlian因果推理方法的核心是我们的变量之间的网络建设(这是“贝叶斯网络”)和所谓的“后门”变量组变量的定义。在下面的章节中,我将着重介绍这些概念,然后我们会看到它们是如何连接到因果推断。

3.1贝叶斯网络为I地图(地图独立)

贝叶斯网络的有向非循环图,表示节点之间的连接具有方向和有图内没有循环。这是一个图,表示在一组变量的独立性。在图G,与{X一世一世= 1,2,…,ñ}作为组变量,我们可以写出如下概率联合分布:

P (X_1、X_2……, X_n) = \prod_{i=1}^n P(X_i|pa_i)

其中p一个一世是指父X一世

图1所示。一个贝叶斯网络的例子。

让我们看一看图1,其中节点的父节点X1包括PA1= {X4X}。基于图1的图的联合分布可表示为:

P (X_1、X_2 X_3、X_4 X_5) = P (X_4) P (X_5) P (X_1 | X_4, X_5) P (X_3 | X_1) P (X_2 | X_1)

换句话说,就是图中的每个子-父家族G表示确定性函数:

X_i = f_i(pa_i, \epsilon隆_i) (i = 1,…,n)

其中∈一世(1≤一世ñ是相互独立的,任意分布的随机变量。

在图表中,连接两个变量的路径被称为路线;踪迹是活性时Xÿ并不是独立的给定了连接变量。如果没有一个直接的边缘之间Xÿ时,它们通过第三可变连接ž通过下列情况之一:

图2:图中三个连通变量的所有可能组合

A.间接因果作用(图2A):X→Z→ÿ这条古道是活动的当且仅当ž观察到的

B.间接证据效应(图2b)X←Z←ÿ这条古道是活动的当且仅当ž观察到的

C.常见的原因(图2C):X←Z→ÿ这条古道是活动的当且仅当ž观察到的

D.常见效果(图2d):X→Z←ÿ这条古道是,如果活跃且仅当ž或者一个ž的后裔观察

如图2所示,人们可以通过观察贝叶斯网络给定的观察到不同的变量之间的独立性和条件独立性。为了给更多的形式概念,了解沿途一些定义是很重要的。首先,我们必须了解“d分离。”这个概念将帮助我们找到更重要的变量,这将使目标和控制变量独立。

d分离:让X, Y,ž在三组中的节点G。我们说Xÿ为d分离给定ž如果任何节点之间没有活动的跟踪XXÿÿ特定Z。

接下来,我们需要定义“后门变量。”这个定义是非常重要的,我们将致力于全断面吧!

3.2后门变量

我们在前几节中讨论了协变量的重要性。在贝叶斯网络中,我们可以利用变量之间的联系来检测正确的协变量。以下定义是可用于干预计算的主要变量类型之一。

后门准则:[5]:一组变量ž满足相对于后门的标准有序对变量X一世XĴ在有向无环图中G如果:

(ⅰ)在没有节点ž是的后代X一世

(ⅱ)ž阻塞每一个活动路径之间X我,和XĴ通过X的父母一世

从[4]所取的图3的例子来解释后门标准。

作为3一个例子,在图中,变量的下列集合与用于套后门标准匹配X一世XĴ

ž1= {X1, X4}

ž2= {X1X3X4}

ž3= {X4X}

ž4= {X1X4X}

ž= {X1X3X4X}

ž6= {X2X4}

ž7= {X2X4X}

ž8= {X3X4}

ž9= {X1, X2, X3, X4}

ž10= {X3, X4X}

ž11= {X2X3X4}

ž12= {X2X3X4X}

ž13= {X1X2X4}

ž14= {X1X2X4X}

ž15= {X1X2X3X4X}


确定一组后门变量后,我们就可以很容易地计算干预。下面的定理提供的一切到底是怎样走到一起,并显示了后门变量的作用数学:

G-式定理:如果一组变量ž相对于满足后门准则(X,Y)然后

P(Y |做(X = x)= \ sum_z P(Y | X = X,Z = Z)P(Z = z)的

基本上,当我们确定后门变量,我们可以通过上面的等式(以下简称为式1)计算出的干预。稍后我会表明,我们只需要一组后门变量,以便计算干预。在我们拥有多套后门变量的情况下,答案是相同的,如果我们使用任何套。

那么,让我们在我们的伞形例子中应用Pearlian的微积分。贝叶斯网络大概是这样的:

图4。这是雨伞问题的图表。

变量Rain,是我们设置雨伞为控制的后门变量,事故为目标变量。看看公式1(当然,如果我们有实际的数据,我们可以肯定地回答),雨将是ž变量,伞将是X,而发生事故的概率是ÿ。我们不仅要知道,伞和事故是独立变量,以便p事故|将被完全解释p事故|)=p事故|因为事故|雨。

正如你所看到的,Pearlian做演算模型并检测正确的协变量,提高对潜在结果的方式提供了方法。但是,它仍然有其自身的挑战,我们将在我们的测试中探讨这些方法如下。

4.制作合成数据

现在我们了解了这两种常用方法的优缺点,让我们看看它们在实践中是如何发挥作用的。为了验证这些理论,首先,我需要创建一些合成数据。这种方法将帮助我控制输入的分布以及它们与系统输出的关系。我还可以为我想要测试的控制变量生成随机测试。因此,我可以得出推论与观察非常不同的数据;最重要的是,我将能够确切地知道我的控制变量的因果推论在多大程度上符合目标。

我使用了以下python包来制作本教程;大多数都是标准的python包。”causalgraphicalmodels”和“causalinference”是我用来寻找后门变量和计算各种潜在结果模型的两个特定的变量。

导入numpy作为np导入seaborn作为sns导入itertools导入状态模型。api是来自scipy的sm。stats导入norm导入causalgraphicalmodels作为cgm导入causalinference作为ci

注意:下面的函数必须添加到causalgraphicalmodels/example.py中

cie_example = StructuralCausalModel({ “Z1”:拉姆达N_SAMPLES次:np.random.normal(大小= N_SAMPLES次), “Z2”:拉姆达N_SAMPLES次:np.random.normal(大小= N_SAMPLES次), “Z8”:拉姆达N_SAMPLES次:NP。random.normal(大小= N_SAMPLES次), “Z9”:拉姆达N_SAMPLES次:np.random.binomial(1,p = 0.01,大小= N_SAMPLES次)* \ np.random.normal(大小= N_SAMPLES次)+ \ np.random。正常(LOC = 0.1,标度= 0.01,大小= N_SAMPLES次), “×”:logistic_model([ “Z1”, “Z 2”],[1,1]), “Z3”:linear_model([ “X”],[1]), “Y”:linear_model([ “Z3”, “Z5”, “Z9”],[3,-1,30]), “Z4”:linear_model([ “Z2”],[ -1]),"z5": linear_model(["z4"], [2]), "z6": linear_model(["y"], [0.7]), "z7": linear_model(["y", "z2"], [1.3, 2.1]) })

更新后的例子。pÿ,we have our data generator ready:

CIE = cgm.examples.cie_example cie_cgm = cie.cgm cie_cgm.draw()

图5。用于合成数据的贝叶斯网络。

数据= cie.sample(N_SAMPLES次= 100000)data.head()

表1中合成的数据的样本。

图5给出了表示变量之间联系的贝叶斯网络。表1只是显示了一个数据示例。我从图4所示的网络中采样了100,000次,相当于观察的行数。

为了模拟随机测试中,我们可以简单地使用相同的网络,并删除所有箭头进入节点X;即我们的曲线图中,的值X通过控制可变ž2但我们想随机改变的值X。因此,通过分离z之间的连接2X(除去z的效果2),我们可以给控制变量随机赋值X

cie_cgm.do( 'X')。绘制()

图6。贝叶斯网络的随机化检验。

如图6的上方示出,一个随机化试验的结构可以通过简单地移除所有的连接从所述变量(可以实现z1Z2),该控制变量x。

randomized_test =(CIE。做( 'X')。样品(N_SAMPLES次= 100000,函数set_values = { “×”:np.random.binomial(p值= 0.5,n = 1时,大小= 100000)}))
sns.distplot(randomized_test [randomized_test.x == 1] .y.clip(-25,30),标记= '处理')sns.distplot(数据[data.x == 1] .y.clip(-25,30),label='Observation for Treatment') sns.distplot(randomized_test[randomized_test.x==0].y.clip(-25, 30), label='Control') sns.distplot(data[data.x==0].y.clip(-25,30), label='Observation for Control') plt.ylabel('Probability Density') plt.legend()

y的图7的概率密度函数上的x∈{治疗= 1,对照= 0}空调两者随机化的测试和观察结果。

如图7所示,存在在变量中的隆起的微小差异X中观察和随机试验的结果。实际的差异可以计算如下:

ATE = randomized_test [randomized_test.x == 1] .y.mean() -  randomized_test [randomized_test.x == 0] .y.mean()ATE_obs =数据[data.x == 1] .y.mean()- 数据[data.x == 0] .y.mean()印刷(F “实际ATE:{ATE}”)打印(F “看ATE:{ATE_obs}”)

观察估计干预几乎50%的错误(48%)的值。在下面的章节中,我将使用各种技术来估算“实际ATE”只使用观测数据。

5.测试是可能的成果方法

因此,让我们把潜在后果理论测试。我们刚生成的数据,我们也愿意看到我们在多大程度上可以用这种方法去。如上面这个理论的描述中所述,可能的结果可以是一个非常有效的方法,如果一个人知道正确的协变量。我估计大多采用两种方法模型使用各种集协的潜在结果框架内ATE。第一盘我会尽量在我的数据现有的所有协变量。这种做法将表明,即使正确的协变量是选择变量的一个子集,估计还是会失败!

对于第二组,我会选择合适的协变量集。我会从Pearlian借用做这个做演算,并从后门变量集选择。在这个练习中,我试图表明,当协变量正确选择,在可能的结果建模的所有变化收敛到相同的解决方案。虽然这不能一概而论每一个问题,我想强调相比,制作更复杂的模型选择正确的协变量的重要性。

5.1。所有变量作为协变量

ZS =厘米= ci.CausalModel(Y = data.y.values,d = data.x.values,X =数据[ZS] .values [在data.columns如果c.startswith( “Z”)C为C])cm.est_via_ols() cm.est_via_matching() cm.est_propensity_s() cm.est_via_weighting() cm.stratify_s() cm.est_via_blocking() print(cm.estimates)
Y = [] yerr = [] X_LABEL = []为方法,结果在字典(cm.estimates).items():y.append(结果[ “吃”])yerr.append(结果[ “ate_se”])x_label.append(方法)X = np.arange(LEN(Y))plt.errorbar(X = X,Y = Y,yerr = yerr,线型= “无”,倾覆= 5,标记= “O”)PLT。Xticks(x, x_label) plt.title("Estimated Effect Size", fontsize=18) plt.hlines(ATE, -0.5, 3.5, linestyles="dashed") plt.xlim(-0.5,3.5);

图8.虚线示出的实际从一个随机测试ATE。

使用各种技术和协变量的所有变量示于图ATE的估计8。在此图中的虚线是实际值。结果清楚地表明如何没谱的估计,以及如何将这些结果时,我们引入了更多复杂的建模技术,我们的计算并没有显着改善。

5.2。ž2作为协变量

我将展示在下一节我们如何可以利用后门变量定义选择合适的协变量,但现在假设我奇迹般地选择ž2作为协变量。

注意:生成输出的代码基本相同,唯一的变化是必须替换变量“zs”,如下所示:

ZS = [ 'Z2']

图9.虚线示出的实际从一个随机测试ATE。

图9所示的结果证实了我们关于协变量的重要性与模型复杂性的假设。图表显示,实际的ATE值在我们试验的四种方法的估计范围内。在这种情况下,方法的复杂性(非线性)并没有增加任何价值的最终输出的准确性。

该试验表明,潜在的结果的方法是,其提供不同的方法来估计所述因果推断的有效技术。唯一的挑战是潜在的结果不选择正确的协提供了一个明确的指示。

6.测试Pearlian Do-Calculus方法

6.1。后门变量的列表

在可能的结果部分中,我们发现,正确地选择协变量是至关重要的一步。贝叶斯网络提供的工具和促进通过所谓的选择这一过程“后门的变量。”

参照第3.2节“causalgraphicalmodels”python中的包为给定图的一组控制目标变量提供后门变量列表。

cie_cgm。get_all_backdoor_adjustment_sets(“x”、“y”)

我提出的所有后门可变套以上;您可以使用这些作为一个练习来测试,如果你能找到相同的列表,或者至少可以找到每个组的理由。

如果我们从这个列表中选择任何一组,可能的结果可以正确地估计出ATE值(我仅用一组显示了这一点)。

6.2。用公式1计算当量

式。1(复制下面为方便起见)需要一组协变量的联合分布ž。我们还需要Pÿ|X=Xž=ž它基本上是一个映射的函数žXÿ

在我们的例子ž= {ž2}这年代将联合分布隐含为单一概率密度函数;我将制作两个OLS模型ž2分别为X= 0X= 1。

P(Y |做(X = x)= \ sum_z P(Y | X = X,Z = Z)P(Z = z)的

让我们第一OLS对空调的观测数据X= 1。

#该X_是协变量而X == 1 Z_ =数据[数据[X] == 1] [ 'Z2'] Y_ =数据[数据[X] == 1] [ 'Y']#添加恒定在为了在OLS Z_ = sm.add_constant(Z_)#拟合OLS模型y_x1_z = sm.OLS(Y_,Z_)y_x1_z_model = y_x1_z.fit截距()

我会为同样的OLSX= 0

Z_ =数据[data.x == 0] [ 'Z2'] Y_ =数据[data.x == 0] [ 'Y'] Z_ = sm.add_constant(Z_)y_x0_z = sm.OLS(Y_,Z_)y_x0_z_model = y_x0_z.fit()

为了估计Pž2),我假定与μ,从观察σ计算正态分布。当然,在更一般的情况下,应该算Pž)使用更复杂的技术。

亩=数据[Z] .mean()STD =数据[Z] .STD()Z_ =数据[Z] .values p_z =拉姆达Z:norm.pdf(Z,μ,STD)

所以我们已经准备好了所有的原料!让我们计算Pÿ|X=X))

#可能是更好的做法是估计在Y标准偏差为Z2的#功能。现在我假定在std不会改变从观察到#干预(其不是这种情况)y_std =数据[Y] .STD()DEF p_y_x_z(Z,Y,模型):返回norm.pdf(Y,模型.predict([1,Z]),INT(y_std))* p_z(z)的DEF p_y_dox(YS,X):如果x == 1:模型= y_x1_z_model elif的X == 0:模型= y_x0_z_model返回np.sum(v_p_z(z_, ys, model)) # np.vectorize helps me to pass a numpy array to a function that receives scalar v_p_z= np.vectorize(p_y_x_z) v_p_y_dox = np.vectorize(p_y_dox) # Because I'd like to calculate the whole density function of P(Y|do(x)) I have to # calculate the Eq(1) for different y. For calculating the ATE I don't need # to save all of these values. yy = np.linspace(-20, 30, 60) py_dox1 = v_p_y_dox(yy, x=1) py_dox0 = v_p_y_dox(yy, x=0)

通过使用ž2作为协变量:

图10的处理和控制的效果的概率分布的使用估计ž2作为协变量。

通过使用ž作为协变量:

图11的处理和控制的效果的概率分布的使用估计ž作为协变量。

有图10和图11所示第一重要的两点,选择正确的协可以估计不仅ATT或ATC,而且它可以预测推断整个概率分布。其次,我们使用了两种完全不同的变量集并尽可能他们适合后门变量标准的结果是一样的。

6.3。学习贝叶斯网络结构

到目前为止,正如我们所看到的相对于潜在的结果的方法,做演算方法提供了一个强大的工具,以找到估算干预的相对协变量。现在的问题是它会如何难以估计的网络架构,这对寻找的“后门”或“前门”变量关键的一步。幸运的是,为了这个目的已经创造了许多结构性的学习算法。提供这些重要的工具了深刻的检讨是不幸的是此博客的范围。因此,我想显示中的R现有的包称为的一个例子bnlearn已经实现大部分的这些算法有效,是开源的,它是比较容易使用。bob网下载

在Python包相当于被称为pgmpy,在此包中,不过网络学习模块比在bnlearn慢得多。所以,现在我将尝试表明,技术上有可能使用bnlearn观测数据获取网络。

#ryp2有助于在python运行R模块从rpy2.robjects.packages导入importr进口rpy2.robjects.packages作为rpackages导入rpy2#导入bnlean bnlearn = rpackages.importr( 'bnlearn')readr = rpackages.importr( 'readr')#导入我们在前面一节中生成的为csv dtrain = readr.read_csv数据(“data.csv”)#爬山是一种用于结构学习的最常见算法DAG = bnlearn.hc(dtrain)打印(DAG)

贝叶斯网络通过基于分数的方法学:

模型:

[Z9] [Z8] [Z2] [Z1] [Z4 | Z2] [X | Z2:Z1] [Z5 | Z4] [Z3 | X] [Y | Z9:Z5:Z3] [Z6 | Y] [Z7| Z2:Y]

节点:12

弧线:11

无向弧:0

向弧:11

平均马尔科夫毯尺寸:2.67

邻域平均尺寸:1.83

平均分支系数:0.92

学习算法:爬山

得分:BIC(高斯)。

惩罚系数:5.756463

学习过程中使用的测试:187

优化:TRUE

在这个例子中,bnlearn成功地学习了结构,即使我们的数据包括离散和连续变量,这在技术上被称为混合网络。

结论

在这个博客中,我试图展示因果推理计算的内在挑战,它最终依赖于找到正确的协变量。潜在结果方法为计算因果推论提供了更好的工具,但它没有提供一个合适的路径来找到正确的协变量集。另一方面,Pearlian do-calculus方法可以(至少在我们的示例中)提供正确的工具来估计正确的变量集,但是在确定图的结构方面存在挑战。

一个假设我已经是我们测得的或我们的数据,这是情况并非总是如此之内观察到的混杂变量。我将奉献我的下一个博客的地方,我们还没有观察到的混杂变量,必须先接近它因果推理的情况估计。

参考文献

  1. 赖兴巴赫,汉斯。时间的方向。卷。加州大学出版社,1956年65大学。
  2. Peters, Jonas, Dominik Janzing和Bernhard Scholkopf。因果推理的要素:基础和学习算法。麻省理工学院出版社,2017年。
  3. 鲁宾,D. B.(2005)。因果推断使用可能的结果:设计,建模,决策。杂志美国统计协会100(469),322-331。
  4. 巴尔,伊恩。Python因果推理http://www.degeneratestate.org/posts/2018/Mar/24/causal-inference-with-python-part-1-potential-outcomes/
  5. 珠儿,j .(1995)。因果图用于实证研究。Biometrika82(4),669-688。