计算反事实#

通过计算反事实,我们回答以下问题

我观察到变量 \(X\) 被设定为值 \(x\) 时,变量 \(Z\) 的某个结果为 \(z\)。如果我对 \(X\) 进行干预,将其设定为不同的值 \(x'\),那么 \(Z\) 的值会变成什么?

作为一个具体示例,我们可以设想以下情况

我的低密度脂蛋白胆固醇 (LDL)水平异常偏高 (\(Z = 10\))。最近几个月我没有服用任何药物 (\(x = 0\))。如果我每天服用 5 克药物 (\(X := 5\)),我的低密度脂蛋白胆固醇水平 (\(Z\)) 会发生什么变化?

请注意,基于 Pearl 图形因果模型框架的反事实估计需要比干预样本生成更强的假设(详情请参阅理解方法章节)。

如何使用#

为了了解如何使用此方法,我们生成一些数据

>>> import networkx as nx, numpy as np, pandas as pd
>>> from dowhy import gcm
>>> X = np.random.uniform(low=0, high=10, size=2000)
>>> Y = -2*X + np.random.normal(loc=0, scale=5, size=2000)
>>> Z = 3*Y + 80 + np.random.normal(loc=0, scale=5, size=2000)
>>> training_data = pd.DataFrame(data=dict(X=X, Y=Y, Z=Z))

如果我们考虑胆固醇的例子,这里的 \(Y\) 可以被认为是某种影响低密度脂蛋白胆固醇水平的身体测量值,例如身体吸收药物能力或其代谢的衍生物。

接下来,我们将建模因果关系并将模型拟合到数据。估计反事实需要一个可逆的 SCM,并且可以由加性噪声模型表示。

>>> causal_model = gcm.InvertibleStructuralCausalModel(nx.DiGraph([('X', 'Y'), ('Y', 'Z')])) # X -> Y -> Z
>>> gcm.auto.assign_causal_mechanisms(causal_model, training_data)
>>> gcm.fit(causal_model, training_data)

假设我们观察到的值是 \(x=0, y=5, z=110\)。我们想知道服用药物(例如,设定 \(x:=5\))是否会导致 \(z\) 的值变小。在这种情况下 \(z\) 的反事实值可以通过以下方式估计

>>> gcm.counterfactual_samples(
>>>     causal_model,
>>>     {'X': lambda x: 5},
>>>     observed_data=pd.DataFrame(data=dict(X=[0], Y=[5], Z=[110])))
   X         Y         Z
0  5 -4.82026  80.62051

正如我们所见,\(X\) 取了我们的处理/干预值 5,而 \(Y\)\(Z\) 则取了基于我们训练过的因果模型和固定观测值的确定性值。例如,如果 \(X\) 是 0,\(Y\) 是 5,根据数据生成过程,我们预期 \(Z\) 会是 95。然而,我们观测到 \(Z\) 是 110,表明在这个特定样本中存在大约 ~15 的噪声值。有了这个隐藏噪声因子的知识,我们可以估计如果将 \(X\) 设为 5 时 \(Z\) 的反事实值,结果如上所示,约为 ~80。

我们也可以直接将这些噪声值提供给函数

>>> gcm.counterfactual_samples(
>>>     causal_model,
>>>     {'X': lambda x: 5},
>>>     noise_data=pd.DataFrame(data=dict(X=[0], Y=[5], Z=[15])))
   X         Y         Z
0  5 -4.845684  80.431559

正如我们所见,当 \(X\) 设为 5,且 \(y = -2 \cdot x + 5 = -5\) 时,\(z\) 应该约为 ~65。但我们知道 \(Z\) 的隐藏噪声约为 ~15。因此反事实结果再次是 \(z = 3*y + 80 + 15 = 80\)

需要注意的是,我们获得估计值并不完全精确,正如结果中所示,因为模型参数未能完美学习。特别是,正如数据生成过程所示,学习到的 \(Y\)\(Z\) 的系数并非精确的 -2 和 3。像机器学习中常见的情况一样,更多数据或对模型进行微调有助于提高准确性。

理解方法#

图形因果模型中的反事实与模拟干预的影响非常相似,但有一个重要的区别:执行干预时,我们展望未来;而对于反事实,我们回溯到另一个可能的过去。为了在计算中体现这一点,在执行干预时,我们首先为特定的观测值重新创建所有噪声值,然后估计反事实结果。然而,这比生成干预样本需要更强的建模假设。

回想一下,节点 \(Y\) 的因果机制表示为 \(Y := f(X, N)\),其中 \(X\)\(Y\) 的父节点,\(N\) 是噪声。为了生成 \(Y\) 的干预样本,我们可以从 \(N\) 中取任何随机值,但对于反事实,我们需要首先(基于模型)重构导致我们观察到的特定噪声值。这要求因果机制相对于 \(N\) 是可逆的,尽管它不需要相对于 \(X\) 可逆。确保这一点的常见建模假设是加性噪声模型,形式为 \(Y := f(X) + N\),其中噪声可以通过 \(N = Y - f(X)\) 重构。请注意,目前反事实估计仅支持连续数据,而生成干预样本对数据类型没有限制。

为了进一步阐明噪声在此处的作用,我们回顾引言中关于高水平低密度脂蛋白胆固醇的例子。鉴于存在许多无法观测的因素可能影响胆固醇水平,例如运动和遗传,问题来了:如果我服用了药物,我的低密度脂蛋白水平会降低吗?为了回答这个问题,我们可以使用干预方法,其中我们保持个体特有的未观测因素(即噪声)不变,只改变假设服用的药物剂量。在实践中,这可以通过先重构噪声,然后使用该特定值来估计干预药物剂量后的低密度脂蛋白水平来实现。这里关键在于使用重构的噪声值,而不是从噪声分布中随机采样。否则,观察到的低密度脂蛋白水平降低可能并非因为药物本身,而是因为碰巧生成了一个导致低水平的噪声值。假设建模假设大致正确,我们就可以分析在反事实情景下药物是否会有帮助。

注意

关于可逆机制的备注:通常,相对于 \(N\) 可逆的机制允许我们估计点反事实。但是,也可能允许某些机制不可逆。在这种情况下,我们将获得基于观测证据的反事实分布,这不一定是点估计。