搜广推论文阅读:冷启动POSO
今天来分享一篇快手的关于冷启动的论文笔记:[2108.04690] POSO: Personalized Cold Start Modules for Large-scale Recommender Systems。作者水哥也在知乎上发表过非常详实的细节推荐系统难题挑战(7):POSO,从模型角度解决用户冷启动问题 - 知乎,观看后收获很多。
背景与出发点
冷启动一直是推荐系统中的难点,一方面,新用户刚刚进入推荐系统,行为稀少,数据积累很少;同时,新用户的行为模式和老用户的行为模式有比较大的差距,比如在快手场景,作者分析发现新用户的观看时间小于老用户,但是点喜欢的概率却高于老用户。
除上述两点外,本文还提出了冷启动困难的另一重原因,即新用户和老用户数据量的不平衡性,新用户稀少的数据量导致了模型很难有动力去拟合新用户的分布。
作者对此做了实验,发现使用is-new-user训练模型时,模型屏蔽该特征后对输出影响很小,而去屏蔽其它在新老用户上分布均匀的特征则恰恰相反。通俗点讲,因为新用户量太少了,模型懒得去focus这部分数据。
实现方法
理论形式
理想情况下,我们可以针对每个用户都学习一个模型,这样对于冷启动的新用户,其个人化的模型也可以很好学习其行为规律,但是由于推荐系统庞大的用户数量,这一设想是不现实的。
沿着这一思路,可以对用户进行分组,学习不同用户群体的特点。单个用户可以视作不同用户分组结果的加权叠加。而具体叠加的权重可以交给模型学习,这一形式可以表示为:
其中
x
x
x 是某层特征输入,而
x
^
\hat{x}
x^是该层特征输出,
x
p
c
x^{pc}
xpc代表用于分化网络的个性化特征,例如如果是针对新老用户的话,该特征就是衡量是否新老用户的。
假设网络有3个模块,对新用户输出的权重是2、1、0,老用户输出权重是0、1、2。我们就可以说第一个模型预测新用户、第三个模块预测老用户,而第二个模块一半一半。
注意,这里实际上还是一个理想下的概念,在具体精排过程中,我们哪怕构建两个一样模块对原有模型也是存在压力的,因此还要进一步简化。
POSO简化
由于原有模型结构的不同,POSO在不同的深度网络中会演变成不同的简化形式。原文中给出了三种最常见网络的POSO形式,分别是MLP、MHA和MMoe。
具体推导过程参考论文以及链接https://zhuanlan.zhihu.com/p/472726462,这里给出3种POSO的形式。
MLP
一个有趣的点是,这里推导出来,MLP的POSO形式实际上和PPNet是相同的,但是后者的出发点完全不同,是从特征重要性和加权角度来考虑的。
如何看待这一点,可以从以下3个方面来考虑:
- POSO并不等同于PPNet,因为指导思想不同,同时POSO也存在不局限于MLP的其它形式。
- 虽然实现雷同,但是Motivation决定了具体使用的方式。例如POSO由于出发点是对用户分别建模,主导思想是利用特征分化网络,因此在 x p c x^{pc} xpc的选择上和PPNet是不同的。这一点在细节部分会继续展开。
- 不同思想导向相似的解决路径是正常的,核心还是是否有用,是否可以解决Motivation提出的问题。
MHA
这里作者根据是否已经高度个性化来让特征进行不同程度的分化:
- query:非序列,用户标签id等,已经高度概括和个性化,不再施加变化
- key:只是用于和query生成attention,轻量级个性化
- value:决定最终输出很重要,完全个性化
MMoe
相关细节
分化网络特征的选择
- 新老用户定义:需要注意的是,新老用户或者新老物料是如何定义的问题。例如,我可以定义一个月内没有任何行为的为新用户,但是这回导致一个问题——当行为数从0到1时发生了突变,用户突然从新变成老,但实际上,这应该是一个渐变的过程。因此作者更主张用平滑的特征来处理该问题,例如用户历史曝光数,这是一个稠密变量而不是一个稀疏变量,由于量级问题需要进行高斯化。
- 特征的处理方法:为什么要选择一个稠密变量来生成gate,而不是用稀疏变量进行hash?一个重要原因是,神经网络的输出不是突变的。当新老用户变量 x p c x^{pc} xpc从小变大的时候,不可能所有网络输出都变大或者变小(否则就是训练失败),而是一部分变大、一部分变小,这样必然会产生符合 x p c x^{pc} xpc特征变化的分化方向
- 用多少特征做gate输入:用稀疏变量还有一个问题,例如很多实现会用uid做分化,但是用uid分化方向是不确定的,可能是用户的某些属性之类的。另外,作者认为POSO中分化特征选择必须要一致,不能第一层网络用是否新用户、第二层网络用是否新物料,这会引起网络的混乱。也不适合用多个特征做分化变量,比如用是否新用户+是否新物料做 x p c x^{pc} xpc,这会使得分化方向不确定,特别是引入一些分布均衡的特征,会严重削弱POSO对于不均衡的数据建模的效果。当然,这仅局限于原文场景,也有实践指出用uid分化效果很好的,具体还是要多尝试。
分化网络特征的使用
- 激活函数:gate层最好选择sigmoid激活函数。很多gate会使用softmax,但是对于特征维度多的情况,softmax容易导致权重集中到某些维度,而其它维度权重过小。
- 量纲变化:经过sigmoid激活函数后,最好乘以2。原因是分化特征经过高斯后大部分情况下是0,这就导致其输出经过sigmoid是0.5,乘以2=1,可以保证整体embedding不变。
- gate网络的实现:原文中gate使用的是线性网络,例如MHA中假设需要生成4个权重,网络就是1个从1->4的FC层。但是这个过程是线性化的,部分经验指出,将该过程非线性化可以显著提升模型线上效果。
- field-wise or bit-wise:POSO可以应用在各个层,因此会诞生一个问题,从embedding到dense是用field-wise还是bit-wise(第二层dense往后没有field概念了,只有第一层有这个问题),实验后发现是field-wise效果好一些。
- POSO加在哪儿效果好:POSO主要针对的是原始特征提取,因此适合用在浅层。如何是用在深层网络,比如分化不同task的部分,效果就会一般。
- 是否需要stop梯度:一般情况,不stop梯度学习难度更大,部分情况可能会导致结果劣化,具体还是要实验尝试。
参考链接
-
阅读与实践