城市里每一条地铁线路,都要经过交通规划局的评审打分。审批官手里有一张固定的评估表:这条线路经过哪些站、站与站之间挨不挨着、有没有换乘枢纽、全程跑完要多少预算。至于列车具体是顺时针开还是逆时针开、先到哪一站——评估表上一律不作区分。也就是说,两个只把行车方向整体掉头的方案,审批分数会一模一样。 这听起来有点不可思议,但恰恰是“基于分数的因果发现”里一个躲不开的核心性质——评分等价性(score equivalence)。在 AI 世界里,我们常想从一堆观测数据里猜出变量之间的因果方向(是 X 导致了 Y,还是 Y 导致了 X?),最常见的思路就是给每个候选因果图打分,然后挑分数最高的。可评分等价性告诉我们:有些结构不同的图,只是因为箭头方向整体反转,打出来的分数居然完全相同——就像同一批站点、同一种连通关系的地铁,只是行车方向相反,审批分数完全一样。 这篇文章就带你在“地铁评估表”的比喻里,看懂评分等价性从哪来、会带来什么麻烦、又该怎么绕过它。

岗位关联

搞懂评分等价性,你就能在因果发现中精准定位“方向盲区”,知道何时该相信分数、何时必须靠 V 结构或实验来定方向——这是从“会跑代码”到“读懂结果”的关键一步。

目录
  1. 可视化演示
  2. 核心概念:评分函数与因子分解
  3. 马尔可夫等价:同样的骨架,不同的跑法
  4. 评分等价原理:为什么分数必然打平
  5. 关键算法:GES 的加加减减
  6. 等价类区分:V 结构与干预实验
  7. 性能优化:只算变化的部分
  8. 实践应用:从工具到业务决策
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示系统处理流水线、实时性能指标曲线及多方案对比分析,包含数据流转、吞吐延迟监控与方案评估。

本节配有交互动效(进入视口后自动加载,约 3KB)。

系统可视化 处理流程:输入→处理→模型→输出 性能监控:实时指标 P=L×T

核心概念:评分函数与因子分解

地铁规划局评审一条新线路,从来不是凭感觉拍板,而是用一张评估表给各种方案打总分。评估表上写得很清楚:这条线一路能拉来多少客流(数据拟合得好不好),以及沿途要盖多少站、维护多复杂(结构复杂度付出的代价)。总评分的算法并不神秘——就是“客流收益 + 建设维护成本调整”这两块拼起来。

放到因果发现里,这张“评估表”就是评分函数。给定了观测数据 D 和一个候选的因果图 G(也就是一个 DAG,节点是变量,边是因果方向),评分函数输出一个数值 Score(G:D),代表“这个图解释数据的能力”。一个关键的工程技巧是:总分可以被拆成每个变量的“家族分”之和。所谓家族,就是指某个变量和它的父节点们组成的一个小团体。每个小团体独立计分,最后统统加起来,得到全图的分数。

正因为评分可以“化整为零”,后续的因果发现算法才可能在局部做加减法来加速搜索。地铁规划局也是这么干的——评估人员逐站核算客流,最后汇总成全线的总流量,哪里要调整,只改那一站的数字就够了。

Score(G:D)=∑i=1ns(xi∣PaiG)\displaystyle \text{Score}(G:D)=\sum_{i=1}^{n} s(x_{i}\mid \text{Pa}_{i}^{G})
整个图的评分,等于每个变量“带着自己的父节点”单独计分后的总和。
  1. 变量总数与编号数据里有 n 个变量,下标 i 从 1 数到 n,逐个遍历每个变量。
    n=∣V∣\displaystyle n=|\mathcal{V}|
  2. 父节点集合表示在候选图 G 中,变量 x_i 的父节点构成的集合。
    PaiG={xj∣xj→xi∈G}\displaystyle \text{Pa}_{i}^{G}=\{x_{j}\mid x_{j}\to x_{i}\in G\}
  3. 局部家族分表示“给 x_i 及其爸爸们这个小团体”打的局部分数,包含似然项(拟合数据的程度)与结构项(模型复杂度的惩罚)。
    s(xi∣PaiG)=似然项+结构项\displaystyle s(x_{i}\mid \text{Pa}_{i}^{G})=\text{似然项}+\text{结构项}
  4. 求和符号把所有变量的局部分累加起来,构成整张图的最终分数。

马尔可夫等价:同样的骨架,不同的跑法

一条环形地铁线路上,同样的一批站点,可以设计出好几种跑法:顺时针跑、逆时针跑、甚至安排成对向发车。可在交通局审批官眼里,这些方案“停哪些站、站与站之间怎么连着”完全相同,只有车头朝向不同。换句话说,从一张静态的运行图里,你根本分辨不出列车实际往哪个方向开。

因果发现里也有同样的现象。假设我们考虑三个变量 X、Y、Z,两个图 G₁:X→Y→Z 与 G₂:X←Y←Z。它们的骨架——也就是把有向边涂掉方向后得到的无向边集合——完全一样,都是 X—Y—Z 这条链;而且它们都没有V 结构(指的是某个节点同时拥有两个彼此不相连的父节点,像一个“汇合枢纽”)。骨架相同、V 结构相同,我们就说这两个 DAG 属于同一个马尔可夫等价类。观测数据给出的概率分布,最多只能把我们引导到等价类这一层,类内谁是谁的方向,分布本身“不置一词”。

技术上的定义可以这样表述:两个 DAG 是马尔可夫等价的,当且仅当它们拥有相同的骨架和相同的 V 结构集合。这是整个评分等价性讨论的地基。地铁审批官按“站点连通关系 + 换乘枢纽”来评估线路,等价类里的线路在他眼里就是“同一个方案的不同跑法”;同理,概率分布按“条件独立关系”来刻画变量系统,等价类里的图在分布眼里就是“同一个故事的不同讲法”。

  • 骨架识别:忽略边的方向,只看变量两两之间有没有边相连。
  • V 结构识别:找出所有形如 x→y←z、且 x 与 z 之间没有边的汇合点。
  • 等价类:共享同一骨架与同一 V 结构集合的全部 DAG 组成的集合。
  • 方向模糊:等价类内部边的方向无法由观测分布决定,这就是“方向盲区”。

所以,当你在论文或工具输出里看到“该数据对应一个等价类,而非唯一因果图”,别惊讶——这正是分布本身能承诺的极限。

评分等价原理:为什么分数必然打平

既然交通局审批表上只统计“站间联通关系和换乘枢纽”,压根不看车头朝向,那么同一等价类里方向相反的线路,最终评估分数理所当然会一模一样。这不是巧合,而是评分函数在设计之初就被写进纸面里的性质,叫作朝向不变性。

贝叶斯评分家族里,BDeu 和 BGe 分数是两支主力。它们都不是“拿最大似然值估一个数”那么简单,而是对参数做边际化——把所有可能的参数取值都积分掉,得到“这个图结构本身解释数据的概率”。正是这个积分过程,让等价类内方向相反的图分数精确相等。写成 BDeu 的完整表达式,它长这样:

从公式可以直观看到:评分只依赖“谁是谁的父节点”的集合,而不依赖父节点之间的排列方向。因此只要两个图的骨架和 V 结构相同,父节点集合逐变量对应相等,分数必然相同。这个性质在文献里称作分数一致性——在样本量足够大时,真图所在的等价类会拿到最高分;也正因如此,GES 这类算法找回来的不是“唯一真图”,而是一个“分数最高的等价类”。

P(D∣G)=∏i=1n∏j=1qiΓ(αij)Γ(αij+Nij)∏k=1riΓ(αijk+Nijk)Γ(αijk)\displaystyle P(D\mid G)=\prod_{i=1}^{n}\prod_{j=1}^{q_{i}}\frac{\Gamma(\alpha_{ij})}{\Gamma(\alpha_{ij}+N_{ij})}\prod_{k=1}^{r_{i}}\frac{\Gamma(\alpha_{ijk}+N_{ijk})}{\Gamma(\alpha_{ijk})}
BDeu 分数把每个变量按“父节点的每种取值组合”分块,对每块数据做狄利克雷积分,最终得到结构 G 的边际似然。
  1. 外层连乘遍历变量对图中每一个变量都计入一个因子,一个都不能少。
    ∏i=1n(⋯ )\displaystyle \prod_{i=1}^{n}(\cdots)
  2. 中层连乘遍历父节点组合q_i 表示变量 x_i 的父节点取值一共有多少种组合,对每种组合单独统计。
    qi=∏xj∈PaiGrj\displaystyle q_{i}=\prod_{x_{j}\in\text{Pa}_{i}^{G}} r_{j}
  3. 内层连乘遍历取值r_i 表示 x_i 自身有几种取值(比如二值变量 r_i=2),对每个取值 k 算一个伽马积分。
    ri=∣dom(xi)∣\displaystyle r_{i}=|\text{dom}(x_{i})|
  4. 计数与先验N_{ijk} 是数据中“父组合为 j、x_i 取值为 k”的样本数;α_{ijk} 是狄利克雷先验的伪计数,α_{ij} 是它们的和。
    αij=∑k=1riαijk,Nij=∑k=1riNijk\displaystyle \alpha_{ij}=\sum_{k=1}^{r_{i}}\alpha_{ijk},\quad N_{ij}=\sum_{k=1}^{r_{i}}N_{ijk}
  5. 伽马函数积分Γ 函数在这里的作用是把先验伪计数与观测计数“柔和地合并”,等价于对所有可能的参数 θ 做积分后得到的归一化常数。

关键算法:GES 的加加减减

线路方案的数量是天文数字——每加一条边、每改变一个方向,都可能衍生出上亿种排列。地铁规划师当然不会把每条线路都全量评估一遍。他的做法是“小步快跑”:从一个空方案开始,每轮只做一个小改动,比如给某两站之间新增一条联络线,或把某段线路取消;只要改动后总分变高,就接受这个改动,然后继续往下试探。等分数再也涨不动了,再反过来做删减,直到收敛。

这就是 GES(Greedy Equivalence Search,贪婪等价搜索) 算法的思想。它分为两个阶段:第一阶段是前向加边,不断往图里加边,只要局部增量是正的;第二阶段是后向删边,不断删掉冗余边,仍然只看局部增量。每一步的决策依据,是下面这个增量公式:

GES 的可贵之处在于它不直接搜索“具体哪条边指向哪边”,而是在等价类的层面做操作。因为评分等价性保证了等价类内所有图同分,算法只需要找到“哪个等价类分数最高”即可,最后再根据骨架和 V 结构把方向信息呈现出来。这就像规划师不需要纠结列车顺时针还是逆时针跑——只要确定哪组站点连通关系客流最大,方向问题留给实地调研去解决。

Δi,j=s(xi∣Pai∪{xj})−s(xi∣Pai)\displaystyle \Delta_{i,j}=s\bigl(x_{i}\mid \text{Pa}_{i}\cup\{x_{j}\}\bigr)-s\bigl(x_{i}\mid \text{Pa}_{i}\bigr)
把变量 x_j 加入 x_i 的父集合后,家族分的提升量;若 Δ 为正,说明这条加边值得保留。
  1. 当前父集合表示在现有候选图中,x_i 已经有的父节点们。
    Pai\displaystyle \text{Pa}_{i}
  2. 加入候选父节点后的家族分把 x_j 临时放进 x_i 的父集合,重新算一次 x_i 的局部评分。
    s(xi∣Pai∪{xj})\displaystyle s\bigl(x_{i}\mid \text{Pa}_{i}\cup\{x_{j}\}\bigr)
  3. 原家族分保持现状不动时 x_i 的局部评分。
    s(xi∣Pai)\displaystyle s\bigl(x_{i}\mid \text{Pa}_{i}\bigr)
  4. 增量判定Δ>0 说明加边让总分上升,贪心策略接受;否则跳过这条候选边。

等价类区分:V 结构与干预实验

分数打平之后,方向到底藏在哪里?交通局有两种破局手段。第一种是盯住换乘枢纽站:枢纽站的客流模式很特殊——两条支线的客流在这里汇合再疏散,这种“汇聚”结构能在运行图上直接看出方向。第二种是实地调研:派人去站台蹲点,看列车从哪个方向进站、哪个方向出站,真相一目了然。

对应到因果发现,第一种手段就是活用 V 结构。形如 x→y←z 的结构里,y 是汇合点,x 和 z 都是 y 的父节点,而且 x 与 z 之间不能有边。V 结构的特殊性在于:它本身不依赖于分布等价性就能被识别——在观测数据中,x 与 z 通常独立(或条件独立于 y 以外的变量),但给定 y 之后二者会变得相关。这个 “给定中间变量后反而相关” 的信号,直接锁定了 y 是汇合点。第二种手段是干预实验——也就是 do 算子。对变量 X 施加干预(强制它取某个值),相当于物理上切断了所有指向 X 的边,这时观察 Y 的分布变化,就能确认 X 是否真的影响 Y。后门调整公式给出了从观测数据模拟干预效果的途径:

除了 V 结构和干预实验,PC 算法也能帮上忙:它先做条件独立性检验恢复骨架,再利用 V 结构锚定部分方向,最后通过方向传播规则(Meek 规则)把能确定的方向尽量推断出来。剩下的“顽固边”,就只能交给领域先验知识或真实实验去拍板了——这和交通局最后那步实地调研,逻辑完全一致。

P(y∣do(X=x))=∑zP(y∣X=x,Z=z) P(Z=z)\displaystyle P\bigl(y\mid \text{do}(X=x)\bigr)=\sum_{z} P\bigl(y\mid X=x,Z=z\bigr)\,P(Z=z)
在满足后门准则的调整集 Z 上做加权平均,就能用观测数据估算干预后的分布,从而打破等价类的方向模糊。
  1. 干预记号do(X=x) 表示人为强制 X 取值为 x,与普通的“观测到 X=x”意义完全不同。
    do(X=x)\displaystyle \text{do}(X=x)
  2. 调整集Z 是满足后门准则的一组协变量,它阻断了 X 与 Y 之间所有非因果路径。
    Z: 阻断了X→Y的所有后门路径\displaystyle Z:\ \text{阻断了} X\to Y \text{的所有后门路径}
  3. 加权平均对 Z 的每一个取值,用条件概率 P(y|X=x,Z=z) 乘以 P(Z=z),再求和,得到干预后的边际分布。

性能优化:只算变化的部分

现在想象一座拥有上百个站点的大城市,规划师要评估的线路方案数以万计。如果他每做一个微调,就把整条线所有站的客流全部重新盘一遍,那算到退休也算不完。聪明的做法是:微调只影响局部——比如只是给 A 站和 B 站之间加一条联络线,那么只有 A、B 两站及其邻近站的客流估算会变化,其他 98 个站的数据完全可以“缓存”起来不动。

因果发现算法的性能瓶颈与此完全相同。GES 每轮都要评估大量候选操作,如果每个操作都全图重新算一次评分,代价是灾难性的。因此工程实现中普遍采用三类优化。其一是分数缓存:把每个变量在当前父集合下的局部分存起来,下次遇到相同组合直接命中复用。其二是局部更新:加边、删边、转边只影响相关变量的家族分,只有这些变量需要重算。其三是并行计算:不同变量的局部分彼此独立,天然可以分到多个线程或机器上同时算。至于近似搜索,则是当候选操作太多时,用随机采样或剪枝策略挑选一部分高潜力操作评估,牺牲少量精度换取数量级的加速。候选操作的数量级可以这样估计:

这些优化手法在 Tetrad、causal-learn、gCastle 等开源库中都有成熟实现。你只需要理解:评分等价性带来的计算负担,并不是“每张图都要从头算”,而是“可以拆着算、缓存着算、并行着算”——就像交通局把整座城市的客流评估拆成各站独立核算,最后汇总一加。

∣候选操作∣≈O ⁣(n2rmax⁡)\displaystyle |\text{候选操作}|\approx O\!\left(n^{2}r_{\max}\right)
每轮要评估的候选操作数大致和变量数平方成正比,还受最大状态数影响,这就是必须做局部更新和缓存的原因。
  1. 变量平方项n² 来自“任意两个变量之间加边、删边、转边”的组合数。
    n2=(n2)×2+(n2)\displaystyle n^{2}=\binom{n}{2}\times 2+\binom{n}{2}
  2. 最大状态数r_max 是单个变量取值数量的上界,关系到父节点组合的枚举量。
    rmax⁡=max⁡iri\displaystyle r_{\max}=\max_{i} r_{i}

实践应用:从工具到业务决策

回到真实世界。假设你是一名数据科学家,手里拿到一份电商平台的用户行为观测数据,想搞清楚“商品曝光→点击→购买”这条链路上真实的因果方向。用因果发现工具跑一遍 GES,输出结果很可能是“一个等价类,而不是一张唯一的 DAG”——链条中间的方向标记着“待定”。这时候评分等价性就不再是课本概念,而是直接影响你业务结论的约束条件。

实践中的标准流程是这样的:先确认数据是观测数据还是实验数据。如果是观测数据,你只能拿到等价类级别的结论;下一步立刻检查图里有没有 V 结构——比如“是否点击→是否购买←是否收到优惠券”这样的汇合点,V 结构能帮你锚定一部分方向;再下一步,对关键边引入领域先验(比如“曝光一定发生在点击之前”这种业务常识)或者部署一个小规模 A/B 实验,用真实干预数据定方向。工具层面,causal-learn 提供 GES 的 Python 实现,Tetrad 适合交互式探索,gCastle 集成了评分函数和多种搜索策略。常见的坑包括:把等价类内的某个方向当成铁律、在存在隐藏混杂变量时仍然相信评分结果、以及把非平稳时间序列数据当独立同分布样本处理。理解了评分等价性,你就能一眼识别这些歧义,并把有限的实验资源花在真正需要定方向的边上——这正是“读懂因果结果”与“只会跑因果代码”的分水岭。

AI 应用场景

医疗因果发现:疾病与症状的等价类分析

阶段:因果发现 + 结果解释

解决的问题:电子病历通常是观测数据,“高血压→心脏病”与“心脏病→高血压”这类链式结构方向难辨。传统做法直接看相关性或回归系数,容易把方向搞反;用评分等价性校准期望后,GES 先锁定等价类,再借助 V 结构(如“高血压→脑卒中←糖尿病”)锚定局部方向,剩余边通过孟德尔随机化(一种近似干预的遗传学方法)定方向。

具体案例:某三甲医院团队分析 5 万份慢病随访数据,用 GES 得到等价类后,发现“血压异常与肾功能指标”之间方向模糊;通过一个已知的 V 结构锚定部分路径,再对关键边做孟德尔随机化,最终确认肾小球滤过率下降早于血压异常,修正了此前病历系统的规则引擎。

推荐系统:曝光、点击与购买的因果链路

阶段:基于分数的因果发现 + 在线实验验证

解决的问题:推荐系统中“曝光→点击→购买”是典型的链式结构,观测日志无法区分“曝光导致购买”还是“购买意愿高的人更容易被曝光”。传统点击率预估模型只看相关性,上线 A/B 实验成本高。先用 GES 在历史日志上找出等价类,再对等价类内模糊的边做定向 A/B 实验,能节省 70% 的实验资源。

具体案例:某电商平台用评分等价性分析后,发现“加购”与“购买”间的方向可被一个 V 结构(“加购←收藏夹使用量→购买”)锚定,而“曝光”与“点击”方向仍模糊;团队只在曝光→点击这一条边上做了两周分流实验,就明确了因果方向,随后把规则引擎升级为因果感知的排序模型。

工业根因分析:故障日志中的因果链路

阶段:因果发现 + 根因定位

解决的问题:设备故障日志里,“温度升高”与“负载增大”常同时出现,运维人员难以判断谁是根因。传统告警系统用相关性做关联分析,误报率高。用 GES 对传感器序列做因果发现,评分等价性提示方向模糊,再结合 V 结构和控制变量实验定方向,可显著降低误报。

具体案例:某工厂对 200 台设备的传感器数据跑 GES,发现“电流异常→电机过热←冷却泵故障”这个 V 结构直接锁定冷却泵为辅因;而“电流异常”与“转速下降”方向模糊,工程师通过一次主动停机实验确认了因果方向,将根因定位时间从 2 小时缩短到 20 分钟。

Python 演示

python87 行
"""BDeu score equivalence demo: flipping non-V edges keeps the score."""import math import networkx as nximport numpy as np  class BDeuScorer:    """BDeu additive scorer with Dirichlet prior alpha."""     def __init__(self, alpha=1.0):        self.alpha = alpha     def _dirichlet_log(self, counts):        """Log marginal likelihood of one Dirichlet-multinomial block."""        k = len(counts)        alp = self.alpha        n = int(counts.sum())        s = math.lgamma(alp * k) - math.lgamma(alp * k + n)        for c in counts:            s += math.lgamma(alp + c) - math.lgamma(alp)        return s     def local_score(self, data, var, parents):        """BDeu local score of var given parents on boolean data."""        x = data[:, var]        if not parents:            counts = np.array([                int(np.sum(x == 0)),                int(np.sum(x == 1))            ])            return self._dirichlet_log(counts)        keys = np.zeros(data.shape[0], dtype=int)        for j, pa in enumerate(parents):            keys = keys * 2 + data[:, pa].astype(int)        total = 0.0        for u in np.unique(keys):            mask = keys == u            counts = np.array([                int(np.sum(x[mask] == 0)),                int(np.sum(x[mask] == 1))            ])            total += self._dirichlet_log(counts)        return total     def score(self, data, graph):        """Additive score over all nodes of the DAG."""        total = 0.0        for var in sorted(graph.nodes):            parents = list(graph.predecessors(var))            total += self.local_score(data, var, parents)        return total  def generate_chain_data(n_samples=2000, seed=7):    """Data generated from X -> Y -> Z with strong conditionals."""    rng = np.random.default_rng(seed)    x = rng.binomial(1, 0.5, n_samples)    y = np.where(x == 1,                 rng.binomial(1, 0.8, n_samples),                 rng.binomial(1, 0.2, n_samples))    z = np.where(y == 1,                 rng.binomial(1, 0.8, n_samples),                 rng.binomial(1, 0.2, n_samples))    return np.column_stack([x, y, z])  def main():    data = generate_chain_data()    scorer = BDeuScorer(alpha=1.0)    g_forward = nx.DiGraph([(0, 1), (1, 2)])    g_backward = nx.DiGraph([(1, 0), (2, 1)])    g_v = nx.DiGraph([(0, 1), (2, 1)])     s1 = scorer.score(data, g_forward)    s2 = scorer.score(data, g_backward)    s3 = scorer.score(data, g_v)     print("Score of X->Y->Z : %.4f" % s1)    print("Score of X<-Y<-Z : %.4f" % s2)    print("Score of X->Y<-Z : %.4f" % s3)    print("Reversed chain scores equal :", abs(s1 - s2) < 1e-6)    print("V-structure score distinct  :", abs(s1 - s3) > 1e-3)  if __name__ == "__main__":    main()
目的:实现 BDeu 评分函数,验证“把链式结构的边全部翻转,评分不变;换成 V 结构,评分明显改变”这一评分等价性核心性质。
  1. total += self.local_score(data, var, parents)把每个变量的家族分累加为整图分数,体现了评分函数的可分解性。
  2. keys = keys * 2 + data[:, pa]把多个父变量的取值编码成唯一整数组合,方便分组统计各状态的样本量。
  3. np.where(x == 1, ...)用条件概率生成 X→Y→Z 的链式合成数据,保证真实因果链条已知。
  4. abs(s1 - s2) < 1e-6判断分数是否相等时用容差而非 ==,规避浮点累计误差。

常见误区

误区我刚跑完 GES,发现好几个图的分数一模一样,是不是所有因果图评分都相同?那还怎么选出最优结构?

正解不是所有图,只有属于同一个马尔可夫等价类的图才会打平——即骨架相同且 V 结构相同。换入一个 V 结构,分数立刻产生明显差异。这就像地铁审批表只认站间关系,同样的十个站连成环,顺时针和逆时针跑法当然同分;但如果把其中一个站改成换乘枢纽,整个审批结果完全不一样。

为何常见:初学者通常从链式结构这一个例子出发,看到“方向翻转分数不变”就过度外推,忽略了 V 结构作为等价类“分水岭”的地位。

误区我用某个评分库算出来 A→B 的分数比 B→A 高,那 A 导致 B 是不是就实锤了?

正解如果 A→B 与 B→A 属于同一等价类(两个变量之间只有一条边时最常见),评分等价性保证它们的分数精确相等,不存在谁高谁低。你看到的“差异”要么是数值误差,要么是用了不满足等价性的启发式分数。真正的方向锚点来自 V 结构、干预实验或领域先验,而不是分数本身。

为何常见:人天然倾向于“数字大 = 更重要”,但评分函数恰恰被设计成对方向不敏感,这是它与普通分类准确率最大的不同。

误区评分等价只是小样本下的巧合吧?我把样本量从 1 万加到 1 亿,总能分出因果方向了吧?

正解评分等价性是渐近性质,样本量趋于无穷依然成立。只要数据来自完整观测、分数满足一致性,等价类内的分数在极限下完全相同。增加样本只会让分数更稳定地“打平”,不会让方向浮出水面——这就像给地铁审批表增加再多的客流统计,也统计不出列车方向。

为何常见:很多统计直觉来自参数估计——样本多,误差小。但这里不是噪声问题,而是模型不可识别性问题,前提条件就不满足。

误区我在图里找到了一个 V 结构,这下整张因果图的方向应该全部定下来了吧?

正解V 结构只能锚定它自身的汇合结构——x→y←z 中 y 的父节点是确定的。其余边的方向仍可能在你未观测的等价类内翻转,需要通过 PC 算法或 Meek 方向传播规则逐步推导:能定的才定,定不了的继续保持“方向未知”。链式结构中远离 V 结构的边,方向往往仍然模糊。

为何常见:把“局部锚定”误当成“全局定向”,忽略了方向传播规则只能从已确定方向逐步外推,推不动的边依然属于等价类。

面试题

Q1. 评分等价性的核心含义是什么?

单选题 · easy

  • A.所有因果图的最终评分都相同
  • B.马尔可夫等价的图分数相同← 正确答案
  • C.分数最高的图一定是真实因果图
  • D.V 结构不影响最终的评分

答案:B。评分等价性说的是:当两个 DAG 骨架相同且 V 结构相同时(属于同一马尔可夫等价类),评分函数给出相同分数。选项 A 过度推广,C 违背等价类精神(分数只选类不选方向),D 与事实相反——V 结构恰恰是区分等价类、改变分数的关键。

Q2. 两个 DAG 属于同一个马尔可夫等价类,需要满足什么条件?

单选题 · easy

  • A.骨架相同且 V 结构相同← 正确答案
  • B.只需要骨架完全相同
  • C.变量取值个数必须相同
  • D.必须有相同数量的边数

答案:A。马尔可夫等价的充要条件是“相同骨架 + 相同 V 结构集合”。只看骨架不够,因为没有 V 结构时方向仍可翻转。变量取值个数与边数不是等价类的定义条件。这就像地铁线路必须“站间连通关系 + 换乘枢纽结构”都一致,才算同一评价档次。

Q3. BDeu 分数中的超参数 α 在贝叶斯网络评分中代表什么?

单选题 · mid

  • A.每个节点允许的最大父节点数
  • B.狄利克雷先验的等效样本量← 正确答案
  • C.数据集的总样本量大小
  • D.图的最大入度约束值

答案:B。α 是狄利克雷先验的等效样本量,它决定了先验的强度——α 越大,先验对评分的影响越重。它不是结构约束(A、D),也不是观测样本量(C)。可以把 α 理解为审批官的“历史经验权重”:经验越足,新数据对分数的撼动越小。

Q4. 链式结构 X→Y→Z 翻转所有边得到 X←Y←Z,评分等价性告诉我们什么?

单选题 · mid

  • A.翻转后分数显著更低
  • B.翻转后分数显著更高
  • C.两者分数保持相同← 正确答案
  • D.翻转后无法用 BDeu 评分

答案:C。X→Y→Z 与 X←Y←Z 骨架相同(X—Y—Z)且都没有 V 结构,属于同一等价类。BDeu 等评分等价性分数在类内精确相同,分数不会一高一低,更不会无法评分。这就是“环形线路顺时针逆时针同分”的典型场景。

Q5. 以下哪些 DAG 属于同一个马尔可夫等价类(变量 X、Y、Z)?

多选题 · mid

  • A.X→Y→Z← 正确答案
  • B.X←Y←Z← 正确答案
  • C.X→Y←Z
  • D.X←Y→Z← 正确答案

答案:ABD。A、B、D 的骨架都是 X—Y—Z 这条链,且都不含 V 结构,属于同一等价类。C 的骨架同为 X—Y—Z,但存在 V 结构 X→Y←Z(Y 是汇合点),属于另一个等价类。骨架相同但 V 结构不同,分数也不会相同——如同换乘枢纽的改变会改变审批结果。

Q6. GES 算法两个阶段的正确顺序是?

单选题 · mid

  • A.先做等价类翻转再做加边
  • B.先删边后加边
  • C.先加边后删边← 正确答案
  • D.随机并行加删

答案:C。GES 第一阶段 forward 从空图出发贪心加边,直到分数不再提升;第二阶段 backward 贪心删边,直到分数不再提升。顺序固定为“先加后删”。这对应地铁规划师先大胆扩充方案、再精简冗余线路的两步走策略。

Q7. 在没有任何干预实验的前提下,仅凭观测数据的评分,哪些边的方向可以被可靠确定?

单选题 · extreme

  • A.链式结构中所有边的方向
  • B.V 结构汇合点的父边方向← 正确答案
  • C.任意等价类之外的边方向
  • D.融合大规模样本后的方向

答案:B。V 结构 x→y←z 在纯观测数据下是可识别的——“给定 y 后 x 与 z 反而相关”这一分布特征直接锁定汇合点,无需干预。链式结构(A)的方向在等价类内模糊,加大样本(D)也无法打破评分等价性。“等价类之外”的说法本身就不成立(C)。

Q8. 以下哪项是打破马尔可夫等价类内方向模糊的最可靠手段?

单选题 · hard

  • A.设计干预实验直接干预变量← 正确答案
  • B.增加 BDeu 先验等效样本量
  • C.换成 BIC 惩罚分数
  • D.对数据做标准化预处理

答案:A。干预实验(do 算子)物理切断了指向目标变量的边,能直接观测因果效应,是打破方向模糊的黄金标准。调整先验(B)、更换惩罚分数(C)、标准化数据(D)都无法改变“观测分布对应等价类”的数学事实——就像给审批表加再多细则,也看不出来列车实际往哪开。

Q9. 评分等价性给因果发现带来了哪些影响?

多选题 · hard

  • A.单独依赖分数无法确定边的方向← 正确答案
  • B.等价类内无需再做任何区分
  • C.需要 V 结构或实验才能打破方向模糊← 正确答案
  • D.BDe 分数不适用于因果发现

答案:AC。评分等价性意味着等价类内方向不可由分数区分(A 正确),V 结构与干预实验是破局关键(C 正确)。B 错误——等价类内仍需通过 V 结构、领域先验做进一步定向。D 错误——BDe 家族恰恰是最主流的评分函数之一,它的适用性不受等价性影响。

Q10. 实践中处理评分等价性带来的方向模糊,常用做法包括?

多选题 · hard

  • A.利用 V 结构确定局部方向← 正确答案
  • B.使用 PC 算法骨架信息辅助← 正确答案
  • C.引入领域先验知识限制方向← 正确答案
  • D.直接取分数差异最大的方向

答案:ABC。V 结构提供局部锚点(A),PC 算法用条件独立性检验和方向传播规则扩展可定向范围(B),领域先验补充业务常识(C),三者都是工程上常用的破局手段。D 错误——评分等价性保证等价类内分数相同,“分数差异最大的方向”并不存在,硬取只会得到数值噪声。