- 文献阅读:Towards Out-of-Distribution Sequential Event Prediction:A Causal Treatment
- 1. 问题描述
- 2. 方法 & 模型设计
- 1. loss定义
- 2. 模型设计
- 3. 实验 & 结果
- 1. 基础实验
- 2. CaseQ策略细节分析
- 4. 结论 & 总结
- 文献链接:https://arxiv.org/abs/2210.13005
1. 问题描述
这篇文章是我最近刷到的一篇工作,和我最近的工作有一点相似,所以就想拿来参考一下。
这篇文章针对的主要训练数据与线上服务的数据偏差问题。
具体而言,当前推荐模型的训练模型往往都是采用历史某一个时间段内的真实点击数据拟合用户与商品之间的关联性,从而预测未来某个时刻用户对于某一个商品的感兴趣程度,并用ctr或者cvr进行表征。
但是这样一来会带来一定的问题:
- 历史训练数据所处的时间段与线上服务的时间存在一定的gap,导致商品的分布与线上服务当中真实的商品数据分布存在一定的偏差,劣化模型的效果,且这种劣化作用会随着时间的增长而增大。
举例来说,如果用户上次浏览点击的时候是夏季,看了几件T恤,然后半年过去了,他在冬季重新浏览了一下,这个时候他更可能买羽绒服,而不会是T恤,虽然显然后者与用户的浏览历史关联度更高。更极端的,一个用户如果在08年的时候浏览过手机,那可能他点了一堆诺基亚,而到了22年,苹果华为早已是主流了,诺基亚可能都已经不存在这个商品类目了。
因此,这篇文章就尝试搞定上述问题,他们的方法也比较直观,就是在事件(商品点击)当中引入事件发生时的context信息,从而使得上述这种随时间增加而产生的商品分布偏差可以尽可能地被抹除。
2. 方法 & 模型设计
如前所述,这篇文章的核心方法就是在事件的预测当中引入context信息。
但是这里也存在一定的问题,主要就是隐私保护的问题,使得事实上现在我们基本都不太能够获取到用户点击发生时的context信息。
而文中针对这个问题的处理文中使用的方法也是相对来说比较巧妙的,就是先预先设计K个context场景,然后使用贝叶斯概率的方式将其耦合入最终点击的预测,某种意义上来说,就是先去预测每一个context下用户点击发生的概率,然后根据每一个context发生的概率对其进行一下加权求和,最终得到不同综合情况下用户的点击概率。
具体可以参考下图:
下面,我们首先来看一下loss的数学定义,然后来看一下文中给出的模型实际的构造方法。
1. loss定义
这里,模型的loss定义本质上就是如下条件表达式:
P θ ( Y ∣ d o ( S ) ) = P θ ( Y ∣ S , C ) = ∑ i = 1 ∣ C ∣ P θ ( Y ∣ S , C = c i ) ⋅ P ( C = c i ) \begin{aligned} P_{\theta}(Y|do(S)) &= P_{\theta}(Y|S,C) \\ &= \sum\limits_{i=1}^{|C|} P_{\theta}(Y|S,C=c_i) \cdot P(C=c_i) \end{aligned} Pθ(Y∣do(S))=Pθ(Y∣S,C)=i=1∑∣C∣Pθ(Y∣S,C=ci)⋅P(C=ci)
而通过附录B中给出的推导,我们可以使用Jensen不等式直接将上式放缩为:
P θ ( Y ∣ d o ( S ) ) ≥ E c ∼ Q ( C ∣ S = S ) [ l o g P θ ( Y ∣ S = S , C = c ) ] − D K L ( Q ( C ∣ S = S ) ∣ ∣ P ( C ) ) P_{\theta}(Y|do(S)) \geq E_{c\sim Q(C|S=S)} [logP_{\theta}(Y|S=S,C=c)] - D_{KL}(Q(C|S=S) || P(C)) Pθ(Y∣do(S))≥Ec∼Q(C∣S=S)[logPθ(Y∣S=S,C=c)]−DKL(Q(C∣S=S)∣∣P(C))
其中, Q ( C ∣ S = S ) Q(C|S=S) Q(C∣S=S)为模型拟合的在行为序列 S S S情况下场景(context) C C C的发生概率。
而关于 P ( C ) P(C) P(C)的计算,可以通过下述表达式来近似:
P ( C ) ≃ 1 N ∑ i = 1 N Q ( C ∣ S = S i ) P(C) \simeq \frac{1}{N}\sum\limits_{i=1}^{N}Q(C|S=S_i) P(C)≃N1i=1∑NQ(C∣S=Si)
当然,完整计算上式的复杂度太高,因此文中对其进行了简化,只从中sample了一些样本进行近似拟合:
P ( C ) ≃ 1 R ∑ j = 1 R Q ( C ∣ S = S j ) P(C) \simeq \frac{1}{R}\sum\limits_{j=1}^{R}Q(C|S=S_j) P(C)≃R1j=1∑RQ(C∣S=Sj)
其中 R ≪ N R \ll N R≪N。
由此,我们事实上就将上述loss表达式完全转换成了 P θ ( Y ∣ S , C = c i ) P_{\theta}(Y|S,C=c_i) Pθ(Y∣S,C=ci)与 Q ( C ∣ S ) Q(C|S) Q(C∣S)的表达式了。
因此,我们只需要用模型给出 P θ ( Y ∣ S , C = c i ) P_{\theta}(Y|S,C=c_i) Pθ(Y∣S,C=ci)与 Q ( C ∣ S ) Q(C|S) Q(C∣S)即可。
2. 模型设计
下面,我们来看一下文中给出的具体模型设计。
首先,文中对于行为序列中的每一个行为的embedding映射倒是一个非常简单的行为,就是一个基础的one-hot embedding的lookup,记作:
h m 1 = O n e H o t ( x m ) T ⋅ H x h_m^1 = \mathop{OneHot}(x_m)^T \cdot H_x hm1=OneHot(xm)T⋅Hx
然后,通过一个神经网络(比如RNN或者Self-Attention网络),可以将其投影到一个输出的embedding:
[ h 1 2 , h 2 2 , . . . , h t 2 ] = Φ ( [ h 1 1 , h 2 1 , . . . , h t 1 ] , c ( t ) ; Θ ) = ∑ k = 1 K c ( t ) [ k ] ⋅ Φ k ( [ h 1 1 , h 2 1 , . . . , h t 1 ] ; Θ k ) \begin{aligned} [h_1^2, h_2^2, ..., h_t^2] &= \Phi([h_1^1, h_2^1, ..., h_t^1], c(t); \Theta) \\ &= \sum\limits_{k=1}^{K}c(t)[k] \cdot \Phi_k([h_1^1, h_2^1, ..., h_t^1]; \Theta_k) \end{aligned} [h12,h22,...,ht2]=Φ([h11,h21,...,ht1],c(t);Θ)=k=1∑Kc(t)[k]⋅Φk([h11,h21,...,ht1];Θk)
其中,关于 c ( t ) [ k ] c(t)[k] c(t)[k]的计算,文中是一个attention层的输出 q t q_t qt来进行模拟的,具体而言,就是将输入向量 h t h_t ht映射到 k k k个归一化权重上:
q t = Ψ ( h t 1 ; Ω ) q_t = \Psi(h_t^1; \Omega) qt=Ψ(ht1;Ω)
其中 ∑ k = 1 K q k = 1 \sum\limits_{k=1}^{K}q_k = 1 k=1∑Kqk=1。
具体其中的映射关系为:
q t [ k ] = e x p ( ( s t k + g ) / τ ) ∑ k = 1 K e x p ( ( s t k + g ) / τ ) s t k = a k ⋅ t a n h ( W k ⋅ h t ) \begin{aligned} q_t[k] &= \frac{exp((s_{tk} + g)/\tau)}{\sum\limits_{k=1}^{K}exp((s_{tk} + g)/\tau)} \\ s_{tk} &= a_k \cdot \mathop{tanh}(W_k \cdot h_t) \end{aligned} qt[k]stk=k=1∑Kexp((stk+g)/τ)exp((stk+g)/τ)=ak⋅tanh(Wk⋅ht)
此时,输出层的向量就可以表达为:
[ h 1 2 , h 2 2 , . . . , h t 2 ] = ∑ k = 1 K q t [ k ] ⋅ Φ k ( [ h 1 1 , h 2 1 , . . . , h t 1 ] ; Θ k ) [h_1^2, h_2^2, ..., h_t^2] = \sum\limits_{k=1}^{K} q_t[k] \cdot \Phi_k([h_1^1, h_2^1, ..., h_t^1]; \Theta_k) [h12,h22,...,ht2]=k=1∑Kqt[k]⋅Φk([h11,h21,...,ht1];Θk)
由是,我们来看一下文中最终给出的CaseQ模型结构的loss函数定义。
首先,关于模型的预测结果,这部分其实和传统的定义差不多,就是拿最后一层的输出和全部商品计算内积取最大值:
y ^ t = a r g m a x m ∈ { 1 , . . . , M } ( H x ⋅ h t D + 1 ) [ m ] \hat{y}_t = \mathop{argmax}_{m \in \{1, ..., M\}} (H_x \cdot h_t^{D+1})[m] y^t=argmaxm∈{1,...,M}(Hx⋅htD+1)[m]
因此,此时完整的loss定义函数就可以表达为:
L = ∑ S ∑ t = 1 ∣ S ∣ − 1 [ l ( y t , y ^ t ) + α D K L ( q t ∣ ∣ 1 R ∑ j = 1 R ( q ( S j ′ ) ) ) ] L = \sum\limits_{S} \sum\limits_{t=1}^{|S|-1}[l(y_t, \hat{y}_t) + \alpha D_{KL}(\bold{q}_t || \frac{1}{R} \sum\limits_{j=1}^{R}(\bold{q}(S_j')))] L=S∑t=1∑∣S∣−1[l(yt,y^t)+αDKL(qt∣∣R1j=1∑R(q(Sj′)))]
其中,这里的 q t \bold{q}_t qt定义略微复杂,具体表达如下:
q t = F l a t t e n ( ⊗ l = 1 D q t l ) ∈ R K D \bold{q}_t = \mathop{Flatten}(\mathop{\otimes}\limits_{l=1}^{D}q_t^{l}) \in \mathcal{R}^{K^D} qt=Flatten(l=1⊗Dqtl)∈RKD
其中, K K K为context种数,然后 D D D为模型层数。
3. 实验 & 结果
下面,我们来看一下文中给出的实验以及对应的结果如下:
1. 基础实验
这里的实验设计其实主体上就是在推荐数据集上测试一下效果,考察一下基础指标是否有变得更好,以及随着时间gap的增加,指标降低是否弱于原始模型。
这里,文中采用了如下几个测试数据集:
- Sequential Recommendation
- Movielens;
- Yelp;
- Event Prediction
- Stack Overflow;
- ATM;
两类实验下的具体实验结果如下图所示:
可以看到:
- 当测试集紧邻训练数据时,CaseQ不会损伤模型的效果,反而会带来小幅的指标提升;
- 当测试数据与训练数据的gap增大时,CaseQ
- 针对不同类型的基础模型,CaseQ策略总是有效的;
- 针对两类不同的任务,CaseQ同样是有效的;
2. CaseQ策略细节分析
然后,文中还对Context进行了更为细致的考察。
首先,文中看了一下对于不同的时间gap下输出与不同的context之间的关联关系如下:
可以看到:
- 不同时间gap下,context的分布之间存在明显的差异,因此可以认为context确实学到了与时间gap之间的关联关系。
此外,为了更好地说明context之间的差异性,文中还将context投影到了二维空间当中,看了一下context之间差异性。
从上图中的Figure5中可以看到:
- 随着训练的深入,不同的context之间的差异会逐渐变大,说明随着训练的深入,不同的context确实能够表征不同的特征。
另外,文中还考察了CaseQ模型的可扩展性,如上图中的Figure6中显示的:
- 模型训练以及预测的耗时 t t t近似有 t ∝ K × D t \propto K \times D t∝K×D,即两者近似呈线性关系,因此存在着良好的可扩展性。
最后,文中还对context的超参进行了考察,如上图中Figure7中展示的:
- 一定范围内, K × D K\times D K×D的增大可以带来效果的增益,但是并不是越大越好,太大反而会对结果有所伤害。
4. 结论 & 总结
结论而言,这篇文章的核心思路其实就是引入一个新的变量context来模拟不同场景,然后分别计算不同场景下的事件发生概率,最后对其使用context发生概率来进行加权求和来优化模型的效果。
这个思路其实也不算有特色,至少我们的实际业务场景里面事实上很早就用到了,虽然是出于不同的出发点,但是真实的模型结构其实大差不差。
但是,这里比较惊艳我的还是这里的loss函数的变化,感觉有一试的价值,回头可以在我们自己的业务上面试试看效果,虽然我还是不太理解这为啥可以work,总感觉怪怪的……