想象你是一位立志开餐厅的年轻厨师。研发新菜时,你一边炒一边尝,觉得“太棒了,这道菜一定能火”。可到了正式评审那天,评委们却皱起眉头——因为你早就在试吃时,悄悄把菜调成了“自己喜欢的样子”。你自己尝出来的好评,根本不是评委的真实评价。这就是“自己出题、自己阅卷”带来的乐观偏差。在因果机器学习里,因果森林也面临同样的困境:如果一棵树既用同一批数据决定“怎么分裂”,又用同一批数据报告“效果多好”,它就会像那位厨师一样,自信满满地说出虚高的分数。而“诚实分裂”(Honest Splitting)正是把“研发”和“评审”分开的黄金法则:一部分样本负责定规则,另一部分样本负责打分数,让因果森林的估计真正可信、可推断。
诚实分裂是因果森林实现无偏估计与统计推断的基石。掌握它,你就能分辨“模型自嗨”与“真实疗效”,做出让业务方和论文审稿人都信服的因果结论。
可视化演示
测试驱动开发三阶段循环:先写失败测试(红),再最小实现使其通过(绿),最后重构优化代码质量。
本节配有交互动效(进入视口后自动加载,约 3KB)。
TDD三阶段循环 RED:编写测试,预期失败 GREEN:最小代码使测试通过 REFACTOR:优化代码质量 循环周期 = 编写测试 + 实现 + 重构 每次循环增量提升代码质量与测试覆盖率
异质效应
一家餐厅想给不同顾客推荐招牌菜,但客人的口味千差万别:有人嗜辣,有人忌口,有人只爱清淡。如果给所有客人端上同一道菜,总有一半客人不满意。聪明的做法是给客人“画像”,把口味相近的客人分到同一桌,再为每桌设计专属菜品。因果森林的使命,正是给每个个体画这张“口味画像”。
在因果推理中,这张画像对应一个核心概念:条件平均处理效应(CATE,Conditional Average Treatment Effect)。它回答的问题是:“给定一个人的特征 \(X\),干预对 TA 的平均影响是多少?” 比如,给定用户的历史消费特征,发放优惠券平均能带来多少额外购买?
因果森林中的每一棵树,就像一位“分诊师”:它不断根据特征提问(“月消费高吗?”“最近买过母婴用品吗?”),把人群切分成越来越小的组,直到同组成员的口味足够接近。叶子节点就是分诊师最终写下的“推荐卡”。但如果分诊师用的病例数据同时兼任“疗效考核表”,他写的推荐就会越来越自嗨,这就引出下一节的乐观偏差。
- 符号认识\(\tau(\mathbf{x})\) 表示特征为 \(x\) 的个体的处理效应,它是一个随 \(x\) 变化的函数。
- 潜在结果之差\(Y(1) - Y(0)\) 是同一个体在接受干预与不接受干预时的结果差异,这是因果效应的“真身”。
- 期望运算\(\mathbb{E}[\,\cdot\,]\) 表示对人群中所有同特征个体求平均,消除随机波动。
- 条件限定\(\mid \mathbf{X} = \mathbf{x}\) 表示只在特征等于 \(x\) 的子群体内求这个平均,突出“因人而异”。
乐观偏差
一位厨师研发新菜时,每炒一勺都自己尝一口,并根据口感继续加盐加糖。最终他拍胸脯保证:“这道菜 98 分!” 可评委盲测后只给了 75 分。问题出在哪?他用自己的舌头既当了“调整依据”,又当了“评分标准”——舌头被自己的手艺驯化了,失去了客观性。传统决策树(CART)在因果估计中也这么干:用同一批样本既决定如何分裂,又报告分裂后的效果,得到的效果自然“自卖自夸”。
统计学上,这种自夸叫乐观偏差。Athey 与 Imbens(2016)将树估计器的期望平方误差拆成三部分,清楚地暴露出偏差的来源:
不诚实的树用全量数据同时做“结构学习”和“效果汇报”,优化误差就像厨师尝菜后“手一抖多加了两勺糖”——训练集上看起来更完美,真实场景却翻车。诚实分裂用独立样本做评审,恰好能让优化误差归零。
- 分解起点左边是估计值 \(\hat{\tau}(\mathbf{x})\) 与真实效应 \(\tau(\mathbf{x})\) 的均方误差,衡量估计有多离谱。
- 结构误差\(\hat{\tau}_S(\mathbf{x})\) 是在固定训练样本 \(S\) 下“理想估计器”的预测,它与真实值的差距由树的表达力不足造成,相当于菜谱本身平庸。
- 优化误差实际估计器由于在 \(S\) 上做了贪心分裂,会偏离理想估计器,偏离得越远,说明“为了迎合训练数据”扭曲得越厉害。
- 常数项剩余的不可约噪声,无论怎么换厨师都存在。
分裂准则
既然要写菜谱,就得决定“菜怎么切”。切菜的准则是:让切出来的两组食材在“烹饪反应”上差异越大越好——爱吃辣的一堆,爱吃甜的一堆,这样后续调味才能精准。因果树的分裂准则也是同样的哲学:寻找一个特征切分点,使左右两个子节点的处理效应差异最大。
形式上,对于候选切分 \(s\),林中的经典准则(如 Athey & Imbens 的 CART 准则)基于训练样本估计左右子节点的效应,用加权平方和度量分裂带来的“异质性增益”:
关键细节在于:\(\hat{\tau}_{\ell}\) 只用“结构样本”计算。如果混入评审样本,就是这个厨师一边炒菜一边把评委的筷子也拿来尝——准则立刻被污染。这就是诚实分裂在分裂准则层面的体现。
- 左右子节点切分 \(s\) 把父节点 \(P\) 分成左 \(L\)、右 \(R\) 两组,样本量分别为 \(n_L\) 和 \(n_R\)。
- 权重\(\frac{n_{\ell}}{n_{P}}\) 表示子节点样本占父节点的比例,样本多的子节点话语权更大。
- 组内效应估计\(\hat{\tau}_{\ell}\) 是子节点内处理组与对照组的结果均值之差,刻画该子群体的平均因果效应。
- 加权求和对所有候选切分计算 \(\hat{\Delta}_{\mathrm{ext}}(s)\),值越大,说明该切分越能区分不同效应的个体,就选它。
样本二分
好餐厅的规矩是:后厨研发和评委品鉴必须分开。主厨在研发间里自由试错,但不能把评委请进厨房看过程;等菜谱定稿了,再让评委盲测打分。诚实分裂在因果森林里立了同样的规矩:把样本随机分成结构样本 \(S\) 和估计样本 \(E\),用 \(S\) 学习树的形状,用 \(E\) 估计叶子里的效应值。
比喻回扣:结构样本是“藏着掖着的研发笔记”,估计样本是“从没进过厨房的评委”。当树结构固定后,估计样本像盲测一样流过叶子,给出不带人情分的效果值。正因为两者分离,因果森林才能向统计推断迈出坚实一步。
- 二元划分\(I(Z_i \in S)\) 是指示函数,当样本 \(Z_i\) 被划入结构样本时取 1,否则取 0;估计样本同理。
- 结构样本\(S\) 只参与分裂规则与树结构的确定,相当于“菜谱研发组”。
- 估计样本\(E\) 不参与任何分裂计算,只在树结构固定后用来估计每个叶子的处理效应,相当于“盲测评委组”。
- 独立性\(S\) 与 \(E\) 互不相交,且随机划分保证两组分布一致,这是“诚实”的数学保证。
渐近性质
盲测为什么可信?因为评委人数足够多、且没有受过厨师干扰时,评分的平均值会稳定在某个真值附近,波动越来越小。诚实分裂给出的效应估计也具备这种“大数定律式”的稳定性:当样本量增大,估计量不仅一致,而且渐近正态,这让构造置信区间成为可能。
这条性质把因果森林从“黑箱打分器”升级为“可推断的测量仪”。有了渐近正态性,业务方问“这个效应到底是不是碰巧?”,工程师就可以给出置信区间而不是一句“模型说有效”。
- 归一化因子\(\sqrt{n}\) 表示用样本量的平方根把误差放大到合适的尺度,让极限分布非退化。
- 估计误差\(\hat{\tau}(\mathbf{x}) - \tau(\mathbf{x})\) 是估计值与真实效应的偏差,诚实分裂保证这个偏差的均值趋向 0。
- 依分布收敛\(\xrightarrow{d}\) 表示随着 \(n\) 增大,误差的分布越来越接近右边的正态分布。
- 渐近方差\(\mathcal{N}\left(0, V(\mathbf{x})\right)\) 中的 \(V(\mathbf{x})\) 是方差,由分裂结构、样本量与噪声共同决定,是构造置信区间的基石。
实验对照
为了让你信服“诚实分裂”,我们做一场厨房对照实验:两位厨师做同一道菜。厨师 A(naive)边做边尝边改,厨师 B(honest)定好菜谱后盲测。结果显示,A 的自评高达 95 分但评委只给 72 分;B 自评 78 分,评委给了 80 分。A 的“自评 - 评委”差距,就是乐观偏差。
数学上,假设真实效应为 \(\tau\),naive 估计器 \(\hat{\tau}_N\) 与 honest 估计器 \(\hat{\tau}_H\) 的均方误差满足:
这场对照实验告诉我们:模型在训练集上多自信不重要,关键是“换一桌陌生评委”后它还剩几分。诚实分裂牺牲了一点训练集上的漂亮分数,换来了测试集与真实场景中经得起推敲的稳健表现。
- naive 的误差\(\mathbb{E}\left[(\hat{\tau}_N - \tau)^2\right]\) 是“既当运动员又当裁判”的估计器相对真值的均方误差。
- honest 的误差\(\mathbb{E}\left[(\hat{\tau}_H - \tau)^2\right]\) 是“研发与评审分离”的估计器相对真值的均方误差。
- 非负差额两者相减大于等于 0,说明诚实分裂至少不比 naive 差,且通常显著更好。
- 不等号方向\(\geqslant 0\) 保证乐观偏差可以被消除,这正是诚实分裂被誉为“因果森林基石”的原因。
实践工程
从单棵树的诚实分裂到因果森林工程落地,中间还有一道坎:样本二分会让我们手里可用于训练的食材减半。厨师的解法是“一鱼多吃”——用自助法(Bootstrap)反复重采样,蒸出好几条味道相近但细节不同的鱼,再综合各家所长。因果森林正是通过自助法生长出大量结构略有差异的诚实树,再取平均,既保住无偏性,又压低了方差。
至此,厨房哲学贯穿始终:先把菜谱研发(结构学习)与菜品评审(效应估计)分开,再用多轮“复刻盲测”(自助法)稳定火候。这样端出来的因果森林,才是一道能让客人放心下筷、让老板放心定价的招牌菜。
- 自助法重采样每次从原始样本中有放回地抽出同样大小的样本,生成一棵新树的数据源。
- 森林平均\(\frac{1}{B} \sum_{b=1}^{B} \hat{\tau}_b(\mathbf{x})\) 表示把 \(B\) 棵树的效应估计取平均,降低单棵树的随机波动。
- 方差估计\(\frac{1}{B-1} \sum_{b=1}^{B} \left(\hat{\tau}_b(\mathbf{x}) - \hat{\tau}(\mathbf{x})\right)^2\) 用各棵树估计值偏离森林均值的大小,来刻画效应估计的不确定性。
- 工程落地实际部署时还需调节最小叶子大小、最大深度、分裂比例等超参数,用小样本堆出多样性的树,最终输出“效应 + 置信区间”。
AI 应用场景
精准营销中的增益建模
阶段:模型训练与评估阶段
解决的问题:传统营销给所有用户发同样的优惠券,浪费预算且打扰高价值客户。增益建模(Uplift Modeling)需要估计“某用户因优惠券而增加的购买概率”,但直接用历史数据训练模型,很容易把“本来就爱买的人”误判成“优惠敏感的人”,产生严重的乐观偏差。
具体案例:某电商平台用因果森林对 50 万用户做增益建模。他们采用诚实分裂:一半数据学习用户特征与优惠敏感度的树结构,另一半独立数据估计每个叶子内的增量购买率。结果发现,传统模型自评 AUC 为 0.78,但小流量验证时实际增益只有 0.05%;诚实森林自评 0.72,实际验证增益却达到 0.31%。业务团队最终按诚实森林的预测分群投放,营销 ROI 提升了 3 倍。
医疗个性化治疗方案推荐
阶段:模型推理与可信部署阶段
解决的问题:医生想知道“这位高血压患者用 A 药还是 B 药效果更好”。普通机器学习模型只能预测患者服药的结局,无法回答“换药带来的增量效果”,且容易把训练集的偶然规律当作普适真理。
具体案例:一家临床决策支持系统公司用诚实因果森林建模电子病历数据。系统在训练时将患者随机分为结构组与评估组,结构组决定“按哪些指标分群”,评估组在树结构固定后估计每类患者的用药效应差异。系统最终输出:“65 岁以上、合并糖尿病的患者,换用 B 药平均收缩压多降 4.2 mmHg,95% 置信区间 [2.1, 6.3]”。医生据此调整处方,避免了过度自信的模型给出危险建议。
Python 演示
import numpy as np rng = np.random.RandomState(0) def gen_data(n=600): x1 = rng.binomial(1, 0.5, n) x2 = rng.binomial(1, 0.5, n) X = np.column_stack([x1, x2]) w = rng.binomial(1, 0.5, n) true_tau = 1.0 + 1.5 * x1 + 2.0 * x2 + 1.0 * x1 * x2 y0 = 1.0 + 0.5 * x1 - 0.5 * x2 + rng.normal(0, 1, n) y = y0 + true_tau * w return X.astype(np.float64), w.astype(np.float64), y.astype(np.float64), true_tau class CausalTree(object): def __init__(self, max_depth=2, min_leaf=30, honest=True): self.max_depth = max_depth self.min_leaf = min_leaf self.honest = honest self.X = None self.y = None self.w = None self.nodes = [] self.leaves = [] def fit(self, X, y, w, split_idx): self.X = X self.y = y self.w = w self.nodes = [] self.leaves = [] self._build_node(np.arange(X.shape[0]), split_idx, 0) return self def _build_node(self, idx, split_idx, depth): if depth >= self.max_depth or len(idx) <= self.min_leaf: self.leaves.append(idx.copy()) return X, y, w = self.X, self.y, self.w tau_global = y[idx].mean() # only for variance reduction best_gain, best_f, best_t = -1.0, None, None for f in range(X.shape[1]): xf = X[idx, f] cuts = np.unique(xf) if len(cuts) < 2: continue for t in (cuts[:-1] + cuts[1:]) / 2.0: left = idx[xf <= t] right = idx[xf > t] if len(left) < self.min_leaf or len(right) < self.min_leaf: continue # use only the split sample for honest splitting use = left if self.honest: use = np.intersect1d(left, split_idx) if len(use) < 2: use = left var_before = np.var(y[use]) var_after = len(left) / len(idx) * np.var(y[left]) + \ len(right) / len(idx) * np.var(y[right]) gain = var_before - var_after if gain > best_gain: best_gain, best_f, best_t = gain, f, t if best_f is None: self.leaves.append(idx.copy()) return split = self.X[idx, best_f] <= best_t self._build_node(idx[split], split_idx, depth + 1) self._build_node(idx[~split], split_idx, depth + 1) def leaf_id(self, idx_sub): out = np.full(len(idx_sub), -1, dtype=int) for li, leaf in enumerate(self.leaves): mask = np.arange(len(idx_sub)) for node_idx in leaf: pass for j, i in enumerate(idx_sub): for node in leaf: pass if i in leaf: out[j] = li return out def leaf_effect(tree, est_idx): y, w = tree.y, tree.w effects = [] for leaf in tree.leaves: idx = np.intersect1d(leaf, est_idx) if len(idx) == 0: effects.append(0.0) continue p = w[idx].mean() if p == 0 or p == 1: effects.append(0.0) continue weighted = w[idx] * y[idx] / p / 2.0 - (1.0 - w[idx]) * y[idx] / (1.0 - p) / 2.0 effects.append(weighted.mean()) return effects def run_once(seed): rng = np.random.RandomState(seed) X, w, y, true_tau = gen_data() n = len(y) idx = rng.permutation(n) tr, te = idx[:n // 2], idx[n // 2:] tree_naive = CausalTree(honest=False, max_depth=2, min_leaf=30) tree_naive.fit(X, w, y, tr) eff_naive = leaf_effect(tree_naive, tr) tree_honest = CausalTree(honest=True, max_depth=2, min_leaf=30) tree_honest.fit(X, w, y, tr) eff_honest = leaf_effect(tree_honest, te) pred_naive = np.zeros(n) pred_honest = np.zeros(n) for li, leaf in enumerate(tree_naive.leaves): pred_naive[leaf] = eff_naive[li] for li, leaf in enumerate(tree_honest.leaves): pred_honest[leaf] = eff_honest[li] mse_naive_test = np.mean((pred_naive[te] - true_tau[te]) ** 2) mse_honest_test = np.mean((pred_honest[te] - true_tau[te]) ** 2) return mse_naive_test, mse_honest_test if __name__ == "__main__": naive_list, honest_list = [], [] for seed in range(10): m1, m2 = run_once(seed) naive_list.append(m1) honest_list.append(m2) print("naive test MSE: %.4f" % np.mean(naive_list)) print("honest test MSE: %.4f" % np.mean(honest_list)) print("乐观偏差被降低: %.4f" % (np.mean(naive_list) - np.mean(honest_list)))
y0 = 1.0 + 0.5 * x1 - 0.5 * x2 + rng.normal(0, 1, n)生成不依赖处理变量的基线结果,模拟“不干预也会发生的事”。true_tau = 1.0 + 1.5 * x1 + 2.0 * x2 + 1.0 * x1 * x2定义真实处理效应随特征变化,是评估预测误差的“标准答案”。self.honest = honest标志当前树是否使用诚实分裂,控制分裂时是否只使用结构样本。use = np.intersect1d(left, split_idx)诚实分裂的核心:计算分裂增益时只用结构样本,评审样本完全不参与切分选择。var_before - var_after以“分裂后方差减少量”作为准则,方差降得越多,说明切分越能区分异质效应。eff_naive = leaf_effect(tree_naive, tr)不诚实树用训练样本自身的叶子数据估计效应,相当于“自己给自己打分”。eff_honest = leaf_effect(tree_honest, te)诚实树用从未参与分裂的评估样本估计效应,相当于“陌生人盲测”。pred_naive[leaf] = eff_naive[li]把叶效应写回样本,得到每个个体的处理效应预测。np.mean((pred_naive[te] - true_tau[te]) ** 2)在测试集上比较预测效应与真实效应的均方误差,是检验“谁更可信”的最终标准。
常见误区
误区把样本分成两份,一份学结构、一份估效应,那训练数据不是少了一半吗?模型肯定变差,这不划算。
正解是“少用了一半数据做结构学习”,但换来的是效应估计无偏。就像米其林餐厅宁可少卖一半菜,也要保证评委盲测客观;数据量足够大时,这点结构损失完全可被森林的自助法平均弥补。诚实分裂不是浪费,而是用可量化的方差换不可量化的偏差,这笔账在统计推断场景下非常划算。
为何常见:人们习惯从“训练集大小决定模型好坏”的监督学习视角看问题,忽略了因果估计的核心矛盾不是拟合精度,而是“自评虚高”。
误区结构样本训练、估计样本验证,这不就是剪枝用的验证集吗?或者不就是交叉验证换了个名字?
正解剪枝是“用验证集决定树该剪多狠”,验证集仍参与模型选择;交叉验证是“反复轮流当验证集”。诚实分裂更极端:估计样本从头到尾不参与任何分裂准则计算,只负责在树固定后估计叶内效应。它不是模型选择的辅助工具,而是保证估计量无偏的结构性设计,与“调超参”完全不是一回事。
为何常见:因为三者都涉及“把数据分成两份”,表面流程相似,初学者容易混淆“验证”与“独立估计”的本质区别。
误区既然诚实分裂消除了乐观偏差,那把树长到最深、把每个叶子都分到只有一个样本,不是能更精细地刻画每个人效应吗?
正解叶子样本太少时,叶内效应估计的方差爆炸,置信区间宽到毫无意义,正如盲测只有一位评委时分数完全不可信。诚实分裂只消除“优化误差”,不消除“方差”。实践上要限制最大深度、最小叶子样本量,并用自助法做森林平均,才能在偏差与方差间取得平衡。
为何常见:把“无偏”误解为“什么都好”,忘记无偏只是误差的一半,方差是另一半。
误区这个概念是因果森林论文里提出的,所以只适用于树模型做因果推断,普通机器学习用不上。
正解“结构学习与评估解耦”的思想具有普适性:任何需要在训练集上做贪心选择、又要在同一批数据上报告性能的模型,都存在乐观偏差。深度学习中的“早停法”、特征选择中的“嵌套交叉验证”,本质上都是同一哲学的不同体现。
为何常见:因为 Honest Splitting 这个术语确实诞生于因果树论文,但它的底层思想在统计学中早有渊源,读者容易被名词绑定限制视野。
误区模型输出了一个 95% 置信区间,那就说明真实效应有 95% 概率落在这个区间里,可以直接写进审计报告。
正解置信区间依赖渐近正态性、无干扰、可忽略性等假设。如果样本量不够大、分裂数太少、协变量缺失,区间依然可能偏窄或偏倚。置信区间是“在模型假设成立且样本足够大时”的承诺,部署前必须做敏感性与鲁棒性检验。
为何常见:人们容易把统计推断的数学结果当作绝对真理,忽略了所有推断都有前提条件,就像盲测也要保证评委没被收买。
面试题
Q1. 在诚实分裂中,估计样本(Estimation Sample)的核心作用是什么?
- A.决定每棵树的最优分裂特征与阈值
- B.在树结构固定后,估计叶子内的处理效应← 正确答案
- C.用于对特征做标准化和缺失值填充
- D.帮助选择森林中树的数量
答案:B。估计样本的定位是“盲测评委”:树结构已由结构样本定稿,估计样本只负责在叶子内给出无偏的效应值。A 是结构样本的工作,C 是数据预处理,D 属于超参数调优,都与诚实分裂的设计无关。
Q2. 诚实分裂能够带来哪些收益?
- A.减少结构学习的过拟合,降低乐观偏差← 正确答案
- B.使效应估计量具备渐近正态性,支持置信区间← 正确答案
- C.提高训练集上的拟合精度
- D.减少训练时间,因为只训练一半数据
答案:AB。A 是诚实分裂的直接目标;B 是随之而来的统计推断能力。C 恰恰相反,诚实分裂通常会让训练集表现更“难看”;D 不是收益,样本二分会增加方差,时间未必减少且并非设计目的。
Q3. 诚实分裂最核心的思想是什么?
- A.用更多数据训练更深的树
- B.让结构学习与效应估计使用互不相交的样本← 正确答案
- C.在分裂后对叶子做正则化剪枝
- D.用交叉验证挑选最大化增益的阈值
答案:B。诚实分裂的本质是把“出题”与“阅卷”分离:结构样本定分裂规则,估计样本评效应值,互不偷看。C 是剪枝,D 是模型选择,A 与诚实无关。
Q4. 为什么传统 CART 回归树直接用于因果效应估计会产生乐观偏差?
- A.因为 CART 不能处理分类变量
- B.因为同一批数据既用于选择分裂规则,又用于报告叶子效果← 正确答案
- C.因为叶子的样本量总是过大
- D.因为 CART 只优化分类准确率而非回归误差
答案:B。传统 CART 用训练集贪心选分裂点,又用同一批训练集汇报叶均值,等于“自己出题自己判卷”,优化误差被计入效果。其余选项没有命中乐观偏差的本质来源。
Q5. 诚实分裂可以完全消除以下哪类误差?
- A.结构误差
- B.抽样的随机噪声
- C.优化误差(乐观偏差)← 正确答案
- D.所有类型的偏差
答案:C。诚实分裂用独立评估样本固定树结构,消除了“因迎合训练数据而虚报效果”的优化误差。但结构误差来自树表达能力不足,随机噪声永远存在,所以无法消除所有偏差。
Q6. 诚实分裂付出的主要代价是什么?
- A.结构样本减少,单棵树的叶子方差变大← 正确答案
- B.估计结果完全不可解释
- C.必须使用深度学习模型
- D.不再需要随机化实验
答案:A。样本一分为二,用于学习树结构的样本变少,单棵树的估计方差上升。但因果森林用自助法多树平均来补偿方差。B、C、D 均与诚实分裂的真实代价无关。
Q7. 若要为因果森林的叶子效应构造置信区间,需要哪些条件?
- A.估计量满足渐近正态性← 正确答案
- B.能够从自助法或方差公式中估计出标准误← 正确答案
- C.叶子内必须有足够样本量支撑方差估计← 正确答案
- D.所有特征必须服从正态分布
答案:ABC。置信区间依赖渐近正态(A)、标准误估计(B)以及叶子样本量(C)。特征是否正态并非必要条件,因果树对特征分布没有这种强假设。
Q8. 在 Athey 与 Imbens 的诚实因果树框架中,分裂准则的增益函数为什么只用结构样本计算?
- A.因为结构样本已经包含全部标签信息,估计样本没有标签
- B.为了确保分裂规则不依赖估计样本的潜在结果,从而保证无偏推断← 正确答案
- C.为了降低计算复杂度,估计样本留给预测阶段使用
- D.因为估计样本专门用于测试模型是否过拟合
答案:B。诚实分裂的数学保证来自“分裂规则独立于用于效应估计的数据”。如果估计样本参与分裂,树结构就会与估计目标产生依赖,乐观偏差卷土重来。B 精确描述了这种解耦的因果逻辑。
Q9. 哪种工程手段最常用于弥补诚实分裂带来的单树数据量下降?
- A.对特征做多项式扩展
- B.使用自助法(Bootstrap)生成多样树再做平均← 正确答案
- C.在每个叶子内训练一个线性回归
- D.把分裂阈值改成随机取值
答案:B。因果森林通过自助法重采样生长多棵诚实树,用平均降低方差,同时保持叶内效应的无偏性。B 是工业界标准做法。A、C、D 不是针对“数据量减少”的标准补偿方案。
Q10. 以下关于诚实分裂与传统 CART、交叉验证的区别,说法正确的有哪些?
- A.诚实分裂要求估计样本完全不参与分裂准则计算← 正确答案
- B.交叉验证反复轮换验证集并参与模型选择,诚实分裂不做这种事← 正确答案
- C.诚实分裂的树结构一旦由结构样本确定,估计样本只读不写← 正确答案
- D.传统 CART 与诚实分裂在因果效应估计上的表现没有差别
答案:ABC。A、C 是诚实分裂“只读不写”的严格性;B 点明它与交叉验证的本质区别。D 错误,正是差别构成了乐观偏差的来源。