他山之石————推荐系统中的跨域建模
推荐系统是在线服务的重要组成部分,特别是对于电子商务平台而言。在推荐系统中,转化率(CVR)预测对于优化电子商务的总交易额目标至关重要。然而,CVR存在众所周知的样本选择偏差(SSB)和数据稀疏性(DS)问题。虽然现有的方法ESMM和ESM2通过建模用户行为路径来训练所有展示样本,但是此方法也只是通过构建在某个特点场景下的行为路径来解决DS问题,而在实际的推荐系统中,面临的往往是有着不同性质的场景之间的样本稀疏问题。
这段时间梳理了几篇针对解决跨域建模等一系列问题的几篇论文,在这里整理一下。
全域学习
方法
为了解决推荐链路中的样本选择偏差问题和数据稀疏问题,我们提出了基于全域学习的信息流推荐全链路无偏学习解决方案,重新构建了概率空问,充分利用了推荐系统的漏斗结构,直接建模了漏斗结构中上一阶段汳回结果到正样本的概率,使得训练与预测在推荐系統中一致,从而消除样本选择偏差;同时模型引入全网的领域知识辅助本场景的排序模型学习,将上一阶段返回结果到王样本的概率进一步拆分成上一阶段返回结果到全网正样本的概率与全网正样本概率到本场景正样本概率的乘积,有效的解決了数据稀疏问题。
形式化定义
我们的研究主要集中在排序阶段,以GMV优化为目标的推荐模型可以拆解为:流量X点击率X转化率X笔单价,传统对$\text{CTR} \times \text{CVR}$的建模方式如下:$p_{pvTopay}=p(Click=1|Pv=1) * p(Pay=1|Click=1)$然而这样建模存在两个问题,一个是样本选择偏差问题,加上训练数据为曝光的样本,而预测的样本为推荐系统上一阶段的结果,例如精排模型的预测样本为粗排返回的结果,粗排模型的预测样本为召回返回的结果。存在训练和预测不一致的问题,进一步产生数据闭环导致问题加重;另一个问题是数据稀疏问题,在排序阶段往往只会用到本场景的曝光样本,忽略了用户在全场景的丰富行为。因此,如何解决样本选择偏差使排序阶段的训练和预测保持一致,以及如何在推荐系统的全链路阶段均引入用户在全场景的样本是非常重要的问题。
基于此,我们提出了基于全域学习的信息流推荐全链路无偏学习解決方案,重新构建概率空问,作为现有概率 $P{PvToPay}$ 的补充,同时引入用户在全网的行为,以此缓解上述问题。首先我们重新构建了概率空间,以精排模型为例,为了使训练空问与预测空间一致从而解决样本选择偏差问题,我们充分利用推荐漏斗式的结构,直接构建粗排返回结果到正样本的概率,即:$p{DrToPay}=p(Pay=1|Drr=1)$,
其中 ${Drr =1}$ 是粗排返回的结果集合。进一步的为了在排序的每个阶段均引1入用户在全网的行为从而缓解数据稀疏问题,我们将概率$P_{DrrToPay}$
进一步拆解成如下形式:
,其中 $p(Pay{all} =1|Drr =1) $是粗排返回结果到全网成交正样本的概率, ${Pay{all} = 1}$ 是粗排返口结果且用户在全网成交的样本集合,$P(Pay{gul}=1|Pay{all} =1)$ 是全网成交正样本到本场景成交正样本的概率,${Pay_{gul} = 1}$是最终在本场景的成交正样本集合。这样建模有3个优点:1)统一了模型训练和预测的候选数据集,以精排模型为例其训练样本集合与预测样本集合均是粗排返回的结果集合,不再存在线上预测与 离线训练不一致的问题,缓解了样本选择偏差问题;2)在推荐系统链路阶段显示且直接地建模了用户在全网的成交行为,建模推荐系统漏斗结构中上一阶段结果到全网正样本的概率,缓解了数据稀疏问题;3)建模全网样本到本场景样本的概率,从而使得排序模型的最终建模目标为本场景的正样本,更符合本场景的心智,滅少无用信息的引入,减少适合其他场景而不适合本场景的样本曝光。
最终精排模型建模了人粗排返回结果到本场景成交的概率,公式如下:
如上概率构建方式能够使得训练和预测的候选数据集保持一致,有效缓解数据偏差问题,同时在本场景有效引入全域领域知识,缓解数据稀疏问题。最终 $P{DrrToPay}$可以作为 $P{PvToPay}$的补充,在线上共同进行预测,最终以 GMV 为优化目标的问题形式化如下:
粗排模型的优化目标与精排类似,不同的是候选集合用到的一阶段的召回结果集合,建模了从召回到本场景成交的概率,形式化如下:
模型
模型的整体结构分为两部分,左边的一部分$p(Pay_a=1|PS=1)$建模的是上一阶段结果到全网成交的概率,右边一部分$p(Pay_g = 1|Pay_a=1,PS=1)$建模的是全网成交到本场景成交的概率。模型的整体结构如下:
Embedding Layer
模型的输入层是Embedding层,它将输入的大量稀疏特征映射到低维稠密的向量空间中,模型的输入特征主要包括用户特征画像特征、商品属性特征、上下文特征、交叉特征和行为序列特征。
Layer Normal Target Attention Layer
用于处理行为序列特征,该层捕获了目标商品Target item 与用户历史行为序列的相似性,考虑向量的物理意义,我们使用内积来计算Attention,两个item越相似,权重越大;并采用Mutil-Head Attention的方式有效的将序列特征放到多个平行的空间进行计算,提升模型的容错性和精准度。
MLP layer
得到所有特征的向量表示之后,最终将向量串联起来输入到 MLP Layer 中通过 Sigmoid 函数获得$p(Pay{all} =1|Drr =1)$ 。为了建模用户隐式反馈中的bias,比如 Position Bias, 很多时候用户点击某个商品井不是因为真的最喜欢这个商品,而仅仅只是因为其排序的位置比较靠前;User Bias,不同用户的点击偏好不同,有些用户就是具有较高的点击率,而另一些用户本身就偏爱浏览而不爱点击。模型分为 Mainnet 和 Biasnet, Mainnet 输入全部特征用于建模用户的隐士反馈,Biasnet 输入用户信息以及 position 信息用于捕捉隐式反馈中的 Bias。最终两个网络的输出相加,通过Sigmoid 函数获得$p(Pay{all} =1|Drr =1)$
损失函数
通过MLP Layer之后,最终的损失函数如下,训练数据集为上一阶段的正样本和随机负采样的样本集合,其中全网成交的样本标签为1,随机负采样的样本标签为0。
建模第二部分的损失函数同上,只是label和训练数据集不同。
CTNet
《Continual Transfer Learning for Cross-Domain Click-Through Rate Prediction at Taobao》
方法
分析现有的学术界和工业界的跨域推荐(Cross-Domain Recommendation,CDR)的相关工作,主要可分为两大类:联合训练 (Joint Learning)和预训练-微调 (Pre-training & Fine-tuning)。其中,联合训练方法同时优化源域(Source Domain)和目标域 (Target Domain)模型。然而,这一类方法需要在训练中引入源域的数据,而源域数据通常规模很大,从而消耗巨大的计算和存储资源,很多较小业务难以承担如此大的资源开销。另一方面,这一类方法需同时优化多个场景目标,场景之问的差异也可能带来目标冲突的负面影响,因此预训练-微调类方法在工业界很多场景有着更广泛的应用。
工业界推荐系统一个重要的特点是模型训练遵循连续学习 (Continual Learning)范式,即模型需要使用最新的用户反馈数据,利用离线增量更新 (incremental Learning)或在线学习 (Online Learning)等方式学习最新的用户兴趣分布。
对于本文研究的跨域推荐任务而言,源域和目标域的模型都是遵循连续学习的训练方式。我们由此提出了一个学术和工业上将有广泛应用的新问题:连续迁移学习 (Continual Transfer Learning),定义为从一个随时间变化的领域到另一个也随时间变化的领域的知识迁移。我们认为,现有的跨域推荐和迁移学习方法在工业推荐系统、搜索引擎、计算广告等的应用应当遵循连续迁移学习范式,即迁移的过程应当是持续的、多次的。原因在于用户的兴趣分布变化较快,只有通过连续的迁移才可以保证稳定的迁移效果。结合这一工业推荐系统的特点,我们可以发现预训练-微调在实际应用上的问题。由于源域和目标域的场景差异,通常需要用非常大规模的数据(例如数百亿样本)才可以利用源域模型调到一个效果较好的结果。而为了实现连续迁移学习,我们需要每隔一段时间都利用最新的源域模型重新微调,造成了非常巨大的训练代价,这样的训练方式也是难以上线的。此外,利用这些大规模的数据微调也可能使得源域模型遗忘掉保留的有用知识;利用源域模型参数去替换掉原有的目标域已经学好的参数也丢弃了原有模型历史上获得的有用知识。因此,我们需要设计一个更加高效,适用于工业推荐场景的连续迁移学习模型。
本文提出了一个简单有效的模型CTNet (Continual Transfer Network,连续迁移网络)解決了上述问题。不同手传统的预训练-微调类方法,CTNet的核心思想是不能选忘和丢弃所有模型在历史上获取的知识,保留了原有的源域模型和目标域模型的所有参数。这些参数中保存了通过非常久的历史数据学习得到的知识 (例如淘宝有好货的精排模型已经连续增量训练两年以上)。CTNet采用了简单的双塔结构,利用了一个轻量级的Adapter层将连续预训练 (Continually Pre-trained) 的源域模型中间层表示结果映射并作为目标域模型的额外知识。不同于预训练-微调类方法需回溯数据以实现连续迁移学习,CTNet只需要增量数据进行更新,从而实现了 高效的连续迁移学习。
问题定义
本文探讨的是连续迁移学习这一新问题:给定随时间变化的源域和目标域,连续迁移学习(Continual Transfer Learning)希望能够利用历史或者当前获得的源域和目标域知识提升在未来目标域上的预测准确率。本文提出的方法的应用场景具有以下特点:
- 不同的推荐场景规模相差较大,可以利用较大规模数据训练得到的源域模型的知识提升目标域的推荐效果
- 不同场景的用户和商品共享同一个大底池。但不同场景由于精选商品池、核心用户、图文等展示效果不同存在较为明显的领域差异。
- 所有推荐场景的模型都是基于最新收集是数据持续增量训练的。
上图展示了我们的方法部署上线的情景,在$t$时刻之前源域模型和目标域模型都是只利用各自场景的监督数据单独连续增量训练的。从$t$ 时刻开始,我们在目标域上部署了跨域推荐模型CTNet,该模型将在不能還忘历史上获取的知识的情况,继续在目标域数据上持续增量训练,同时连续不断地从最新的源域模型中迁移知识。
模型
我们在原有的目标域的精排模型中嵌入了源域模型的全部特征及其网络参数,形成一个双塔的结构,其中CTNet的左塔为源塔 (Source Tower),右塔为目标塔 (Target Tower)。不同于常见的只利用源域模型打分分数或只利用一些浅层表示(如Embedding) 的方法,我们通过Adapter网络,将源域模型MLP的所有中问隐藏层(特别是源域MLP深层蕴含的user和item的高阶特征交互信息)的表示结果 z°映射到目标推荐域,并将结果加入到Target Tower的对应层z中(如下面公式所示)。CTNet效果提升的关键就是利用了MLP中深层表征信息的迁移。借鉴Gated Linear Units(GLU)的思想,Adapter网络 ,采用了门控的线性层,可以有效实现对源域特征的自适应特征选择,模型里有用的知识会做迁移,而与场景特点不符的无用的信息就丢奔掉。由于源域模型持续不断的使用最新的源域监督数据进行连续预训练,在我们的训练过程中,Source Tower也将持续不断的加载最新更新的源域模型参数并在反向传播过程中保持固定,保证了连续迁移学习的高效进行。模型适用于连续学习范式,使得目标域模型持续的学习到源域模型提供的最新知识,以适应最新的用户兴趣变化。同时由于模型仅在目标域数据上进行训练,保证了模型不受源域训练目标的影响,同时完全不需要源域数据训练,避免了大量的存储和计算开销。此外,这样的网络结构借鉴了无损添加新特征的设计方法,实现了模型的热启动,Target Tower完全由原有的目标域线上模型初始化,Adapter的初始参数较小,可以在最大程度上保证原有模型的效果不受损害,仅需较少增量数据就可得到很好的效果。
UGIC
方法
预训练
在CV和NLP领域,预训练方法已经被广泛应用于各种主流任务中并取得了很好的效果,尤其在BERT横空出世后,大规模无监督预训练语言模型横扫了NLP各种任务。受BERT影响,CV领域的预训练工作也从有监督预训练开始向无监督预训练转向,MOCO、Simsiam、MAE等一系列优秀的无监督预训练工作也使得视觉领域无监督预训练模型在下游任务的效果可以媲美甚至超过有监督预训练模型。推荐领域的预训练模型也已经被广泛研究,如BERT4ReC,,S3Rec等。这些工作基本沿着预训练语言模型的思路将MLM任务迁移到了用户行为序列上进行预训练,并针对推荐系统的特点对预训练任务进行了一定的微调。
相比BERT4Rec这种无监督预训练方法,我们在实践中选择了一种更为简单的有监督预训练方案,这种选择主要基于以下两点考虑:1、用户在手淘app上的浏览点击行为天然的为我们提供了训练的标签,每天用户在猜你喜欢推荐页大概会产生接近100亿次的曝光行为,常年累月的数据积累使得我们可以轻松的获得海量的有标签数据进行预训练。2、仅在用户行为序列进行无监督预训练本质上还是仅利用了用户的正反馈行为进行表征学习,无法有效利用用户的曝光数据。基于以上考虑我们收集了用户在首猜场景的曝光/点击,点击/加购和点击/购买日志作为我们的预训练样本。其中曝光/点击样本占比超过了95%是预训练样本的主体,点击/加购和点击/购买样本的加入是希望我们的预训练模型可以学习到多种用户兴趣以服务多个下游模型。在用户行为日志的基础上我们构建了曝光/点击(clk)、点击/转化(CV)、点击/加购(cart)三种预训练预估任务,其中clk预估任务直接采用了常用的pointwise的交叉熵损失,cv和cart预估任务除了pointwise loss外还额外引 了pairwise loss来缓解任务的稀疏性,最后三个预估任务以multi-task的方式结合在一起,网络结构示意图如下
同时在实践中我们发现,预训练的样本量对最后的效果有着至关重要的影响,预训练样本量从1个月提高到6个月再到年,在预训练任务上的test auc指标分别会有1个百分点以上的提升,在下游任务的主模型中离线gauc也会从无任何提升到点几个千分点的提升再到4点几个千分点的提升,具体数据见在离线效果部分,因此我们最终上线的方案采用了用户过去两年在首猜上的行为日志作为我们的预训练数据。
特征选择&模型结构
如前文所述,用户每天在首猜场景会产生约100亿的行为数据,而我们的预训练任务的目标是要利用用户两年时间的累积数据。如此庞大的预训练数据量给我们的预训练任务带来了非常大的挑战,为了能够尽量加快模型训练速度,我们一方面尽量精简了模型的输入特征,另一方面也采用了尽量简单的模型结构。
具体而言,特征选择方面我们仅选择了主模型的极小一部分特征子集来构建我们的预训练模型,item侧特征我们仅保留了itemid、 cate id shop_id几个最重要的id特征,用户行为特征我们也仅保留了一条用户行为序列,整体特征量约是主模型的1%。除了主模型特征子集,我们也在预训练任务中加入了更为稀疏的user ic特征。user_id的全特征空间约有10亿+,在我们的主模型中直接加入这一特征会面临严重的过拟合问题(该现象我们目前仅有一些不成熟的猜想,还没有定论,也欢迎大家一起讨论),但是在大了两个数量级的预训练数据上,我们相信可以对更加稀疏的user_id充分的训练,同时user_id庞大的参数空间可以给我们的预训练模型提供更好的记忆性,从而得到更好的表征用于下游任务。
模型结构部分我们选择采用了最简单的DNN结构,同时仅在用户行为序列和target item之间加入了attention 模块,去掉了计算更加耗时的GRU等模块。通过特征逆择和模型结构的精简,以及batch_size的调整,与主模型相比,预训练任务的训练加速比提升了约100倍,除此之外,我们还对负样本进行了随机负采样,仅保留1/5的负样本来进一步加速训练,这些操作使得我们有能力在大约1周左右的时问里完成2年数据的预训练。
预训练任务的模型结构和特征精简本质上是在预训练模型能力和训练样本量之问进行trade off, 目前我们的经验来看预训练数据量的影响远大于精细的预训练模型结构的影响。
预训练知识表征
我们认为预训练好的预训练模型参数中encode了从预训练数据中抽取到的知识,因此我们用预训练模型一些层的输出作为预训练的知识表征。我们定义的预训练知识表征可以分为3个方面user-level, item-level, user-item-iteration-level。其中user-level的知识表征用userid的embedding来表示,记为$\mathscr{K}_u$,item-level的知识表征用item特征的embedding来表示,记为$\mathscr{K}_i$,user-item-interaction-level的知识表征用fc的倒数第二层输出表表示,记为$\mathscr{K}{ui}$,同时由于存在3个预训练任务,因此$\mathscr{K}{ui}$会有三种不同的表现形式分别记为$\mathscr{K}{ui}^{clk}$,$\mathscr{K}{ui}^{cv}$,$\mathscr{K}{ui}^{cart}$。最终我们将所有抽取到的知识concat到一起供给下游模型。
预训练知识表征与主模型融合
在利用预训练模型抽取到合适的知识表征之后,接下来就是要把抽取到的预训练知识表征合理的应用到下游任务中。传统的预训练模型在应用中通常是采用pre-training & fine-tuning机制,即在下游任务中,加载pre-training参数作为模型参数的初始化,然后在下游任务的训练样本上进行finetune。
然而这种pre-training & fine-tuning机制在实际的工业级推荐系统中并不完全适用。一方面,线上服务的模型常采用参数增量更新的ODL模式,即每次模型训练都会完全加载之前一个版本的模型参数,然后利用此后一段时间的训练数据进行参数更新,如此循环下去如下图所示。在我们的线上系统中,线上服务的模型己经滚动更新了超过1年以上的时间。在此模式下如果仅将预训练模型参数作为模型初始化,那在后续的增量训练过程中可能会遇到灾难遗忘问题(catastrophic forgetting),实践中我们也确实发现仅加载预训练参数作为下游任务模型初始化参数虽然能够有效的加快模型收敛速度,但是随着训练过程的进行,效果gap会逐渐缩小至完全无提升。另一方面,预训练模型同样也需要在用户行为日志上持续进行增量训练以捕捉用户最新兴趣,pre-training & fine-tuning机制也难以满足预训练模型的参数更新需求。
针对以上问题,我们采用了另一种预训练知识表征的融入方式,将预训练知识表征作为下游任务模型的额外输入,帮助下游任务更好的进行预估。同时为了够更好的保留主模型的网络结构,我们设计了一个Knowledge Plug-in Network结构,用加法操作代替了传统新加特征的concat操作。这种结构的好处一方面是得主模型可以加载之前版本的模型参数,避免了从随机初始化重新训练,实现特征“热后动”的功能。另一方面在预训练知识表征发生更新时(如新增了一组知识表征时)也可以通过finetune较少的模型参数快速上线,给预训练知识表征保留了一定的拓展空间
在线服务
到目前为止我们所尝试的算法方案都非常的简单,对于各种问题基本上就是直觉上的解法,并没有花里胡哨的模型结构设计和算法堆砌。然而预训练模型在工业级推荐系统的应用其实不仅是一个算法问题,一个通用的大规模预训练模型如果想在工业级推荐系统上大规模上线必须要解决好预训练模型的在线服务问题,即如何在满足线上存储和r约束的条件下,高效的服务好多个下游模型,并且不会影响下游模型的迭代节奏。接下来,我们将详细介绍我们将预训练模型在定向广告业务上进行线上服务的经验。
分解和退化策略
为了不给下游任务增加额外的算力负担,我们采用的是缓存策略将预训练模型提取到的知识表征cache在高性能参数服务器中,这样下游任务可以直接请求对应的预训综知识表征$\mathscr{K}(u,i)$而无需额外的实时计算。然而直接缓存$\mathscr{K}(u,i)$需要遍历所有的(u,i) pair,对于手淘约10^9量级的用户空间以及10^9量级的商品空问,组合起来的大(4,2)数量将达到恐怖的10^18,如此大的量级肯定无法直接缓存。对于这一问题我们设计了预训练知识表征的分解和退化策略。
分解策略是指将预训练模型结构分解成双塔结构,从user塔和item塔分别得到 $\mathscr{K}u,\mathscr{K}_i$然后用二者的乘积来表征$\mathscr{K}{ui}$。然而这种简单的双塔模型结构无法有效的捕捉 $\mathscr{K}_u,\mathscr{K}_i$之间的高阶交叉关系,因此在分解策略的基础上,我们又增加了退化策略。退化策略是指将模型的打分粒度人item粒度退化至更粗的cate粒度,因为cate的空间远小于item,使得我们可以直接遍历(u,c) pair进行缓存。
分解策略和退化策略的组合使得我们可以同时拥有细粒度的打分能力和复杂模型的特征交叉能力,并且预训练知识表征的缓存空间大小也从$N_uN_i$。减少到$N _u+ N_i+ N_uN_c$。
UGIC服务
定向广告业务繁多,旦每个业务场景下会包括粗排/精排两个阶段,每个阶段下又会有ctrlcvr/cart等预估模型,组合起来目前线上几乎有40+的模型在同时服务主流量,于此同时还有相当数量的实验模型在小流量服务。经过大规模预训练的知识表征可以认为编码了 用户长期且稳定的兴趣偏好,实验证明预训练表征至个场景多个阶段多个任务的下游模型均能带来一定的提升。为了能够方便的服务多个下游模型,我们将预训练知识表征服务从RTP中抽离出来,构建了UGIC(User General nterest Center)服务。具体而言,经过分解和退化策略,使得我们有能力将预训练知识表征在UGIC进行缓存,服务过程中,UGIC接收一个(u,i,c) 的pair,并返口对应的知识表征下$\mathscr{K}(u,i,c)$。同时考虑到预训练模型与下游模型的更新己经解耜,不同的下游任务可能会对应不同的预训练模型版本,为了保证在离线一致性,我们在UGIC中也增加了多版本的服务能力,下游任务可以根据自己特定的版本号v访问相应的预训练知识表征,具体过程如下图所示。