本文是推荐算法实战系列第11篇文章。
前面文章包括:
- 推荐系统简介
- 特征工程
- embedding
- 精排
- 召回(1):传统召回以及召回中的loss设计
- 召回(2):word2vec召回、FM召回和双塔召回
- 召回(3):图卷积
- 粗排
- 重排
- 多任务与多场景(1)
本文介绍多场景。
1、 多场景与多任务的异同
多场景主要关注推荐场景下不同的消费模式。它们之间既有差异性也有共性,如何在不同场景间进行信息的共享与迁移,同时避免相互干扰是多场景建模的主要目标。
- 同一个APP,“单列模式”与“双列模式”是不同的场景,两种产品模式下用户的行为模式有差异。
- 同一个APP,不同国家用户的消费模式有差异。
- 同一个APP,不同生命周期和活跃度的用户,需要推荐系统有不同的应对策略。例如,低活用户,推荐结果以热门物料为主;高活用户,以个性化为主。
多场景建模的本质是,不同场景下的数据分布不完全一致,所有场景的数据混在一起,用同一个模型无差别建模会导致模型主要由热门人群、物料主导。哪个群体贡献的样本多,模型对它更友好。那些小众的人群、物料、模式容易被模型忽略。
每个用户群体专门训练一套模型,实现起来有难度。有些小众场景,数据稀疏,模型训练不充分。同时维护多套模型成本高昂。近年来涌现出一批多场景建模的方法。
2、特征
第一种方式,基于特征工程。
首先,设计出能够区别不同场景的“场景指示特征“(Scenario Indicator)。例如:
- ”APP模式”特征能够区分单列还是双列。
- “国籍”、”语言”特征可以区分不同国家的用户。
- “近7天活跃天数”、”是否新注册用户”、“用户是否登录”等可以区分低活用户和高活用户。
接下来,需要考虑这些特征如何引入模型。如果直接将它们加在输入层,可能被其它特征淹没。解决方法是,重要特征尽量加的浅。
- 场景指示特征经过一个单独的浅层网络,得到$logit_{scene}$。
- 其它特征经过常规主网络,得到$logit_{common}$。
- 最终logit是上述两个logit之和。$CTR=sigmoid(logit_{common} + logit_{scene})。$
这种方式,场景指示特征对最终预测结果的影响直接有力。
它的潜在问题是,主网络的影响被削弱。一种解决方案是,对浅层网络的输出加dropout,并且通过dropout的比率平衡主网络和浅层网络的影响程度。
3、模型结构
多场景模型由两大部分组成:
- 场景共享部分:主要建模不同场景的共性部分。
- 场景独立部分:主要建模不同场景的个性部分。
3.1、Split&Merge
最简单的实现形式是将共享结构与各场景独立结构串联起来。类似于上一节多任务重的share bottom方式。
- 假设有两个场景A和B。
- 输入每个batch的样本包含A、B两个部分。
- 所有样本输入share bottom共享部分。
- 其输出根据场景指示特征split成两段(segmentation)。
- SegmentA只包含场景A的样本,经过场景A的专有塔TowerA,得到场景A的输出predA(备注:场景A的输出logits?)。
- 同理,SegmentB经过TowerB得到predB。
- 最后,不同场景的输出Merge到一起,与包含场景A和B的Label计算loss。
这种实现方式下,每个batch内既有场景A的样本,也有场景B的样本,共用一个loss。
它的共性体现在:
- 底层网络,尤其是embedding部分是共享的。
- loss共享。共享loss导致TowerA受场景B的样本影响。(备注:如何让towerA不受场景B的样本影响?)
差异性体现在:
- towerA和towerB的参数是独立的。(备注:merge之后的操作无参数。towerA中包含MLP到logits的所有参数?)
- (备注:线上预测取哪个tower的结果?)
它与MMOE的异同表现在:
- 不同的tower可以看做不同的expert。
- 但是,不同expert的输出不需要融合。即每个tower得到各自的logits。不同tower之间无信息共享。
- 在MMOE中,每条样本要经过所有的网络结构,最后在output阶段,与多个label计算多个loss。
- 在多场景下,每条样本只经过一个expert塔。
3.2、HMOE
HMoE是阿里2020年提出的模型。
上述Split&Merge结构中,不同tower相互独立,每个场景的样本只经过自己的tower。
HMoE认为,对某条样本,除了它所在场景tower的打分,其它场景tower的打分也有借鉴意义。它引入了MoE结构,同时对不同场景样本的反向传播做了隔离。
具体而言:
- 假设有两个场景A和B。
- 输入每个batch的样本包含A和B两个部分。
- 所有样本输入share bottom部分。
- 其输出根据场景指示特征分成两段,SegmentA和SegmentB。
- 每个场景有独立的expert,towerA和towerB。
- segA经过towerA,得到场景A的预估分$S_{AA}$。
- segA经过towerB,得到towerB对场景A的预估分$S_{BA}$。为了防止segA把towerB带偏,计算$S_{BA}$时应该执行stop-gradient,即segA的样本不参与towerB的反向传播,只执行towerB的前向传播。
- 两个tower的输出通过gate网络的输出权重$W_A$融合,得到predA
- (备注:不同场景共享一个gate网络吗?gate网络的输入包含所有场景的样本吗?输出有多个W吗?)
- 同理,得到场景B的融合输出predB。
- 不同场景的输出merge到一起后,与包含场景A和场景B的label计算loss。
3.3、STAR
阿里于2021年提出了STAR模型。每个场景有自己独立的MLP负责建模场景个性信息,所有场景有一个共享的MLP负责建模共性信息。 个性塔和共性塔的参数按位乘得到每个场景的参数。
其原理如下:
\[\begin{aligned} y_p &= DNN(x_p; W_p^*) \\ W_{p^*} &= [W_{p,1}^*,...,W_{p,K}^*] \\ W_{p,i}^* &=W_{p,i} \otimes W_i \end{aligned}\]- 第p个场景的输入$x_p$,经过一个DNN,得到该场景的输出$y_p$。其参数为$W_p^*$。
- $W_{p,i}^*$是DNN的第i层的权重,总共有K层。
- $W_{p,i}^$是由第p个场景的独有结构的第i层权重$W_{p,i}^$与共享结构的第i层权重$W_i$,按位向乘得到。
4、动态权重
动态权重的原理可以分为以下三步:
- 把场景指示特征,喂入权重生成器,生成动态权重向量$DW=WG(z)$。
- 将DW reshape成一个合适形状的DNN,记为$F_{DW}$。例如,DW的长度是640 = 32 * 16 + 16 * 18,可以将DW变形成一个三层MLP,每层的神经元个数分别为[32, 16, 8]。
- 将这个根据场景指示特征动态生成的网络$F_{DW}$,应用于推荐模型的关键位置。
- 不同MLP层之间可以加入非线性的激活函数。
动态权重模式,突出了场景指示特征的作用,让它们像滤波器一样,控制其它信息向上传递的通道。其它信息向上传递过程中,都要经过场景指示特征的调制,根据不同场景,对前一层发现的模式局部增强或者衰减。
LHUC是动态权重的一种简单实现。它让场景指示特征当裁判,生成每个field的特征权重,增强对当前场景重要的特征,削弱对当前场景不重要的特征。
其原理如下:
\[\begin{aligned} C &= LHUC(X_{scene}) \\ FE_i^{rw} &= C[i] \times FE_i \\ y &= DNN(concat[FE_i^{rw}, ..., FE_K^{rw}]) \end{aligned}\]- LHUC的最后一层采用$A(x)=2 * sigmoid(x)$作为激活函数。输出向量有K个元素,K是输入特征field的个数。每个元素表示对应field的权重。元素取值在[0,2]之间,>1表示增强第i个field特征,<1表示削弱第i个field。
- FEi表示第i个field的原始embedding。
- $FE_i^{rw}$表示第i个field加权后的embedding。
- 加权后的embedding拼接后经过上层DNN。
快手提出的PPNet与LHUC类似。
阿里于2022年提出了M2M(multi-scenario multi-task)模型,解决多场景+多目标建模问题。
它在整体上遵循了MMOE结构。只不过在两个关键位置使用了动态权重。
- 场景指示特征生成DW。
- DW reshape后得到每个场景的gate网络的参数,以及每个任务塔的参数。
本文总访问量次