基于表征学习的因果推断技术在快手的实践
导读: 今天的主题是基于表征学习的因果推断技术实践。本次分享主要分为四大部分:
首先是工业界 RCT 实验规范,在工业界中,RCT 数据对因果建模来说非常重要,但很多时候,我们对 RCT 数据的收集操作是不规范的,导致我们在建模时使用的是错误的数据,这将让我们在损失预算的情况下拉低线上效果,本文将会讨论一些 RCT 数据收集上的经验;
第二部分是树模型与深度模型的联合建模,树模型是工业界用到最多的模型,是很多公司的 baseline 模型,而深度模型也是一个主流趋势,它可以让我们自定义设计更灵活的网络结构,文中将讨论如何融合这两类模型,从而发挥二者优势;
第三部分是 RCT 数据和观测数据的融合建模,RCT 数据虽然是无偏的,但是量少且贵,观测数据虽然有偏但是量大随处可得,所以我们希望通过 RCT 数据和观测数据融合建模,来提升数据量;
最后一部分是特征分解,它是目前比较热门学术研究方向,主要研究如何从特征里面去提取 confounder,adjustment variable 和 IV。
全文目录:
- 工业界 RCT 实验规范
- 树模型&NN 联合建模
- RCT&ODB 融合建模
- 特征分解
分享嘉宾|秦旋/余珊珊 快手 增长算法工程师
编辑整理|许振远 腾讯
出品社区|DataFun
01 工业界 RCT 实验规范
首先对 RCT 数据做一个简单介绍。RCT 为什么会有这么强大的魔力,为什么大家都在使用并且愿意投入大量的资金呢?主要原因有三点:
- Comparability and covariate balance
- Exchangeability
- No backdoor paths
1. Comparability and covariate balance
首先给出定义:如果协变量X的分布在任何 Treatment组下都是一致的,我们就说“we have covariate balance”。
用公式可以表达为: ,即 P(X|T=1) 和 P(X|T=0) 是同分布的。
换句话说,几个 treatment 组中,除了 treatment 本身以外,其他的全部都一样。而随机(Randomization)可以帮助我们保证这一点。
下面是一个证明,假设 population 分布是 P(X),在 t=1 时,P(X|T=1)=P(X);t=0 时,P(X|T=0)=P(X),无论 t 等于任何值的情况下,分布都是一样的。
更重要的是,在 RCT 数据情况下可以导致因果就是关联。推导的过程如下图中所示。最重要的是第四个等号,当 t 和 x 独立时,P(t|x)= P(t),然后接一个全概率公式就能得到在 do 算子条件下的 y 就等于控制住 t 条件下的 y,最终可以得到因果就是关联。这也是为什么我们在RCT数据上才能看到符合我们认知的数据现象。
2. Exchangeability
第二个是 Exchangeability 的成立,t 和 y 的潜在结果是独立不相关的。因为除了 t 本身以外,其它的x变量都是一样的,拥有相同的性质,所以就算它们的 treatment 换过来,其潜在结果也不会发生任何变化,注意这里是潜在结果不会发生任何变化而不是结果本身,因为我们只能观察到一种结果。
3. No backdoor paths
当我们拥有随机实验时,由于 t 跟 x 不再有关系,所以就没有了后门路径。
总结下来,RCT 数据是一个黄金准则。因为它可以带来天然的非混淆性质,使得我们可以用这些数据去进行更好的建模。但不幸的是,随机数据极其昂贵,并且经常伴随着伦理问题。所以在大多数场景下,随机数据是一个“奢饰品”。但是在这种奢侈品有限的情况下,如何得到一个尽量无偏的估计呢?这里提供两个思路,第一个思路是在有限的预算下,尽量把 RCT 做正确、高效,因为只有保证这一点,才能才保证建模是对的;第二个思路就是在有偏的观测数据下找到无偏的部分,然后和 RCT 数据去融合建模。
如果不使用 RCT 数据建模会有什么后果呢?举个例子,我们可能会观察到戴眼镜的人学习成绩更好,进一步思考:戴眼镜本身是不是真的会影响学习成绩呢?答案显而易见,不会。因为如果戴眼镜可以提高学习成绩的话,大家都不需要去学习,直接去戴眼镜就好了。再进一步想就会发现学习时间长的人更容易戴眼镜,而学习时间长的人学习成绩更好,所以我们才会观测到戴眼镜会提高学习成绩这个假的因果效应,这就是学习时长这个 confounder 带来的混淆。如果简单地使用观测数据进行建模,那就会造成有偏的估计。因此需要 RCT 数据进行建模。
随机数据的弊端,如下图所列,不再赘述。因此,我们需要科学、高效的 RCT 方案。
工业界有两种不同的 RCT 设计方式:Nested Design 和 Non-Nested Design。我们更希望得到的是 Nested Design,这也是用的最多的方式。当有一个目标 population 之后,直接从其中随机采样分成两组,一组作为 RCT 实验组,一组作为策略实验组。Non-Nested Design 则采取了不同的采样机制,经常是在医学或者比较复杂的业务场景下退而求其次的选择。
如何设计我们的 RCT 方案呢?
首先要明确 Target Population,在做用户增长或者做因果推断时,明确目标人群是非常关键的一点,而往往也是容易被忽略的一点。因为有些时候,有些用户可能并不在做策略的人群里面,所以也就不必要出现在我们的 RCT 数据里面。因此,我们需要提前把 RCT 目标人群的集合缩小,只有精确到最小才能有一个高效的 RCT 实验。
举例来说,在我们做策略的时候,往往对于某些特定用户有着特殊的规则,并且这些规则往往是容易被人忽视的。例如某些有着特殊性质的用户,经常被给予一种或少数几种 treatment。在进行 RCT 实验时,如果将这些人群加进来,就会导致各个 treatment 下的样本分布不均衡。
如果无法特别精确地定义 target population,那么最简单的解决方法就是在线上服务的时候,做好日志记录,在每一次样本落表的时候,都有一个记录且仅记录一条实际的策略 key,以便于进行正确的数据收取。但是最保险的方法还是要把 target population 精确到能力范围内最小。
第二,我们需要在实验前去 shuffle 流量,并且在实验中定期 shuffle 流量,这也是很容易被忽视的一步。很多团队的普遍做法是:在做 RCT 实验时,选择一个实验组,下掉之前的实验,然后直接在上面去做随机的策略。这就可能导致 RCT 组的分布和其他组的分布不一致。因为每个策略都会有各自长期带来的累积效应,如果累计时间长了特征无法AA实际上是不平的,用这样的数据训练出来的模型在另外一组上线可能会带来不好的效果。所以,定期 shuffle 流量是非常必要的一环。除此之外,RCT 实验本身在广义上也是策略的一种,同样会对实验组样本分布造成很大的影响,所以定期 shuffle 流量或者每次都从 whole population 中进行 RCT 数据的采样也是很重要的。
RCT 实验的特征选取方法有两种:第一种是用户维度,第二种是请求维度。
- 用户维度:一直给一个用户一个 Treatment 直到一个实验周期结束。
- 请求维度:每次请求过来,系统随机给予一个 Treatment。
具体使用哪种 RCT,可以基于业务需要选择。比如用户维度的 RCT 可以帮助观察 Treatment 的累积效应。请求维度的 RCT 可以帮助我们看到单次 Treatment 带来的因果效应,并在相同预算下获得更多的训练样本。
但是无论选择哪一种都需要保证没有post- treatment 特征。用户维度只能使用用户第一次请求前的特征,否则会造成特征穿越。请求维度只要是该请求前的特征都可以放心使用。
最后,介绍一个我们这边的主要做法:Online RCT。
相比于集中在某一个时间段开启一个大流量的 RCT,持续在线的小流量RCT 会更加经济有效。因为:
- 它让我们永远都有与当前 population 分布相近的随机数据
当前,我们使用的RCT数据收集于2022年10月,然而,当我们使用这份数据训练出的模型对目前的策略数据进行预估时,不论是预估值的分布,还是Treatment分布,都与RCT数据的测试集有着较大的差距,OnlineRCT可以帮助我们缓解这一点。
- 使我们能更加灵活地变更 treatment,避免浪费
之前,我们的 RCT 方式都是在一段时间内,大流量的开启 RCT 开关,一旦遇到 treatment 变更,就意味着我们之前的 RCT 实验数据不可用,造成时间和金钱的双重浪费。OnlineRCT 可以有效的帮助我们缓解这一问题。
- **它可以助力模型自动化更新 **
天级别的模型自动化更新功能已经应用在了很多场景下,也变成了一种趋势,但是,由于因果建模主要是使用 RCT 数据,所以如果没有高频率的数据更新,增量学习也就不现实了。OnlineRCT 帮助我们解决了这一点。
当我们收集到 RCT 之后,还需要有一套完备的校验工具,主要用来检查数据的无偏性,这一步同样很重要,如果不能保证数据质量,后面所有的模型搭建或者训练可能都是有问题的。
02 树模型&NN 联合建模
首先看一个很典型的因果图(见下图), U 是未观测到的混淆变量,C 是confounder,T 是 treatment,Y 是 outcome,A 是 adjust variable,IV 是工具变量。实际上,在工业界的因果图大多数情况下可以被简化成右边的图:未观测到的混淆变量没有了。在工业界很多场景下,可以假设没有未观测到的 confounder。由于 confounder 都是训练线上模型时使用的特征,所以大多数情况下都是可知的。我们可以做一个假设:即我们的策略都是由模型决定的,模型里面用到的特征都是 confounder。
在绝大多数公司里 RCT 建模的因果图中的 C 到 T 的边被取消了。
借助这张图,看下 NN 模型和树模型在建模因果效应时的不同方式。
下图是比较常见的 DRNet,大多数情况下都是通过这样的损失函数去训练网络参数。但是它存在一个问题,如果我们去训练多头神经网络,每个头是对 Y 的回归,那么得到的 Y 是 confounder 和 adjustment variable 共同的表征。但是,实际上对因果效应造成影响的只有 Confounder。因为网络并不是按照异质性建模,它只是一个回归模型,所以我们有可能把Y估计的很准。但是当我们去算因果效应时,在每一个头去减预测预估值时就会造成偏差。
举个例子,判断吃减肥药的效果。T 是吃不吃减肥药,Y 是体重,A 是在量体重之前有没有上厕所,模型会给 A 一个参数,如果A的参数不一样时去相减算因果效应,就会带来误差,这些误差就会放大最后因果效应的估计。
RCT 数据下,因果森林是基于异质性建模的,并且因果森林只在confounder 上进行分裂,换而言之,它只会在为因果效应提供信息的特征上去进行分裂。在刚才的例子中,量体重之前是否上厕所在各个叶子节点内被消掉了,所以不会在 A 进行分裂。所以 RCT 因果森林输出的因果效应就是 confounder 的表征。
树模型可以得到 confounder 的表征,而 NN 可以支持更个性化的结构。在这里给出两种思路:
- 思路1: 使用树模型生成的 confounder embedding 作为 NN 模型的特征。
- 思路2: 使用对抗学习做特征分解。本文的第四部分会详细解释。
03 RCT&ODB 融合建模
首先,介绍一下 PS matching 的方法,通过 PS 进行分层,在每一层内,通过计算 spiked-in estimator(分别计算每一层的 ATE),得到该层内的 causal effect,最终加权得到总体的 ATE。每个层下的 O 代表观测数据, R 代表 RCT 数据,K 是第 K 层。比如分 k 个桶,O(K) 就是在观测数据里面的第 K 个桶,R是在 RCT 数据下第 K 个桶。
因果效应有一个比较成熟的思路:假设在任意一层 tau_ok=tau_rk,对于每层的 causal effect,因果效应可以通过数据量的加权得到。这样一来,我们可以最终通过样本量加权得到总体 ATE。该方法的优点是,可以解决 PS 在极值处样本量小的问题。此时小量 RCT 数据也可以较好地提升 causal effect 的预估效果。这一套框架主要是想通过计算每一层的 spiked-in ATE,然后加权得到群体的 ATE,虽然这并不是我们想要的,但是我们可以借鉴 该框架融入到我们的系统里。
市面上的观测数据和 RCT 融合主要是解决两部分问题,一部分是 RCT 数据分布和观测数据分布不一致,第二是观测数据有偏,我们现在解决的主要就是观测数据有偏的问题。
我们的做法主要分为三步:
- 步骤一:分层 ,根据左侧图片,第一步是通过 propensity score 对样本进行分层,一个好的 PS 模型并不需要精准的划分样本属于 Treatment 组或者 Control 组的能力,而是要具有 covariate balancing 的能力。在这里,我们认为每一层的样本具有相同的性质。
- 步 骤二:观测数据到 RCT 的 covariate shifting,对观测数据采样,使得每层数据量和与之对应的 RCT 数据的数据量一致 。这部分的目的是为了拉齐 RCT 与 ODB 的数据分布,在之前的工作中,我们的方法为在每一层内,RCT 数据的样本数与 ODB 数据的样本数等比,通过这样的方式,可以使 RCT 和 ODB 中“同性质样本”等比,从而保证分布一致。
- 步骤三:观测数据 unconfounding 性质建立,该步骤是整套方法的核心。 对同层内的 Control 组和 Treatment 组数据进行采样,对于每个层i,使得 n_obs_ti/n_obs_ci=n_rct_ti/n_rct_ci,以此来构造一个对不同性质的样本,被分到 treatment 组和被分到 control 组的概率等比。
我们还有一套验证机制来判断分层分的是否准确。简单来说,看观测数据和 RCT 数据的 treatment 组中的 Y 和因果效应在每一层内是否一致,如果不一致需要用 RCT 数据去填充。
随着对因果方向的深入,我们认为用 GPS 进行聚类不太合理。因为 Propensity Score Vector 并不是协变量 X 的表征,除了 X,在对 T 进行回归的时候往往会无形的加入其他特征,那就是工具变量,所谓工具变量,就是不直接影响 Y,只会通过影响 T 从而影响 Y。如果在做分层的时候,使用的是包含 IV 的表示,那么会严重影响分层效果。举例来讲,补贴预算不会直接影响用户的活跃度,但是会通过影响用户得到激励的几率影响他的活跃度。如果将此类特征放到 PS 模型中,则在分层时会严重依赖该特征,反而影响其他 X 的 balancing 情况,所以我们必须想办法将这类特征过滤出去。有一篇论文论证了为什么 IV 会导致 Propensity Score Inconsistency。
前文中提到了树模型的性质,只在 confounder 上进行分裂,得到的树模型输出的因果效应就是 confounder 的 embedding。
下图中可以看到只有 confounder X 对因果效应提供了信息。如果把 confounder 作为聚类的特征,发现特征在每层内的协变量平衡效果会有非常大的增强。
下面是我们这套系统的几个模块:
- 因果模型模块,该模块存在的目的是获得纯 confounder 的 embedding。可嵌入任何模型,基于目前的认知,使用 RCT 数据和因果森林训练出的 uplift 是比较纯的 confounder embedding。
- 聚类模块,该模块存在的目的是基于 confounder 的 embedding(输入自因果模型模块)获得准确的样本分层,在层内 control 组和 Treatment 组的分布一致,RCT 数据和观测数据分布一致。
- covariate shifting 模块,观测数据到 RCT 的 covariate shifting。
- deconfounding 模块,观测数据 unconfounding 性质建立。
- 基于假设检验的校验模块,假设检验校验机制。
- 评估系统,在一套系统中,评估机制是必不可少的,为此,我们开发了兼容所有 stratification 方法的评估系统,评估内容如下图。
04 特征分解
前面介绍了基于 RCT 数据和观测数据融合建模的一些工作,可以看到,RCT 样本难以构造且价格昂贵,所以我们尝试直接在观测样本上进行建模。在 DNN 建模中引入更多观测样本可以提升模型拟合效果和表达能力,但是引入观测样本的同时会引入 bias。现有大部分工作都是通过样本 Reweighting/Balancing 技术消除 bias,经典的方法有:DragonNet、DML、特征分解等。
下面主要介绍特征分解的原始做法(参考发表在 TKDE2022上的一个工作),以及我们落地时做的一些改进。基于因果图(右边的图)可以看到,协变量 X 分解成工具变量 I,混淆变量 𝐶 和调整变量 A,从而准确地分离出 C 和 A 去预估 outcome(y),消除因为引入观测数据带来的 bias。从图中可以看到工具变量 I 是只影响 treatment,混淆变量 C 会影响 treatment 和outcome,调整变量 A 只会影响 outcome。
论文中举了一个吃药的例子,treatment 是吃不吃药,outcome 是是否恢复健康。在病人的这些特征里面,收入和主治医生是工具变量,只会影响 treatment;年龄和性别是混淆变量,会同时影响 treatment 和 outcome,因为医生在选择 treatment 的时候会考虑病人的年龄和性别,而病人的年龄和性别也会影响恢复健康的概率;基因和环境是调整变量,只会影响 outcome。
要准确地将协变量 X 分解为三个不同类型的隐变量,做法如下:
- 首先从 X 中分解 A,需要满足以下两个条件:一个是调整变量 A 和 T 独立,目的是约束其他变量的信息不会嵌入到调整变量A中。因为从因果图上可以看到,工具变量 I 和混淆变量 C 跟 T 之间是有关系的;另一个是调整变量A能够尽可能精准地预估 Y,从而保证A的信息不会嵌入到其他变量中。
- 然后是从 X 中分解 I,如果balancing做得好,C 和 T 之间将没有依赖,那么在给定𝑇的情况下 I 和 Y 独立。这是因为做好不同treatment下 confounder 的平衡后,C 和 T 之间的因果效应被去掉了,当给定 T 时,I 和 C、I 和 Y 之间都是独立的,从而保证其他变量的信息不会嵌入到工具变量 I 中。同时 I 需要尽可能精准地预估 T,保证 I 的信息不会嵌入到其他变量中。
- 最后基于分解后的 C 和 A 去预估事实和反事实结果。
基于上述分析,设计了以下几个 loss 来分解协变量 X:
- 首先分解 A,通过最小化不同 treatment 下 𝐴 的分布差异实现 𝐴(𝑋)⊥ 𝑇,同时最小化基于 𝐴 预估 𝑌 的损失。disc(·) 表示不同 treatment 下分布的差异,可以用 IPM、MMD、Wasserstein distance 等度量函数来衡量。
- 其次通过 balancing 不同 treatment 下 𝐶 的分布去掉 C 和 𝑇 之间的依赖,实现 𝐶(𝑋)⊥𝑇。𝑤 为可学习参数,是样本层面的一个加权。
- 然后通过最小化不同 treatment 下 𝐼 分布的差异实现 𝐼⊥𝑌 | 𝑇,同时最小化基于 𝐼 预估 𝑇 的损失。同样这里也在样本层面利用 𝑤 进行了加权。
除了上述几个 loss 之外,为了避免过拟合和分解不干净,论文中还增加了正交正则化来改进效果。以𝐼为例,认为权重矩阵 表示输入 𝑋 中的每个变量对输出 𝐼(𝑋) 的贡献。 和 同理。所以如果协变量 𝑋 能够充分分解成 I,𝐶,A,这些权重矩阵应该是正交的。此外为了防止学出来的权重都是零,约束各维权重和为 1。
以上就是论文中给出的特征分解的做法,在我们落地的过程中对其做了一些优化。
- 首先论文中主要是针对 0/1 treatment 的情况,我们将它升级为多 treatment,并且引入多头结构,每个 treatment 生成对应的 I,𝐶,A 表征。
- 其次在平衡 confounder 的步骤中,使用 IPW 替代可学习参数 来平衡样本。对于多 treatment,基于 𝐶 的表征预估 treatment,从而得到对应的权重。
- 最后引入对抗 loss 来保证变量之间独立。
论文中是通过最小化不同 treatment 下的分布差异来保证变量之间独立,基于欧式距离、cosine 距离以及 mmd 等度量函数来衡量分布差异的大小。我们的目标是变量之间无关,不包含有用的信息量,用不同 treatment 下分布相似来表达和 treatment 无关不够直观。此外,分布相似度度量函数计算量比较大,在大规模样本且多 treatment 的情况下需要大量的计算资源。因此我们尝试从信息的角度考虑,通过约束 𝐴(𝑋) 中不存在信息可以去预估 𝑇 来保证 A 和 T 独立。
基于这个想法,我们引入对抗 loss,目标是让 A(X) 无法准确预估 T,即对于多treatment,预估概率都是 1/n,n 是 treatment 的个数。首先使用预训练网络作为判别器,固定 A 的表示,更新判别器参数,使其尽可能准确地预估 T。然后固定判别器,更新 A 的表示,使其尽可能准确地预估 fake label(1/n)。循环训练,直至达到目标。此时 A 中不存在信息可以预估 T,达到 A 和 T 独立的目的。
以上就是本次分享的全部内容。
最后,欢迎对因果推断感兴趣或者有经验的人才加入我们,谢谢大家!
05 问答环节
Q1:基于观测数据做 debias,需要同时考虑模型的相关性和 debias 的效果,在这种情况下,如何在有限的数据中进行离线评估?
A1:这个是一个很好的问题,我们基于观测数据去做建模的时候,或者在对观测数据进行去偏的时,经常需要去看看 debias 的效果。如果没有 RCT 数据,我们的做法是,对样本在 propensity score 上做分层,如果每一层底下样本是同质的,就可以观察到 treatment 组和 control 组的比例就是全量样本中 treatment 组和 control 组的比例。在这种情况下,就说明 debias 做的不错。
Q2:用户维度的 RCT 不断有新用户涌入是否会导致通不过 AA 校验?
A2:不论是用户维度还是请求维度,新用户进来的时候也是随机的会被划分到某一个组。用户落在每一个组里面的概率是相等的。如果每个用户落在每一个组的概率相等的,就不会造成 treatment 组之间 AA 特征的变化。
Q3:长期的 online RCT 是否会违反用户的公平性原则或者带来潜在的 RCT 问题?
A3:需要我们在设计 RCT 的时候考虑到这一点,如果你的业务容易造成这样的 PR问题,需要在设计 RCT 的时候想好应对方法。如果是业务本身风险性就较高,那可能 RCT 本身就不是一个可以去上线的策略了。
Q4:关于长期 online RCT 怎么做模型效果评估?分享中提到用户粒度的特征只能用treatment 之前的,长期 online RCT 怎么做?
A4:做法和上文提到的特征构建方式相同。
Q5:关于表征学习学习出来的 Wi 和倾向性得分可以具体对应上吗?
A5:使用倾向性得分 IPW 去代替 w,出发点是因为整体 loss 设计已经比较复杂了,可以看到针对各个分解的变量设计了不同的 loss,如果最终还要去学参数 w,从实践来看是比较难学习的。而 IPW 比较成熟,在我们落地过程中也被验证过,效果是比较好的。
|分享嘉宾|
秦旋
快手 增长算法工程师
毕业于美国波士顿大学,清华大学计算机系研究员。曾在滴滴出行任职高级算法工程师,研究方向为因果推断。曾自主开发了一套适用于工业界的RCT&观测数据融合算法。参与开发基于SPARK的分布式因果森林,并进行改造与升级。该工作在网约车智能定价业务上多次取得ROI收益。加入快手后,负责裂变场景下RCT数据流的规范化开发与树模型&深度模型的联合建模。
余珊珊
快手 增长算法工程师
浙大硕士,2020年加入快手,现主要工作内容为基于表征学习的因果推断方法在裂变场景的业务落地和技术创新。