推荐算法丨向量召回
矩阵补充
模型训练
矩阵补充模型首先通过两个Embedding矩阵
训练的目标函数为:
线上服务
训练得到用户和物品的embedding,将embedding的结果存储到key-value表,用户的key-value表中key为用户id,value为embedding后的向量。
线上服务过程如下:
- 把用户id作为key查询用户的向量,记作a。
- 最邻近查找:查找用户最有可能感兴趣的k个物品,作为召回结果。
- 第i号物品的embedding向量记作
。 - 内积
是用户对第i号物品兴趣的预估。 - 返回内积最大的k个物品。
- 第i号物品的embedding向量记作
但是矩阵补充实际效果并不好,原因如下:
- 为利用物品、用户属性信息。
- 负样本选取方式不对。
- 内积不如余弦相似度,平方损失函数不如交叉熵损失。
双塔模型
双塔模型(two-tower)也叫 DSSM,是推荐系统中最重要的召回通道。
双塔模型有两个塔:用户塔、物品塔。两个塔各输出一个向量,作为用户、物品的表征。两个向量的余弦相似度作为对兴趣的预估。
模型训练
将物品样本分为正样本(用户感兴趣的物品)和负样本(用户不感兴趣的物品)。
Pointwise: 独立看待每个正样本、负样本,做简单的二元分类
Pairwise: 每次取一个正样本、一个负样本
Listwise: 每次取一个正样本、多个负样本
Pointwise训练
工业界一般使用这种方法。
把召回看作二分类任务:
- 对于正样本,鼓励cos(a,b)接近+1。
- 对于负样本,鼓励cos(a,b)接近-1。
其中a为用户的表征,b为物品的表征。正负样本数量通常控制在1:2或1:3。
Pairwise训练
Pairwise每次取一个正样本、一个负样本。基本想法是要鼓励cos(a,b+)大于cos(a,b-),b+是正样本的表征,b-是负样本的表征。
损失函数:
Triplet hinge loss
如果cos(a,b+)大于cos(a,b-)+m,则没有损失
否则,损失等于cos(a,b-)+m-cos(a,b+)
Triplet logistic loss
σ大于0的超参数。
Listwise训练
Listwise每次取一个正样本、多个负样本。这些物品样本与用户表征的余弦相似度经过softmax后,要使正样本尽可能大(接近1),使负样本尽可能小(接近0)。损失函数使用交叉熵损失。
正负样本
模型应用
双塔模型训练完成后,通过两个步骤投入实际应用:
离线存储:用物品塔计算每个物品的特征向量b,把<特征向量b,物品ID>保存到向量数据库用作最近邻查找。
线上召回:需要推荐时,调用用户塔线上计算用户向量a,并用a作为query查询向量数据库,查找和a余弦相似度最高的k个物品向量,返回这k个物品ID。
之所以存储物品向量而线上计算用户向量,是因为:
- 每次召回只用到一个用户向量,而用到大量物品向量,线上计算物品向量代价过大。
- 用户特征变化较快,而物品特征相对稳定,离线存储用户向量不利于推荐效果。
模型需要定期做更新,分为全量更新(天级别)和增量更新(实时):
- 全量更新:每天做一次全量更新,训练整个模型,包括embedding和全连接层。
- 将昨天的数据random shuffle。
- 在昨天模型参数的基础上(不受增量更新影响),用昨天的数据训练1epoch。
- 训练完成后发布新的用户塔和物品向量。
- 增量更新:做online learning更新模型参数,只更新ID
Embedding。
- 用户兴趣会随时发生变化,因此需要及时更新模型。
- 实时收集线上数据,做流式处理,生成TFRecord文件。
- 对模型做online learning,增量更新ID Embedding参数。
- 发布用户ID Embedding(推荐时使用用户ID查询用户ID Embedding),供用户塔在线上计算用户向量。
全量更新不受一天中不同时段用户使用习惯差异的影响,随机打乱数据训练效果更好。而增量更新可以动态捕捉用户的兴趣变化。因此二者需要结合使用。
双塔模型+自监督学习
双塔模型学不好低曝光物品的向量表征:
- 推荐系统的头部效应严重
- 少部分物品占据大部分点击
- 大部分物品点击次数不高
- 高点击物品的表征学得好,长尾物品的表征学得不好。
通过自监督学习做data augmentation可以更好地学习长尾物品的向量表征:
- 对每个物品做特征两类特征变换,并通过物品塔得到两个特征向量b'和b''。
- 对于同一个物品的两个特征向量
应使其相似度高。 - 对于不同物品的特征向量
应使其相似度低。
特征变换
对物品做特征变换时主要有几种方式:
Random Mask:随机选取一些离散特征(比如类目),把它们遮住。例如:
- 某物品的类目特征是u={数码,摄影}。
- mask后的类目特征变成u'={default}。
Dropout:随机丢弃某个多值离散特征50%的值。
- 多值离散特征:可以有多个取值的特征,例如类目。
- 例如某个物品的类目特征u={数码,摄影} dropout后变成了u'={美妆}。
互补特征(complementary):
- 假设物品一个有4种特征:{ID,类目,关键词,城市}。
- 随机分成两组:{ID,关键词}和{类目,城市}。
- 由{ID,default,关键词,default}计算得到物品表征1。
- 由{default,类目,default,城市}计算得到物品表征2。
- 应使物品表征1和物品表征2尽可能相似。
Mask一组关联的特征
离线计算特征两两之间的关联,用互信息(mutual information)衡量:
其中p(u)表示某特征取值为u的概率,p(u,v)表示某两个特征分别取值u、v的概率。 设一共有k种特征,则两两之间的MI构成k×k矩阵。
随机选一个特征作为种子,mask种子及其相关的k/2种特征。
效果好但成本高。
训练模型
首先对点击做随机抽样,得到n对用户-物品二元组,作为一个batch训练双塔。这种方式下热门物品抽到的概率更高。
接着从全体物品中均匀抽样,得到m个物品,作为一个batch,用来训练物品塔。这种方式下所有物品被抽到概率相同。对这些物品做两类特征变换,物品塔输出两组向量:
如图,取第一组中的向量
如此得到了第i个物品的损失函数: