想象你是一家米其林餐厅的神秘顾问。主厨辞职了,厨房只剩一堆顾客评价记录——哪道菜甜了、哪道菜咸了、哪道菜让客人皱眉。你需要在没有任何配方的情况下,反推出每道菜用了哪些食材、先放什么后放什么。这不是魔术,而是“因果发现”:从观测数据中还原变量之间的因果结构。而GES算法,就是你用来推断菜谱的推理引擎。 但GES不是一个凭空猜测的侦探。它手里握着一张“品鉴评分表”——每次推测出一个候选菜谱,都要用这张表打分:既要看“这份配方能否解释客人的反馈”(拟合数据),又要看“配方是否简单到其他厨师能复刻”(控制复杂度)。这张评分表,就是BIC评分函数(贝叶斯信息准则)。BIC像一把刻度的尺子,告诉GES每一步该往哪个方向走、该不该停。 本文会带你彻底拆解GES是如何用BIC完成这次“寻味之旅”的:从因果发现的任务设定,到贪婪搜索的框架,再到BIC评分的数学细节,以及它如何引导加边与删边,最终在庞大的结构空间中精准找到最可信的那份“菜谱”。

岗位关联

掌握GES与BIC,你就握住了评分式因果发现的主流钥匙。无论做基因调控网络推断、电商因果归因,还是故障根因定位,“评分引导搜索”这套方法论都是你直接可复用的核心武器。

目录
  1. 可视化演示
  2. 因果发现任务
  3. GES搜索框架
  4. BIC评分原理
  5. 评分引导机制
  6. 搜索流程细节
  7. 等价类处理
  8. 方法优劣评价
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

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

BIC评分 = 拟合优度 - 复杂度惩罚 BIC总分 拟合优度(对数似然) 复杂度惩罚(λ·d)模型复杂度 (参数数量)BIC评分BIC = ln(n)·k - 2·ln(L̂) | k=参数数,n=样本量,L̂=最大似然值BIC总分 拟合优度(对数似然) 复杂度惩罚(λ·d)

因果发现任务

主厨要反推菜谱,但他面对的不是一张白纸,而是堆成山的顾客评价单。每张单子上记录着“这道菜用了哪些食材、客人反馈如何”——却唯独没有写烹饪步骤。主厨的目标很朴素:找出一个“配方蓝图”,让每个味道特征都能被更基础的食材选择所解释。在统计学里,这个“配方蓝图”叫作有向无环图(DAG):每个节点是一个变量,每条有向边表示一个变量直接影响另一个变量。

因果发现(Causal Discovery)要解决的,正是从纯粹的观测数据中学习这样一张DAG。它不要求你去做随机实验,而是从成千上万条“顾客评价单”中反复比对:当食材A出现时,味道B是否系统性地跟着变化?当同时控制住食材C的影响后,A与B的关联是否消失?这些规律被编码成一张图,而图背后隐含着一个重要假设——联合分布可以被分解成每个变量在给定其父节点条件下的乘积。

这道分解式是整个因果发现大厦的地基。它告诉我们:只要找到每个变量“真正的父节点”,整张图的联合分布就能被完整刻画。剩下的问题只有一个——如何从浩瀚的候选图中找到这组父节点?这就需要一个聪明的“试菜过程”。

P(X1,X2,…,Xm)=∏i=1mP(Xi∣Pa(Xi))P(X_1, X_2, \dots, X_m) = \prod_{i=1}^{m} P\bigl(X_i \mid \text{Pa}(X_i)\bigr)
  1. 联合分布等式左边是所有变量共同出现的概率,也就是整份“菜谱”的味道全貌。
    P(X1,X2,…,Xm)P(X_1, X_2, \dots, X_m)
  2. 连乘积分解右边表示把整个菜谱拆成一道道“局部配方”相乘,每个变量只依赖它的直接原因。
    ∏i=1m\prod_{i=1}^{m}
  3. 父节点条件$\text{Pa}(X_i)$ 是 $X_i$ 在DAG中的直接父节点集合,即“直接影响它的那些食材”。
    P(Xi∣Pa(Xi))P\bigl(X_i \mid \text{Pa}(X_i)\bigr)

GES搜索框架

既然要找的菜谱可能有无穷多种配方组合,主厨不可能把所有配方都试一遍。聪明的做法是:从一份最简单的“白水煮菜”开始,每次只调整一种食材——加一味、换一味、撤一味,然后立刻请品鉴团打分,保留让分数上升的改动。这就是贪婪搜索的基本精神:每次只做局部最优的调整,一步步爬向更高的评分。

GES,全称贪婪等价搜索(Greedy Equivalence Search),正是把这种“试菜直觉”搬到了因果图上。它的独特之处在于,搜索的并不是所有DAG组成的空间,而是“等价类空间”。什么是等价类?想象两份配方——先加糖后加醋、先加醋后加糖——最后端出来的菜味道完全一样。对顾客来说,这两份配方是“不可区分的”;对统计模型来说,它们的联合分布也完全相同、评分一模一样。这样的DAG归为一类,称为马尔可夫等价类。

与其在成千上万个“味道相同”的DAG之间反复横跳,GES干脆只在一个等价类的“代表”上做文章。每次加边或删边,都自动在等价类层面更新代表图,搜索效率大幅提升。这一步设计的关键在于:在等价类空间里,每一类只需要评估一次评分,而不是对每个同类的DAG分别打分。

BIC评分原理

现在评分表登场。主厨的品鉴表上写着这样一行字:“得分 = 美味程度 − 复杂度罚分”。一道菜做得再好吃,如果配方要用五十种食材、每一步都很玄学、没人能复刻,也很难拿到高分;反之,一道菜简单到只有盐和胡椒,却平淡无奇,同样不合格。BIC评分函数(贝叶斯信息准则)就是这张品鉴表的数学化身。

BIC由两部分组成。第一部分是极大对数似然 $\hat{\ell}(\hat{\theta})$,它衡量当前DAG对应的概率模型在数据上的拟合程度——“这份配方解释顾客反馈的能力”;第二部分是复杂度惩罚项 $-\frac{d}{2}\ln N$,其中 $d$ 是模型自由参数个数、$N$ 是样本量。每多一条边,通常意味着条件概率表里多出若干参数,惩罚随之增大。BIC就像一位挑剔的美食评论家:既要求味道精准,又要求配方简洁。

有了这张评分表,GES的每一步试菜都变得有据可依。但BIC只给出了“打分规则”,真正的搜索还需要一个决策机制来决定每一步该动哪条边——这就是下一节的“评分引导”。

BIC(G)  =  ∑i=1m∑xi,πin(xi,πi)ln⁡θ^xi∣πi⏟对数似然 ℓ^(θ^)  −  d2ln⁡N\text{BIC}(G) \;=\; \underbrace{\sum_{i=1}^{m}\sum_{x_i,\pi_i} n(x_i,\pi_i)\ln \hat{\theta}_{x_i\mid\pi_i}}_{\text{对数似然}\,\hat{\ell}(\hat{\theta})} \;-\; \frac{d}{2}\ln N
  1. 对数似然项$n(x_i,\pi_i)$ 是数据中“父节点取值为 $\pi_i$ 且 $X_i$ 取值为 $x_i$”的样本计数,$\ln\hat{\theta}_{x_i\mid\pi_i}$ 是该条件下估计概率的对数。两者相乘再求和,就是对模型拟合能力的量化打分。
    ∑i=1m∑xi,πin(xi,πi)ln⁡θ^xi∣πi\sum_{i=1}^{m}\sum_{x_i,\pi_i} n(x_i,\pi_i)\ln \hat{\theta}_{x_i\mid\pi_i}
  2. 复杂度惩罚项$d$ 是全部条件概率表中需要独立估计的参数个数,$\ln N$ 是样本量的自然对数。参数越多、样本越大,这一项扣分越狠,防止模型无限复杂。
    d2ln⁡N\frac{d}{2}\ln N
  3. 评分合成用拟合项减去惩罚项。一个优秀的因果图必须同时满足“拟合充分”与“结构简洁”,这正是BIC引导搜索的底层逻辑。
    BIC(G)=ℓ^(θ^)−d2ln⁡N\text{BIC}(G) = \hat{\ell}(\hat{\theta}) - \frac{d}{2}\ln N

评分引导机制

品鉴团评分之后,主厨要做的事很朴素:比较改动前后的分数差。如果加一味蒜让菜从82分涨到85分,这步改动就值得保留;如果加了之后反而掉到79分,就立刻撤回。这个分数差,记作 $\Delta\text{BIC}$,正是GES导航仪的“油门踏板”。

在数学上,GES每次考虑一个候选操作(比如添加 $X\to Y$ 这条边),都计算新图的BIC减去旧图的BIC。注意一个巧妙之处:因为BIC可以按节点分解,一条边只影响目标节点的局部得分,所以增量计算只需重算受影响的局部项,代价很小。当增量为正时,说明这次改动的“拟合收益”超过了“复杂度代价”;当增量为负时,说明这条边纯属画蛇添足。

GES在每一步都会枚举所有合法的单边操作,计算各自的 $\Delta\text{BIC}$,然后贪婪地选择增量最大(且为正)的那个执行。这就像主厨把十种候选调味方案摆上桌,逐一让品鉴团试吃打分,只选得分涨幅最大的那一款。局部决策虽然只看眼前一步,却在宏观上形成了一条持续上升的搜索轨迹。

ΔBIC  =  BIC(G′)−BIC(G)  =  [ℓ^(θ^′)−ℓ^(θ^)]−d′−d2ln⁡N\Delta\text{BIC} \;=\; \text{BIC}(G') - \text{BIC}(G) \;=\; \Bigl[\hat{\ell}(\hat{\theta}') - \hat{\ell}(\hat{\theta})\Bigr] - \frac{d' - d}{2}\ln N
  1. 评分差分$\text{BIC}(G')$ 是新候选图的评分,$\text{BIC}(G)$ 是当前图的评分,两者之差决定了这一步的“投资回报率”。
    BIC(G′)−BIC(G)\text{BIC}(G') - \text{BIC}(G)
  2. 拟合增益方括号内 $\hat{\ell}(\hat{\theta}') - \hat{\ell}(\hat{\theta})$ 表示新图比旧图多解释了多少数据信息。通常加边后拟合不会变差,这个差值非负。
    [ℓ^(θ^′)−ℓ^(θ^)]\Bigl[\hat{\ell}(\hat{\theta}') - \hat{\ell}(\hat{\theta})\Bigr]
  3. 复杂度代价$\frac{d' - d}{2}\ln N$ 是参数个数变化带来的惩罚增量。一条多余的边带来的拟合提升如果不足以抵消这项代价,$\Delta\text{BIC}$ 就会为负。
    d′−d2ln⁡N\frac{d' - d}{2}\ln N

搜索流程细节

主厨的试菜节奏分为两个截然不同的阶段。第一阶段叫“大胆加料”:他几乎不加节制地尝试往菜里加各种食材——只要能提升品鉴分就保留,直到再怎么加分数都不动了。第二阶段叫“冷静收尾”:他开始审视已经加进去的食材,果断删掉那些贡献微薄、纯属增加配方复杂度的配料,直到再删任何一样都会掉分。GES的完整搜索过程,正是这两个阶段的精确复刻。

前向阶段(Forward Phase)从空图出发,反复执行“添加一条边、计算 $\Delta\text{BIC}$”的循环:如果存在让评分上升的加边操作,就选增益最大者执行;当所有合法加边都无法再提升评分时,前向阶段停止。后向阶段(Backward Phase)则反过来,尝试删除已有边,同样每一步选择增益最大的删边操作,直到任何删边都无法提升评分。两个阶段都收敛时,GES输出当前等价类作为最终结果。

为什么先加后删而不是一步到位?因为前向阶段容易被“边太多”误导——某些边单独看有增益,组合在一起却互相冗余。后向阶段正是用来清洗这些冗余的:它允许GES在评分丘陵上更从容地移动,最终停在BIC的局部(理想情况下是全局)最优点。这套“先加法后减法”的节奏,与主厨先大胆试味、再精简配方的职业习惯如出一辙。

text8 行
G ← 空图(等价类表示)# 前向阶段:贪婪添加边while 存在合法加边使 ΔBIC > 0:    选 ΔBIC 最大的加边操作执行# 后向阶段:贪婪删除边while 存在合法删边使 ΔBIC > 0:    选 ΔBIC 最大的删边操作执行return G

等价类处理

主厨发现了一个耐人寻味的现象:他试出了两份配方,一份先炒糖再下鸡翅,一份先煎鸡翅再淋糖汁,端上桌客人完全吃不出差别。他意识到,自己没必要在“哪份配方更正统”上浪费时间——反正它们的味道(分布)一模一样。这就是马尔可夫等价类的精髓:两个DAG如果拥有相同的骨架和相同的V结构,它们表达的联合分布完全一致,互为等价类成员。

骨架是忽略方向后的无向图;V结构是指 $X\to Z\leftarrow Y$ 这种“两个变量同时指向一个共同后代、且它们之间没有边”的局部模式。对因果发现来说,等价类内的方向差异属于“数据无法告诉你”的信息。GES因此聪明地选择在等价类空间中搜索:搜索的每一步都以CPDAG(部分有向无环图)为代表——方向在所有等价类成员中一致的边画实线箭头,方向不一致的边保留为无向线段。

这个设计带来两个红利。第一,搜索空间大幅缩小:原本要在指数级的DAG群中挑挑拣拣,现在只在一类一类的“配方组”中穿行;第二,评分更加稳健:既然同类配方评分相同,GES就不会因为随机选择某个成员而在评分上产生无意义波动。最终输出的CPDAG如实告诉使用者:“这些边的方向数据已经确定,那些边的方向还需要领域知识或干预实验来裁定。”

方法优劣评价

回看主厨的整套方法论,它既让人惊喜,也暗藏风险。惊喜在于效率:主厨没有把世界上的所有配方都试一遍,而是靠“每次局部最优”的贪心策略快速逼近一个高分方案,这在菜谱空间极其庞大时几乎是唯一可行的路;样本充足、数据满足忠实性假设时,GES还有漂亮的渐进一致性——样本越多,越能收敛到真实的因果等价类。

风险同样不容忽视。贪心搜索的本质决定了它可能止步于局部最优:某一步的边删除虽然单独看会掉分,却可能为后续更强的结构调整铺路——但贪心策略永远不会迈出那“暂时的倒退”。此外,GES的统计保证依赖几个关键假设:数据忠实于真实图(没有额外的条件独立巧合)、不存在隐藏的混杂变量、样本量足够大。现实数据中这些假设常常被违背,输出图也就只能视为“候选菜谱”而非金科玉律。

不过瑕不掩瑜。在众多因果发现算法中,GES凭借“评分+贪心”这一组合,在可扩展性与准确性之间取得了极佳的平衡,成为评分式因果发现的标杆。PC等约束式方法依赖独立性检验的误差累积,而GES把一切统一到BIC这把评分尺上,决策更连贯、结果更可解释。理解了这套框架,你就掌握了因果发现的主流思维范式。

AI 应用场景

基因调控网络重建

阶段:因果结构学习

解决的问题:传统生物实验逐个基因敲除成本极高、周期漫长。AI通过BIC评分从基因表达数据中重建调控网络,自动识别“哪些基因影响哪些基因”的结构,把候选实验范围从数万个基因对缩小到最有希望的几条调控边。

具体案例:给定几千个单细胞的转录组表达谱,GES算法以BIC评分为引导搜索基因间的有向调控图。输出的CPDAG中,方向确定的边可以直接作为下游湿实验的靶点候选,帮助团队大幅节省实验经费。

电商用户行为因果归因

阶段:归因分析与策略决策

解决的问题:运营团队常见的困惑是“看了广告的用户购买率高,但广告真的促进购买吗?”只靠相关性分析会被选择偏差误导。用GES对浏览、加购、领券、购买等行为变量搜索因果结构,能找出真实的转化路径。

具体案例:某电商平台用GES对用户行为日志建模,BIC引导搜索发现“领券→加购→购买”是一条稳定的因果链,而“广告曝光→购买”的直接边消失,说明广告只起间接作用。运营据此调整投放策略,把预算更多配置在领券环节,转化率提升约18%。

分布式系统故障根因定位

阶段:异常传播链推断

解决的问题:微服务架构中一个服务抖动会沿调用链传染,日志里满是相关告警,难以区分谁是根源。GES从各服务的监控指标时间序列中学习异常传播的有向图,BIC自动剔除冗余的“伪因果边”。

具体案例:某互联网公司把服务延迟、错误率、QPS波动等时序指标离散化后,用GES重建故障传播图。在一次大规模报警中,算法输出的根因服务与人工排查结果一致,平均定位时间从40分钟压缩到3分钟。

Python 演示

python117 行
import numpy as np  def _group_counts(sub):    """统计子矩阵各取值组合的出现次数,返回字典映射"""    uniq, counts = np.unique(sub, axis=0, return_counts=True)    return {tuple(row): c for row, c in zip(uniq, counts)}  class BICScorer:    """BIC评分器:对任意父集组合计算局部BIC得分"""     def __init__(self, data):        self.data = data        self.n, self.m = data.shape        self.states = [len(np.unique(data[:, j])) for j in range(self.m)]        self.cache = {}     def local_ll(self, var, parents):        """对数似然:sum n(x,pa) * log(n(x,pa) / n(pa))"""        joint = _group_counts(self.data[:, list(parents) + [var]])        if parents:            pa_map = _group_counts(self.data[:, list(parents)])        else:            pa_map = {(): self.n}        ll = 0.0        for key, c in joint.items():            pa_key = key[:-1]            ll += c * np.log(c / pa_map[pa_key])        return ll     def num_params(self, var, parents):        """自由参数个数 = 父组合数 * (状态数 - 1)"""        if parents:            pa_count = len(_group_counts(self.data[:, list(parents)]))        else:            pa_count = 1        return pa_count * (self.states[var] - 1)     def local_bic(self, var, parents):        """BIC局部得分 = 对数似然 - (参数个数/2) * ln(N)"""        key = (var, tuple(parents))        if key not in self.cache:            ll = self.local_ll(var, parents)            d = self.num_params(var, parents)            self.cache[key] = ll - (d / 2) * np.log(self.n)        return self.cache[key]     def total_bic(self, parents):        """整图BIC = 各节点局部得分之和"""        return sum(self.local_bic(v, parents[v]) for v in range(self.m))  def has_path(parents, start, target):    """判断有向图中start能否沿有向边到达target"""    children = [[] for _ in range(len(parents))]    for v, ps in enumerate(parents):        for p in ps:            children[p].append(v)    stack = [start]    seen = set()    while stack:        cur = stack.pop()        if cur == target:            return True        if cur in seen:            continue        seen.add(cur)        stack.extend(children[cur])    return False  def greedy_search(data):    """贪心加边搜索:每次选择令BIC提升最大的合法操作"""    scorer = BICScorer(data)    m = data.shape[1]    parents = [[] for _ in range(m)]    score = scorer.total_bic(parents)     for _ in range(30):        best_delta = 1e-12        best_cand = None        for x in range(m):            for y in range(m):                if x == y or x in parents[y] or y in parents[x]:                    continue                if has_path(parents, y, x):                    continue                cand = [p[:] for p in parents]                cand[y].append(x)                delta = scorer.total_bic(cand) - score                if delta > best_delta:                    best_delta = delta                    best_cand = cand        if best_cand is None:            break        parents = best_cand        score += best_delta    return parents, score  if __name__ == '__main__':    np.random.seed(42)    n = 5000    x0 = np.random.binomial(1, 0.5, n)    p1 = np.clip(0.5 + 0.3 * x0, 0.05, 0.95)    x1 = np.random.binomial(1, p1)    p2 = np.clip(0.1 + 0.3 * x0 + 0.4 * x1, 0.05, 0.95)    x2 = np.random.binomial(1, p2)    x3 = np.random.binomial(1, 0.3, n)    data = np.column_stack([x0, x1, x2, x3])     parents, score = greedy_search(data)    names = ['X0', 'X1', 'X2', 'X3']    for v in range(4):        pa = [names[p] for p in parents[v]]        print(names[v] + ' 的父节点: ' + (', '.join(pa) if pa else '无'))
目的:从模拟的因果数据中,用贪心加边 + BIC评分还原每个变量的父节点,输出学习到的因果结构。
  1. class BICScorer:评分器封装了BIC的全部数学逻辑:局部对数似然、参数计数、局部得分缓存。
  2. joint = _group_counts(self.data[:, list(parents) + [var]])统计“父组合+变量取值”的联合计数,这是计算对数似然的第一手素材。
  3. ll += c * np.log(c / pa_map[pa_key])累加每个父组合下的条件对数似然,实现BIC的拟合优度项。
  4. return sum(self.local_bic(v, parents[v]) for v in range(self.m))整图BIC等于各节点局部得分之和,这是GES能快速评估边操作增量的结构基础。
  5. def has_path(parents, start, target):环检测工具:若加边 x→y 前,y已经能到达x,则新边必然成环,该操作非法。
  6. delta = scorer.total_bic(cand) - score计算候选操作的 ΔBIC 增量,这是GES每一步决策的导航仪表。
  7. if delta > best_delta: best_delta = delta; best_cand = cand贪婪选择:在所有合法加边操作中挑出评分增益最大者。

常见误区

误区既然GES用BIC引导搜索,那最终输出的BIC最高的图,它的每一条有向边都应该揭示了真正的因果方向,比如X→Y而不是Y→X。

正解BIC评估的是图对数据分布的拟合程度与模型简洁度,它并不具备“判断因果方向”的魔法。对于同一马尔可夫等价类内的图——比如只有X→Y和Y→X两个节点的单边图——两者的BIC评分完全相同,因为它们的条件独立集合和参数个数完全一致。GES输出的CPDAG里那些无向边,正是“数据无法裁决方向”的诚实记录。要确定方向,还得靠干预实验或额外的领域知识。

为何常见:我们天然把“评分最高”等同于“因果方向最正确”,忽略了观测数据本身对因果方向的可识别性限制——这是因果推断中最容易踩的思维陷阱。

误区GES每一步都选择ΔBIC最大的操作,看起来每一步都在变好,最后应该能得到全局最优的因果图吧?

正解贪心策略只保证“每一步局部最优”,不保证“最终结果全局最优”。搜索空间里可能藏着这样的地形:先允许一步评分下降的改动,为后续更大的评分提升铺路——但贪心算法永远不会主动迈出那步“倒退”。GES的理论一致性是渐进意义上的:样本量趋于无穷且数据满足忠实性时,它才收敛到真实等价类;有限样本下,它完全可能停在某个局部最优点。

为何常见:把“贪心+评分引导”误当成“暴力遍历全局最优”,忽略了贪心算法进化几十年来都无法根治的固有缺陷——局部最优陷阱。

误区BIC里明确写了复杂度惩罚项,那我的目标应该是让惩罚项尽量大,也就是让图尽量稀疏,参数越少越好。

正解BIC的真实结构是“拟合项减去惩罚项”,两者是此消彼长的平衡关系。如果为了减小惩罚而删掉真实存在的因果边,拟合项会大幅下跌,总分反而更低。想象主厨为了减少食材种类把盐也省了——菜确实简单了,但难吃到没人买单。BIC的惩罚项只是“为了防止过度拟合”,绝不是“越简单越好”的独立追求。

为何常见:把减法公式中的后半项当成了唯一的优化目标,忽视了前半项拟合项的主导作用,属于“只盯局部不看整体”的典型误区。

误区GES有渐进一致性,那我把数据攒得足够多,它输出的CPDAG就一定和真实因果结构一模一样。

正解渐进一致性是一个“在理想条件下成立”的极限性质,而非现实保证。它依赖三个硬前提:数据忠实于真实图(没有巧合成分的条件独立)、不存在隐藏混杂变量(所有共同原因都被观测到)、评分函数在样本极限下一致。现实中任何一条被违背——比如系统里存在未观测的混淆器——样本再多,GES也可能收敛到错误的等价类。用主厨的话说:再多的顾客好评,也无法还原一份被刻意隐藏了关键步骤的菜谱。

为何常见:把统计学中的“渐进理论”当成了“有限样本下的实际操作承诺”,忽略了理论保证背后必须满足的前提条件。

面试题

Q1. BIC评分函数中复杂度惩罚项的主要作用是?

单选题 · easy

  • A.提升模型对样本的拟合精度
  • B.抑制过于复杂的图结构← 正确答案
  • C.扩大搜索空间的范围
  • D.降低数据的采样成本

答案:B。BIC = 拟合项 − 惩罚项,惩罚项 (d/2)lnN 会随着参数个数 d 增大而增大评分扣分,从而抑制模型无节制地变复杂。选项A说的是拟合项的作用;C、D与惩罚项无关。可以理解为:惩罚项是品鉴表里“配方过于繁琐扣分”的那一栏。

Q2. 在BIC公式中LL(θ̂)代表的含义是?

单选题 · easy

  • A.当前模型的参数总数
  • B.数据的对数似然值← 正确答案
  • C.样本量的自然对数值
  • D.图结构的总边数

答案:B。LL(θ̂) 是极大对数似然,衡量当前概率模型在观测数据上的拟合程度——相当于主厨打分表里“美味程度”那一栏。参数总数对应符号 d,样本量的对数对应 lnN,边的数量既不是 LL 也不是惩罚项。

Q3. GES搜索等价类空间而非直接搜DAG空间,最主要的原因是?

单选题 · mid

  • A.观测数据无法区分等价类内图← 正确答案
  • B.等价类空间包含更少的节点
  • C.等价类空间必保证全局最优
  • D.等价类空间无有向环结构

答案:A。属于同一马尔可夫等价类的DAG在观测数据上具有完全相同的条件独立集合和评分,数据本身无法裁决哪张图更“真”,所以GES直接在等价类代表图(CPDAG)上搜索,既避免无意义的方向纠结,又缩小搜索空间。B的“节点更少”不准确(节点数同),C是错误承诺,D只有“无环”对但这不是主要原因。

Q4. 当样本量N翻倍时,BIC的复杂度惩罚项如何变化?

单选题 · hard

  • A.保持不变仍然不变
  • B.惩罚值线性翻倍
  • C.增加ln2的幅度← 正确答案
  • D.随N平方增长

答案:C。惩罚项为 (d/2)lnN,N→2N 时惩罚变为 (d/2)ln(2N) = (d/2)(lnN + ln2),即增加 (d/2)·ln2,而不是翻倍或平方增长。这道题考察对 log 运算的敏感度——惩罚项随样本量呈对数增长,而非线性增长,这也是BIC能在大样本下抑制过拟合的关键设计。

Q5. GES算法后向阶段删除边的最终目的是?

单选题 · hard

  • A.进一步提升拟合优度的空间
  • B.移除前向阶段加入的冗余边← 正确答案
  • C.增加模型的参数数量
  • D.加速搜索到收敛的速度

答案:B。前向阶段只加边,可能加入一些单独看有增益、组合后却冗余的边;后向阶段通过删除边来清理这些“鸡肋食材”,使评分继续上升。A是加边的动机,C与删边行为相反,D的“加速收敛”只是附带效果而非最终目的。

Q6. 当模型参数个数d增大时,BIC评分的变化趋势是?

单选题 · easy

  • A.惩罚项增大评分降低← 正确答案
  • B.拟合项增大评分降低
  • C.惩罚项降低评分升高
  • D.评分完全不受影响

答案:A。d 在惩罚项 (d/2)lnN 中做分子,d 越大扣分越多,BIC总分随之降低。这体现了模型选择的“奥卡姆剃刀”:拟合相同的情况下,参数越少越好。但注意这只是趋势,若 d 增大同时带来拟合项更大增幅,总分仍可能上升。

Q7. 关于同一马尔可夫等价类内的两个DAG,以下说法不正确的是?

单选题 · extreme

  • A.它们满足相同的条件独立集合
  • B.它们具有相同的骨架和V结构
  • C.它们对应的联合分布族相同
  • D.它们的因果方向解释完全相同← 正确答案

答案:D。等价类的定义就是“条件独立集相同”,而等价 ⟺ 相同骨架且相同V结构,因此联合分布族也相同,A、B、C均正确。但等价类中方向未定边的因果解释是恰恰不同的——这正是GES输出CPDAG而非完整DAG的原因:数据无法区分方向,因果方向解释自然不能“完全相同”。

Q8. BIC评分函数的组成部分包括哪些?

多选题 · mid

  • A.对数似然拟合优度项← 正确答案
  • B.参数个数复杂度惩罚← 正确答案
  • C.样本容量的对数因子← 正确答案
  • D.边的因果方向惩罚

答案:ABC。BIC = 对数似然项 − (d/2)lnN,其中 d 是参数个数、lnN 是样本容量的对数因子,三者共同构成BIC。D“边的因果方向惩罚”不存在——BIC不惩罚边的方向,等价类内的不同方向评分相同,这也是评分式方法的特征。

Q9. 下列哪些因素会导致GES找到错误的因果结构?

多选题 · hard

  • A.样本量不足数据噪声大← 正确答案
  • B.数据不满足忠实分布← 正确答案
  • C.存在隐藏的混杂变量← 正确答案
  • D.数据量越大越容易出错

答案:ABC。样本不足使评分估计不稳,非忠实分布使条件独立推断失真,隐藏混杂变量直接违反GES的可识别前提,三者都会把搜索引向错误方向。D相反——样本量增大通常让BIC的估计更稳定可靠,而非更容易出错。

Q10. 关于GES贪婪搜索策略,下列说法正确的有?

多选题 · mid

  • A.每次都选增益最大的操作← 正确答案
  • B.加边和删边按阶段推进← 正确答案
  • C.能保证全局最优的图结构
  • D.每步依据BIC增量决策← 正确答案

答案:ABD。GES在每个阶段枚举所有合法操作并选择ΔBIC最大者执行,即A和D;前向加边与后向删边分阶段进行,即B。C错误——贪心策略无法保证全局最优,只能保证“每一步局部最优”,可能陷入局部极值。