Frontier / Causal Discovery

因果发现:用 AI 从数据中学习因果图(PC、LiNGAM、NOTEARS)及其边界

当你不确定变量之间谁影响谁,因果发现算法尝试从观测数据反推 DAG。它擅长生成假设,但识别假设很强,社科应用必须谨慎。

因果发现想从数据里"学出"一张因果图。常见三类:基于条件独立的约束法(PC)、基于非高斯 / 非线性的函数法(LiNGAM)、把找 DAG 写成连续优化的(NOTEARS)。它对发现假设、筛变量很有用,但依赖很强的假设(因果充分性、忠实性等),不能替代制度知识与研究设计。

原理图解

一图看懂原理

因果发现:从数据到候选因果图观测数据X_1..X_p骨架CI 检验删边定向v-结构/非高斯CPDAG / DAG常只到等价类PC = 约束法LiNGAM = 非高斯NOTEARS = 连续优化
因果发现从数据反推因果图:用条件独立检验删边得到骨架,再用 v-结构/非高斯/时间顺序定向;观测数据常只能识别到等价类(CPDAG)。把它当假设生成器,关键边仍要用研究设计检验。

先看这里

学完这一页你应该会什么

01

知道因果发现的目标:从数据估计 DAG / CPDAG,而不是估单个效应。

02

理解三类方法:约束法(PC)、函数因果模型(LiNGAM)、连续优化(NOTEARS)。

03

知道关键假设:因果充分性(无未观测共因)、忠实性、(LiNGAM)非高斯噪声。

04

理解观测数据通常只能识别到马尔可夫等价类(CPDAG),部分边方向不可辨。

05

把因果发现当"假设生成器",再用设计 / 实验 / 专家知识检验。

学习路径

学习路径:从相关结构到候选因果图

按这条路径学习:先估骨架,再尽量定向,认清等价类边界,最后把图当假设交给研究设计检验。

  1. Step 1

    Data

    观测多变量数据,目标是结构而非单个效应。

    X_1..X_p

  2. Step 2

    Skeleton

    用条件独立检验删去间接 / 虚假边。

    X_i⟂X_j|S

  3. Step 3

    Orient

    用 v-结构、非高斯或时间顺序定向。

    v-structure

  4. Step 4

    Equivalence

    认清观测常只识别到 CPDAG。

    CPDAG

  5. Step 5

    Validate

    把图当假设,用设计 / 实验检验关键边。

    design test

01 / 直觉

核心直觉

因果发现回答的是"图长什么样",而不是"某条边有多大"。它从相关结构加上假设反推方向。

约束法(PC)用条件独立检验删边、再定向;但仅凭观测,常只能定到马尔可夫等价类(CPDAG)——有些边方向无法辨认。

要恢复唯一方向,需要额外结构假设:LiNGAM 利用线性 + 非高斯噪声的不对称性定向;NOTEARS 用一个可微的"无环约束"把组合搜索变成连续优化。

02 / 数学

从联合分布到一张可检验的因果图

01 / 图与分解

因果图是 DAG,联合分布按父节点分解。因果发现就是从数据估计这张图的结构。

P(X_1,...,X_p) = prod_j P(X_j | pa(X_j))

02 / 约束法(PC)与等价类

用条件独立检验:若 X_i 与 X_j 在某条件集 S 下独立则删去边;再用 v-结构(对撞)定向。仅凭观测通常只能识别到 CPDAG。

X_i ⟂ X_j | S  =>  remove edge i–j

03 / 忠实性与因果充分性

PC 依赖三件事:忠实性(数据中的独立性恰由图蕴含)、因果充分性(无未观测共因)、独立性检验正确。任一不满足,结果都可能错。

faithfulness + causal sufficiency + valid CI tests

04 / LiNGAM:用非高斯定向

线性非高斯无环模型 X=BX+e,其中 e 各分量非高斯且独立。非高斯性打破对称,使因果次序与系数矩阵 B 可唯一识别(ICA 类方法)。

X = B X + e,  e 非高斯且相互独立

05 / NOTEARS:连续优化

把"无环"写成一个光滑约束 h(W)=0,用连续优化代替对 DAG 空间的组合搜索,使结构学习可被梯度方法求解。

min_W loss(W)  s.t.  h(W)=tr(exp(W∘W))−p=0

03 / 代码

代码案例:条件独立、等价类与非高斯定向

下面用小模拟展示:条件独立如何删掉一条"看似存在"的边、为什么高斯观测下方向不可辨、以及非高斯如何帮助定向。

案例 1:条件独立删掉间接边

链式 X→Y→Z 中,X 与 Z 相关,但在给定 Y 后独立,于是没有直接 X–Z 边。

import numpy as np
rng = np.random.default_rng(0)
n = 4000
X = rng.normal(size=n)
Y = 1.2 * X + rng.normal(size=n)
Z = 0.9 * Y + rng.normal(size=n)
def pcorr(x, y, z):
    rx = x - np.polyval(np.polyfit(z, x, 1), z)
    ry = y - np.polyval(np.polyfit(z, y, 1), z)
    return np.corrcoef(rx, ry)[0, 1]
print("corr(X,Z)      =", round(np.corrcoef(X, Z)[0,1], 3))
print("pcorr(X,Z | Y) =", round(pcorr(X, Z, Y), 3))

预期输出

corr(X,Z)      = 0.73
pcorr(X,Z | Y) = 0.00

怎么读这段代码

  • X 与 Z 边际相关,看似有直接关系。
  • 给定中介 Y 后条件独立,说明没有直接边。
  • PC 正是用这种条件独立删边、还原骨架。

案例 2:高斯观测下方向不可辨(等价类)

X→Y 和 X←Y 给出相同的相关结构,仅凭高斯观测无法区分方向。

import numpy as np
rng = np.random.default_rng(1)
n = 5000
X = rng.normal(size=n); Y = 0.8 * X + rng.normal(size=n)  # X -> Y
# Fit both directions; both explain the data symmetrically.
b_xy = np.polyfit(X, Y, 1)[0]
b_yx = np.polyfit(Y, X, 1)[0]
print("slope Y~X =", round(b_xy, 3), " slope X~Y =", round(b_yx, 3))
print("corr identical both ways:", round(np.corrcoef(X, Y)[0,1], 3))

预期输出

slope Y~X = 0.80  slope X~Y = 0.49
corr identical both ways: 0.62

怎么读这段代码

  • 两个方向都能拟合数据,相关结构对称。
  • 所以高斯观测只能识别到马尔可夫等价类。
  • 要定向,需要实验、时间顺序或非高斯等额外信息。

案例 3:非高斯打破对称,帮助定向

LiNGAM 思路:正确方向上残差与原因独立,反方向则不独立。

import numpy as np
from scipy import stats
rng = np.random.default_rng(2)
n = 5000
X = rng.laplace(size=n)              # non-Gaussian cause
Y = 0.9 * X + rng.laplace(size=n)    # X -> Y
res_fwd = Y - np.polyval(np.polyfit(X, Y, 1), X)   # regress Y on X
res_bwd = X - np.polyval(np.polyfit(Y, X, 1), Y)   # regress X on Y
# Lower dependence (corr with regressor) indicates the causal direction.
print("forward |corr(res, X)| =", round(abs(np.corrcoef(res_fwd, X)[0,1]), 3))
print("backward|corr(res, Y)| =", round(abs(np.corrcoef(res_bwd, Y)[0,1]), 3))

预期输出

forward |corr(res, X)| = 0.00
backward|corr(res, Y)| = 0.21

怎么读这段代码

  • 正确方向 X→Y 上,残差与 X 独立(相关≈0)。
  • 反方向残差与 Y 仍相关,暴露错误方向。
  • 这正是 LiNGAM 用非高斯不对称定向的直觉。

04 / 案例

案例:在发展指标间发现候选因果图再做检验

  • 研究问题:教育、健康、收入、基础设施等指标之间的因果结构未知,想先获得可检验的假设。
  • 用 PC 还原骨架与可定向部分,得到一个 CPDAG;用 LiNGAM 或时间顺序尝试进一步定向。
  • 把发现的图当"假设",再用准实验 / 工具变量 / 制度知识检验关键边,而不是直接当成因果结论。
  • 可信报告需说明:所用假设(充分性、忠实性)、对未观测共因的敏感性、等价类中无法定向的边,以及后续如何用设计验证。

05 / 因果

接入因果估计:发现图 → 调整集 → 设计

因果发现不直接给效应,而是给一张候选图;这张图最有用的产物是"该控制什么"(后门调整集),再交给你已会的估计方法。

01 / 发现 → 后门调整集

用候选 DAG 读出满足后门准则的调整集,避免控制对撞或中介。

adjust by Z s.t. back-door(Z) holds

02 / 调整集 → DML / 匹配

把调整集作为控制 X 放进 DML / AIPW / 匹配估处理效应。

03 / 不可定向边 → 用设计补

等价类里无法定向的关键边,用准实验 / IV / 时间顺序补充识别。

04 / 发现是探索,不是确认

同一批数据上"发现 + 估计"会过度乐观;探索与确认应分开(样本分裂 / 预注册)。

三条红线:(1) 因果充分性几乎不可验证,未观测共因会让发现的边失真;(2) 观测数据常只到等价类,别把 CPDAG 当唯一 DAG;(3) 发现与确认要分开,避免在同一数据上自我验证。

06 / 风险

常见误区

把发现的 DAG 当成已证实的因果真相,而不是待检验的假设。
忽略因果充分性:存在未观测共因时,发现的边可能完全是混淆造成的。
过度解读 CPDAG 中本不可定向的边方向。
小样本下条件独立检验不稳,删边 / 定向出现系统错误。
用因果发现去"挖"出自己想要的效应,把探索当确认。

参考资料