在【实验科学中策略的长期异质性效应量化方案探索(一)】提到了强化学习估计长期价值,将 A/B 策略看作是策略 π 的不同版本,构造马尔可夫决策过程(MDP)或部分可观测 MDP(POMDP),用强化学习方法来学习和评估 Treatment 策略下的长期累积回报(reward)。
这里有一篇论文【Inferring the Long-Term Causal Effects of Long-Term Treatments from Short-Term Experiments】就是很好的一篇范文,本文就是这篇论文的快速解读与学习。
代理指标方法的文章:
实验科学中策略的长期异质性效应量化方案探索:instacart方案解析(二)
论文地址:https://arxiv.org/pdf/2311.08527
1 替代变量方法
1.1 替代变量方法的优劣
干预措施的长期影响通常是研究的重点,但由于难以进行长期随机对照试验(RCT),直接测量这些影响常常十分困难。
替代变量方法(surrogate methods)
提供了一条从短期测试推断长期结果的路径。这类方法依赖于“中间替代变量”以及一个观察性数据集来建立替代变量与最终长期结果之间的联系。关键要求包括:
- 替代变量能够完全中介干预对最终结果的影响;
- 我们能够识别替代变量对结果的影响。
但是文章认为:
替代指标法只能估计“一个短暂干预所引发的余波(persistence)”,而不是持续干预本身的全部效应。只能评估“短期”因果效应,而并非长期效应,大概就是在Disssss 替代方法的合理性…
替代变量关键假设(Surrogacy Assumptions):
- 完全中介性(complete mediation):
所有干预对长期结果的影响,都通过中间变量传递; - 中介变量对结果的因果可识别性(可通过观察数据建模);
- 可比性(comparability):实验组和观察组状态分布一致。
为什么只是“余波”而非“长期因果效应”?
- 替代方法只能推断:施加一次干预后,随着状态自然演化(按旧机制)对未来的影响;
- 无法建模“持续干预”下状态如何改变;
- 所以只估计了“短暂干预后的惯性影响”,即 persistence,而非干预本身的全周期效应。
来具体看看论文的【2.2】节内容翻译:
1.2 论文【2.2】节的翻译:与替代指标方法的比较
在当前环境下,对比我们的方法与替代指标方法(Athey 等, 2019)的关键差异是有启发意义的。假设我们观察到直到某一时刻 t t t 的所有内容,即我们观察到 N N N 个元组 ( s 0 , y 0 , a 0 , … , s t ) (s_0, y_0, a_0, \dots, s_t) (s0,y0,a0,…,st),其中仅观察到了第 t t t 时刻的状态转移。
我们关注于一个永久性处理策略在 t t t 之后各阶段的结果差异,因为在 t t t 之前的处理效应可以通过协变量调整后的均值差异来恢复。基于第 2.1 节中的假设,第 t + k t + k t+k 时刻( k > 0 k > 0 k>0)的真实潜在结果可以表示为:
E [ Y t + k ( 1 ) ] = ∫ s t , s , y y ⋅ p ( y ∣ s , a = 1 ) ⋅ p ( s ∣ s t , a = 1 ; k ) ⋅ p t ( s t ∣ a = 1 ) (2.13) \mathbb{E}[Y_{t+k}(1)] = \int_{s_t, s, y} y \cdot p(y \mid s, a = 1) \cdot p(s \mid s_t, a = 1; k) \cdot p_t(s_t \mid a = 1) \tag{2.13} E[Yt+k(1)]=∫st,s,yy⋅p(y∣s,a=1)⋅p(s∣st,a=1;k)⋅pt(st∣a=1)(2.13)
其中 p ( s ′ ∣ s , a ; k ) p(s' \mid s, a; k) p(s′∣s,a;k) 是从 s s s 出发在采取动作 a a a 情况下前进 k k k 步的转移核。
使用观察数据集的替代方法则会计算第 t + k t + k t+k 时刻结果的期望,但条件是实验中第 t t t 时刻的状态分布,以及部分依赖于从观察数据集中学习得到的概率模型 p o p^o po:
E [ Y t + k ( 1 ) ] ← E s t [ E Y o [ Y t + k ∣ s t , a = 0 ] ∣ a = 1 ] \mathbb{E}[Y_{t+k}(1)] \leftarrow \mathbb{E}_{s_t}[\mathbb{E}_{Y}^{o}[Y_{t+k} \mid s_t, a = 0] \mid a = 1] E[Yt+k(1)]←Est[EYo[Yt+k∣st,a=0]∣a=1]
展开为:
∫ s t , y t + k y t + k ⋅ p o ( y t + k ∣ s t , a = 0 ) ⋅ p t ( s t ∣ a = 1 ) \int_{s_t, y_{t+k}} y_{t+k} \cdot p^o(y_{t+k} \mid s_t, a = 0) \cdot p_t(s_t \mid a = 1) ∫st,yt+kyt+k⋅po(yt+k∣st,a=0)⋅pt(st∣a=1)
进一步展开为:
∫ s t , s t + k , y t + k y t + k ⋅ p o ( y t + k ∣ s t + k , a = 0 ) ⋅ p o ( s t + k ∣ s t , a = 0 ) ⋅ p t ( s t ∣ a = 1 ) (2.14) \int_{s_t, s_{t+k}, y_{t+k}} y_{t+k} \cdot p^o(y_{t+k} \mid s_{t+k}, a = 0) \cdot p^o(s_{t+k} \mid s_t, a = 0) \cdot p_t(s_t \mid a = 1) \tag{2.14} ∫st,st+k,yt+kyt+k⋅po(yt+k∣st+k,a=0)⋅po(st+k∣st,a=0)⋅pt(st∣a=1)(2.14)
请注意,在使用观察模型时,其条件始终是在对照组(即未接受新型处理)的情形下进行的,因为观察数据中并不存在该新型处理。可比性假设保证了观察和实验条件下的概率是相同的,即 p o = p p^o = p po=p。
从式(2.14)可以明显看出,替代方法只能捕捉通过代理变量 s t s_t st 所中介的部分处理效应。
对于超过代理变量观测时间段之后的时期,该方法遗漏了永久性干预可能带来的两种影响:
- 改变状态转移,因此影响未来状态的分布: p ( s t + k ∣ s t , a = 1 ) ≠ p ( s t + k ∣ s t , a = 0 ) p(s_{t+k} \mid s_t, a = 1) \ne p(s_{t+k} \mid s_t, a = 0) p(st+k∣st,a=1)=p(st+k∣st,a=0);
- 改变状态与结果之间的当期关系: p ( y ∣ s , a = 1 ) ≠ p ( y ∣ s , a = 0 ) p(y \mid s, a = 1) \ne p(y \mid s, a = 0) p(y∣s,a=1)=p(y∣s,a=0)。
因此,替代指标方法只能捕捉到截至代理变量测量时间点的处理效应。这些效应是由于初期处理所带来的持续影响而产生的间接长期效应。我们将在第4节中通过实验验证这一点。
2 离线强化学习方法论
2.1 方法论简述
本文开发了一种新方法,能够从短期实验中估计长期治疗的长期效果,前提是短期观察能够充分表征长期轨迹,即使它们不能中介其效果。
该方法直接从短期实验数据中学习长期时间动态,从而无需代理假设和连接代理与长期结果的观测数据集。利用双重鲁棒估计器来估计长期治疗的长期因果效应并构建置信区间。
- 将因果推断问题转化为 离线强化学习中的策略评估问题;构造一个能逼近目标策略的“平稳策略”,进而估计其长期回报。
将非平稳的T持续治疗策略转换为等效的平稳随机策略,使得Q函数变得可处理和可学习.
利用高效的双重鲁棒估计器来估计长期因果效应,该估计器对Q函数和密度比函数的估计误差具有鲁棒性.
为什么能够估计干预真正的长期影响,适用于长期持续性干预?
- 该方法通过将非平稳的长期治疗策略转化为平稳策略来解决Q函数估计的挑战,从而使得Q函数变得可处理和可学习.
- 利用强化学习的框架,特别是Q函数,能够递归地捕捉未来的奖励,从而能够估计超出短期实验范围的长期累积效应.
- 不同于代理方法只捕捉通过短期代理变量中介的效应,本方法直接学习长期时间动态,即使短期观察不中介效果也能充分表征长期轨迹. 只要这些动态持续存在,该方法就能估计任意长度治疗的长期效应.
假设前提:
- 加性回报假设:长期结果是各期结果的折现之后的和(有点跟LTV类似);
- 无混淆性:随机实验中,处理与潜在结果条件独立;
- 重叠性:对于所有的状态 s s s 和行动 a a a,都有一定概率接受或不接受treatment;
- 马尔可夫性:未来状态只依赖当前状态与动作;
- 平稳性:处理与控制组的动态差异在实验与目标策略下保持一致。
2.2 建模过程
2.2.1 把问题想象成一个“游戏”
论文首先把我们想研究的问题想象成一个不断进行下去的“游戏”,也就是马尔可夫决策过程 (MDP)。
- 状态(State):就是你在游戏里的“位置”或“情况”。比如,一个用户的健康状况、使用某个产品的情况等等。
- 行动(Action):就是你在某个状态下采取的“操作”或“干预”。在这里,就是你是否接受了治疗(比如吃药)或者是否接受了产品的新版本。
- 奖励(Reward):就是你每采取一个行动后,立即得到的“好处”或“坏处”。论文认为,长期的总结果可以看作是每次小奖励的累加。
- 状态变化(Transition):就是你采取行动后,你的“位置”或“情况”会怎么变化。比如,吃药后健康状况会发生改变。
- 策略/行动倾向(Policy / Propensity):在状态 s 下执行动作 a 的概率。论文特别关注的是“长期治疗策略”,意思是前面一段时间一直接受干预,之后就不再干预了;还有“对照策略”,就是一直不干预。
2.2.2 把“临时策略”(非平稳策略)变成“固定策略”(平稳策略)
这是本文方法的一个关键创新点。传统的强化学习通常处理平稳策略 (Stationary Policies),即策略不随时间变化。然而,论文中定义的T持续治疗策略 π T \pi^T πT 是一个非平稳策略 (Non-stationary Policy),因为它在时间 T T T 之后改变了行动。我们研究的“长期治疗策略”是变化的(比如前面吃药,后面不吃了),这在计算上很难处理。
- 困难:直接估计非平稳策略的 Q 函数会非常复杂,因为它需要在每个时间步 t t t 都定义一个不同的 Q 函数 q t T ( s , a ) q^T_t(s,a) qtT(s,a),这会导致维度爆炸。如果策略是变化的,那么每次计算“好坏程度”都需要重新算一套规则,非常麻烦。
- 解决办法:论文利用强化学习中的一个重要性质:对于任何非平稳策略 π \pi π,都存在一个等效的平稳随机策略 π ‾ \overline{\pi} π,它能产生相同的累积折现奖励。这个“固定策略”虽然看起来是固定的,但它能让你获得和那个“变化策略”一样的长期总奖励。这样一来,我们就可以用更简单的数学工具来分析它了。
具体地,对于 T 持续治疗策略 π T \pi^T πT,其等效平稳随机策略 π ‾ T \overline{\pi}^T πT 在状态 s s s 上的平均值是 1 − γ T 1-\gamma^T 1−γT。这意味着,虽然表面上是非平稳的,但我们可以将其视为一个在整个时间范围内的平稳随机策略,只是在状态-行动空间中的“停留时间”分布发生了变化。
2.2.3 学习“行动的价值” (Q函数)
一旦我们把策略转化成了“固定策略”,接下来的关键就是学习每个“行动的价值”,这在强化学习里叫做 Q 函数。
- Q 函数是什么:它告诉你,在某个状态下,如果你采取了某个行动,并且之后都按照特定的“固定策略”去玩,你总共能获得多少未来的折现奖励(即“价值”)。
- 怎么学习:因为我们只有过去的实验数据,不能去实际操作(这就是“离线”的含义),所以需要用一种叫做“时序差分学习”的方法来估计 Q 函数。它会不断调整对每个行动价值的估计,直到它符合从数据中观察到的模式。对于连续状态空间或大型离散状态空间,需要使用函数逼近器(例如神经网络)来参数化 Q 函数 q π ( s , a ; θ q ) q^\pi(s,a;\theta_q) qπ(s,a;θq)。
2.2.4 学习“状态的流行程度” (密度比函数)
为了让我们的估计更准确、更可靠,论文还引入了另一个要学习的东西,叫做密度比函数。
- 密度比是什么:它衡量的是在“我们想评估的策略”下,某个状态和行动组合出现的可能性,与在“我们收集数据的实验策略”下,这个组合出现的可能性之间的比例。简单来说,就是比较在理想策略下和实际实验中,各种情况出现的“流行程度”有多大差异。
- 怎么学习:同样通过机器学习方法来估计这个比例,找到一个函数能最好地反映这种“流行程度”的差异。论文指出可以通过最小化一个特定的损失函数来估计密度比函数。
- L W ( f , w ) = E s , a , y , s ′ ∼ p 0 , a ′ ∼ π ( ⋅ ∣ s ′ ) [ w ( s , a ) ( γ f ( s ′ , a ′ ) − f ( s , a ) ) ] − ( 1 − γ ) E s ∼ p 0 , a ∼ π ( ⋅ ∣ s ) [ f ( s , a ) ] L_W(f,w) = \mathbb{E}_{s,a,y,s' \sim p_0, a' \sim \pi(\cdot|s')}[w(s,a)(\gamma f(s',a') - f(s,a))] - (1-\gamma)\mathbb{E}_{s \sim p_0, a \sim \pi(\cdot|s)}[f(s,a)] LW(f,w)=Es,a,y,s′∼p0,a′∼π(⋅∣s′)[w(s,a)(γf(s′,a′)−f(s,a))]−(1−γ)Es∼p0,a∼π(⋅∣s)[f(s,a)]
这个过程可以理解为训练一个模型来学习实验数据分布与目标策略下的状态-行动分布之间的比例。
2.2.5 构建双重鲁棒 (Doubly Robust) 估计器
最后一步是把前面学习到的 Q 函数和密度比函数巧妙地组合起来,得到对长期治疗效果的准确估计。
本文方法的核心是利用高效影响函数 (Efficient Influence Function, EIF) 来构建一个双重鲁棒的估计器来计算长期平均治疗效果 (ATE)。
- 核心思想:论文构建了一个特殊的估计器,它不仅用 Q 函数来直接估计效果,还会用密度比函数来“纠正”可能存在的偏差。
- “双重鲁棒性”:这种方法最厉害的地方在于它的“双重鲁棒性”。这意味着,即使你对 Q 函数的估计有点偏差,或者对密度比函数的估计有点偏差,只要其中一个估计得足够好,最终对长期效果的估计仍然是可靠的。这大大提高了估计的稳健性。
2.2.6 用“交叉验证”来确保可靠性
为了让最终的估计结果更可信,并且能计算出“误差范围”(置信区间),论文建议使用一种叫做交叉验证的技术。
- 作用:它把数据分成几份。用其中一部分数据去训练模型(学习 Q 函数和密度比函数),用剩下的数据去评估和修正。重复几次这个过程,就能让最终的估计更加稳定,避免模型在特定数据上“死记硬背”导致不准确。
2.2.7 组合所有信息,得到最终的长期平均治疗效果 (ATE)
在交叉验证完成之后,我们就拥有了经过稳健估计的 Q 函数和密度比函数。接下来,就是将这些估计值代入我们之前提到的双重鲁棒估计器中,从而计算出最终的长期平均治疗效果 (ATE)。
核心公式回顾:虽然之前承诺尽量避免公式,但这里的核心思想离不开它,请允许我简要展示一下:
φ ^ B C π ‾ = 基于 q ^ 的初步估计 + 基于 q ^ , w ^ , 观测数据和策略的偏差校正项 \hat{\varphi}_{BC}^{\overline{\pi}} = \text{基于 } \hat{q} \text{ 的初步估计} + \text{基于 } \hat{q}, \hat{w}, \text{观测数据和策略的偏差校正项} φ^BCπ=基于 q^ 的初步估计+基于 q^,w^,观测数据和策略的偏差校正项
用更通俗的话说:
- 我们首先利用学到的 Q 函数(即“在不同状态下,采取不同行动后的长期价值”)来初步计算,如果所有人都遵循“长期治疗策略”和“对照策略”,各自能获得多少长期总价值。然后把这两个总价值相减,得到一个初步的治疗效果估计。
- 接着,我们利用学到的 密度比函数 和 Q 函数,结合实际观察到的实验数据,计算一个 校正项。这个校正项是用来弥补由于我们用机器学习模型估计 Q 函数和密度比函数时可能产生的误差,以及实验数据与我们目标策略之间的差异。
- 最后,将初步估计和这个校正项相加,就得到了最终的偏差校正后的长期平均治疗效果
2.2.8 求解ATE的置信区间
我们的 ATE 估计值是一个点估计,它只是基于有限的样本数据得出的一个特定数字。由于抽样误差、模型估计误差等因素,这个点估计不可能是完美的。置信区间提供了一个数值范围,表示真实 ATE 值很可能落在这个范围之内。置信区间暗示了,如果重复进行这个实验多次,那么在绝大多数情况下,你计算出来的 ATE 估计值都会落在类似的置信区间内。例如:
- 如果一个新药的长期疗效 ATE 估计是 +10%,但置信区间是 [-5%, +25%],这意味着效果可能为负,也可能很大,不确定性很高,决策者可能需要更多数据。
- 如果 ATE 估计是 +10%,置信区间是 [+8%, +12%],这意味着效果非常稳定且显著,决策者可以更放心地采纳。
高效影响函数 (EIF) 的一个核心统计性质:EIF 的方差定义了目标参数(这里是 ATE)的渐近方差。这意味着,如果我们的 ATE 估计器是基于 EIF 构建的,并且满足一定的正则性条件,那么 EIF 值的样本方差就可以作为 ATE 估计量方差的良好估计。
计算过程为:
- 收集所有数据点的 EIF 值,在交叉验证过程中,我们对数据集中的每个观测数据点 都计算出了一个对应的 EIF 值 ϕ i ϕ_i ϕi
- 计算 EIF 值的样本方差(我们首先计算这些 EIF 值的样本均值,再计算这些 EIF 值的样本方差)
- 估计 ATE 估计量的方差,根据渐近理论,ATE 估计量 的方差估计可以由 EIF 值的样本方差除以样本量得到
- 计算 ATE 估计量的标准误差 (Standard Error, SE)
- 构建置信区间,在大样本条件下,ATE 估计量通常服从渐近正态分布。因此,我们可以使用正态分布的临界值来构建置信区间。
3 一些概念的理解与解析
3.1 高效影响函数EIF
3.1.1 相关概念
高效影响函数(Efficient Influence Function, EIF) 是统计学和因果推断领域的一个核心概念,尤其在半参数统计模型(即部分模型结构已知,部分模型结构未知)中用于构建最优估计器。
设我们想估计一个目标参数 ϕ \phi ϕ,比如 ATE(平均处理效应)或某策略的长期收益。我们使用观测数据中的变量 ( s , a , y , s ′ ) (s, a, y, s') (s,a,y,s′) 进行估计。
如果我们直接建模 ϕ \phi ϕ(比如 plug-in 估计),就容易受到模型偏误影响;
EIF 则像一个“偏差修正器”:
它告诉我们,如何在 plug-in 基础上加一个校正项,使得即便模型某些部分估得不准,整体估计仍是一致的且高效的。
3.1.2 高效影响函数EIF跟SHAP值的差别
计算过程不同,不过好像也有一些概念相似
两者都是在尝试理解“什么因素导致了什么结果”或“什么数据影响了什么估计/预测”:
- EIF:量化的是数据中每个观测点(或每个“信息单元”)对特定因果参数估计值的整体影响,并且这种影响是经过统计优化的。它关注的是整体因果效应估计的精度和偏差修正。每个观测数据点对应的 EIF 值(一个实数),其平均值用于校正估计量。其方差用于构建置信区间。
- SHAP 值:量化的是模型中每个特征对单个预测结果的贡献。它关注的是模型内部对某个具体预测的解释。
增量贡献的思路:
- EIF:通过分析数据点的微小扰动如何影响目标参数来构建。这种“扰动”可以看作是对单个数据点贡献的一种数学化表达。
- SHAP 值:基于合作博弈论,通过考虑特征在所有可能的特征组合中的边际贡献来计算。这也是一种“增量”或“边际”贡献的思路。
计算过程来看,EIF更为复杂:
- 通常需要估计多个辅助模型(如Q函数、倾向性分数、密度比等),并通过特定的公式组合这些估计,涉及残差项和加权。
- SHAP值,是基于Shapley值的思想,需要遍历所有可能的特征组合,计算特征加入前后模型预测的变化。通常计算量大,有近似算法(如TreeSHAP, KernelSHAP)。
3.1.3 EIF举例代码
高效影响函数(EIF)用于优惠券营销中的 ATE 估计
我们以一个观察性数据的场景为例,目标是估计“发放优惠券是否提升了用户的消费金额”,即平均处理效应(ATE)。
目标:估计 ATE:
ATE = E [ Y ( 1 ) − Y ( 0 ) ] \text{ATE} = \mathbb{E}[Y(1) - Y(0)] ATE=E[Y(1)−Y(0)]
由于 A A A 不是随机分配的(可能受到 X X X 的影响),我们不能直接比较处理组与对照组的平均值差异。
双重稳健估计器(EIF)公式
双重稳健(Doubly Robust, DR)估计器形式如下:
ATE ^ DR = 1 n ∑ i = 1 n [ μ ^ 1 ( x i ) − μ ^ 0 ( x i ) ⏟ plug-in 预测差 + a i e ^ ( x i ) ( y i − μ ^ 1 ( x i ) ) − 1 − a i 1 − e ^ ( x i ) ( y i − μ ^ 0 ( x i ) ) ⏟ EIF 修正项 ] \hat{\text{ATE}}_{\text{DR}} = \frac{1}{n} \sum_{i=1}^n \left[ \underbrace{\hat{\mu}_1(x_i) - \hat{\mu}_0(x_i)}_{\text{plug-in 预测差}} + \underbrace{\frac{a_i}{\hat{e}(x_i)}(y_i - \hat{\mu}_1(x_i)) - \frac{1 - a_i}{1 - \hat{e}(x_i)}(y_i - \hat{\mu}_0(x_i))}_{\text{EIF 修正项}} \right] ATE^DR=n1i=1∑n plug-in 预测差 μ^1(xi)−μ^0(xi)+EIF 修正项 e^(xi)ai(yi−μ^1(xi))−1−e^(xi)1−ai(yi−μ^0(xi))
代码:
import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
np.random.seed(0)
# 1️⃣ 模拟数据(观察性数据)
N = 1000
X = np.random.normal(0, 1, size=(N, 2)) # 两个协变量(如活跃度、访问频率)
X_df = pd.DataFrame(X, columns=['x1', 'x2'])
# 偏置的处理分配(不是完全随机的)
def treatment_prob(x):
return 1 / (1 + np.exp(- (x[:, 0] + 0.5 * x[:, 1])))
A = np.random.binomial(1, treatment_prob(X))
# 结果模型:Y 受到处理与特征共同影响
Y = 3 * A + X[:, 0] + 2 * X[:, 1] + np.random.normal(0, 1, size=N)
df = X_df.copy()
df['A'] = A
df['Y'] = Y
# 2️⃣ 拟合模型
# 拟合倾向得分模型(逻辑回归)
logit = LogisticRegression()
logit.fit(X, A)
e_hat = logit.predict_proba(X)[:, 1]
# 拟合结果模型 μ₀(x), μ₁(x)
rf0 = RandomForestRegressor()
rf1 = RandomForestRegressor()
rf0.fit(X[A == 0], Y[A == 0]) # 控制组
rf1.fit(X[A == 1], Y[A == 1]) # 处理组
mu0_hat = rf0.predict(X)
mu1_hat = rf1.predict(X)
# 3️⃣ 计算 EIF / AIPW 估计器
# 影响函数部分:
term1 = A / e_hat * (Y - mu1_hat)
term2 = (1 - A) / (1 - e_hat) * (Y - mu0_hat)
dr_ate = np.mean(mu1_hat - mu0_hat + term1 - term2)
# 4️⃣ 基准对比
# 直接 plug-in 模型:E[μ₁(x) - μ₀(x)]
plugin_ate = np.mean(mu1_hat - mu0_hat)
# 5️⃣ 输出结果
print(f"✔️ 估计的 ATE(双重稳健 EIF):{dr_ate:.2f}")
print(f"📎 估计的 ATE(仅 plug-in): {plugin_ate:.2f}")
我们有观察性数据:
- 特征变量 X X X:例如用户画像(活跃度、访问频率等);
- 处理变量 A A A:是否发放优惠券( A = 1 A = 1 A=1 表示发放);
- 结果变量 Y Y Y:用户的后续消费金额;
我们使用 EIF(高效影响函数)/ AIPW(Augmented Inverse Probability Weighting) 估计器,其代码如下:
dr_ate = np.mean(mu1_hat - mu0_hat + term1 - term2)
这边只是针对估计器进行简单的解释:
mu1_hat - mu0_hat
:机器学习模型预测该用户在处理组和对照组下的消费差异,但容易存在偏误。term1 = A / e_hat * (Y - mu1_hat)
:对实际拿到优惠券的用户,如果模型对 Y Y Y 预测有误,这个项做修正term2 = (1 - A) / (1 - e_hat) * (Y - mu0_hat)
:对未发券的用户,补偿 plug-in 模型预测误差- 组合成 EIF 估计器:
dr_ate = np.mean(mu1_hat - mu0_hat + term1 - term2)
为什么叫“双重稳健”,只要以下两者中有一个模型估计准确,就能保证估计器一致:
- 倾向得分模型 e ^ ( x ) \hat{e}(x) e^(x);
- 结果模型 μ ^ 0 ( x ) , μ ^ 1 ( x ) \hat{\mu}_0(x), \hat{\mu}_1(x) μ^0(x),μ^1(x)
3.1.4 EIF构造置信区间实践代码
基于 以上案例,构造双重稳健 ATE 估计器(dr_ate) 构造置信区间(Confidence Interval, CI)
由于双重稳健估计器涉及残差项和预测模型,理论推导其标准误较复杂,最常用的方法是 Bootstrap 置信区间,步骤如下:
- 重复多次从原始数据中有放回采样;
- 每次重新拟合模型、计算 ATE(即 dr_ate);
- 取若干分位数作为置信区间上下界。
from sklearn.utils import resample
import tqdm
def bootstrap_dr_ate(df, n_bootstrap=500, gamma=0.95):
ate_list = []
for _ in tqdm.tqdm(range(n_bootstrap)):
# 有放回采样
boot = resample(df, replace=True)
X = boot[['x1', 'x2']].values
A = boot['A'].values
Y = boot['Y'].values
# 倾向得分模型
logit = LogisticRegression().fit(X, A)
e_hat = logit.predict_proba(X)[:, 1]
# 结果模型
rf0 = RandomForestRegressor().fit(X[A == 0], Y[A == 0])
rf1 = RandomForestRegressor().fit(X[A == 1], Y[A == 1])
mu0_hat = rf0.predict(X)
mu1_hat = rf1.predict(X)
# 计算 EIF 估计
term1 = A / e_hat * (Y - mu1_hat)
term2 = (1 - A) / (1 - e_hat) * (Y - mu0_hat)
dr_ate = np.mean(mu1_hat - mu0_hat + term1 - term2)
ate_list.append(dr_ate)
# 置信区间计算
lower = np.percentile(ate_list, (1 - gamma) / 2 * 100)
upper = np.percentile(ate_list, (1 + gamma) / 2 * 100)
ate_mean = np.mean(ate_list)
return ate_mean, lower, upper
# 假设你已有 df,其中包含 'x1', 'x2', 'A', 'Y'
ate, ci_lower, ci_upper = bootstrap_dr_ate(df)
print(f"✅ ATE 估计值: {ate:.2f}")
print(f"📏 95% 置信区间: ({ci_lower:.2f}, {ci_upper:.2f})")
最终的结果为:
95% 置信区间: (3.03, 3.28)
4 论文代码解读
代码链接:
https://github.com/allentran/long-term-ate-orl
模拟数据生成的图,整体是模拟代码,就看个乐子:
Q函数
预测是通过 td_model.py 中的 QModel 类实现的,Q网络是用 Flax 构建的多层感知机(MLP),分别为 treatment 和 control 两套参数。
状态-动作对 ( s , a ) (s, a) (s,a)的 Q 值预测通过 s e l f . p r e d i c t ( p a r a m s , s , a ) self.predict(params, s, a) self.predict(params,s,a)(即 vmap_td_pred)实现,其内部会根据动作选择对应 Q 网络。
Q函数迭代目标采用贝尔曼方程:
t a r g e t = r t + g a m m a ∗ ( ( 1 − p i a 1 ) ∗ Q ( s ′ , a = 0 ) + p i a 1 ∗ Q ( s ′ , a = 1 ) ) target = r_t + gamma * ((1 - pi_a1) * Q(s', a=0) + pi_a1 * Q(s', a=1)) target=rt+gamma∗((1−pia1)∗Q(s′,a=0)+pia1∗Q(s′,a=1))
“行动倾向”(Propensity Score)
行动倾向 π(a|s)(propensity score)在这个模拟实验中是人为设定的参数(如 0, 1, 或 [0,1]之间的概率)。没有用机器学习拟合 propensity score,而是直接用已知概率(模拟设定)
高效影响函数
高效影响函数和双重稳健估计器是在 doubly robust 形式下实现的
def doubly_robust_pot_outcome(self, s, a, alpha_hat, q_s0, q_error):
w_sa = self.featurize_sa(s, a[:, None]).dot(alpha_hat)
return (1 - self.gamma) * q_s0 + np.multiply(w_sa, q_error).mean()
估计器形式为 “模型预测 + 残差校正项”,实现双重稳健(Doubly Robust)。
置信区间
是通过重复蒙特卡洛模拟(Monte Carlo),对每个设定(如 treatment period)多次估计ATE,并统计分位数。
figures.py 的 main 函数里,读取 qw_vs_surrogates.csv,计算各方法的 5%/95% 分位数作为置信区间:
lower_qw.append(subset['ate_qw'].quantile(0.05))
upper_qw.append(subset['ate_qw'].quantile(0.95))