跳到主要内容

推荐系统学习笔记

b 站课程

王树森老师的资料合集

一. 概要​

推荐系统基本概念​

可以将一个 推荐系统 简单地理解为 给用户推荐实体或非实体物品的系统。其任务是根据用户和物品的特征,使用某种或某些推荐算法预测任意用户对任意物品的兴趣得分,并按照预测的得分顺序,将排在前列的物品展示给用户。

Tip:以小红书为例,物品为小红书笔记,后续统一使用物品进行描述。

转化流程

根据不同公司的不同产品,一般有不同的转化流程。流程中的动作意味着 用户对物品感兴趣,这些动作意味着 用户和物品产生了交互,可以作为 推荐系统使用的推荐依据。 转化流程一般分为三步,下图以小红书为例:

Tip:抖音没有点击流程。

常见的推荐系统评测指标

消费指标(短期消费指标)北极星指标(长期消费指标)
基于点击的指标:点击率基于用户规模:日活用户数、月活用户数
基于反馈的指标:点赞率、收藏率、转发率基于消费用户:人均使用推荐时长、人均阅读笔记数量
基于特定产品的指标:阅读完成率(文章)基于发布用户:发布渗透率、人均发布量

消费指标并不是推荐系统追求的根本目标,考察的关键应该放在北极星指标上。只关注追求极致的消费指标提升,最直接的影响就是导致推荐给用户的物品都是相似或相同的,显著减少了推荐的多样性,用户很难接触到感兴趣但新鲜的物品,长久以往用户活性降低,用户不断流失。在实践中,消费指标降低但是北极星指标提升也被认为是一种正向的趋势。

Tip:发布是小红书的核心竞争力。

推荐系统的实验流程

实验流程:离线实验 → 小流量 A/B 测试 → 全流量上线

离线实验:收集历史数据在其上做模型训练和测试,算法没有部署到产品中,没有跟用户交互。

小流量 A/B 测试:把算法部署到产品中,设置实验组与对照组使用新旧策略,算法与部分用户做交互。

全流量上线:A/B 测试的新策略优于旧策略,就加大交互的用户流量,最后推全。

推荐系统的链路​

推荐系统目标:从几亿物品中选取几十个物品推荐给用户。

推荐系统的链路:

召回:用多条召回通道(协同过滤、双塔模型、关注的作者等),先快速取回几千物品。
粗排:用小规模神经网络,给几千篇物品打分,选出分数 Top 几百的物品。
精排:用大规模神经网络,给粗排选出的几百篇物品重新打分排序。
重排:多样性抽样从几百篇物品中挑选几十篇,依规则打散,并插入广告和运营物品,根据生态再调整排序。

Tip:召回通道实际上就是实现召回的模型方法,第二章节会详细介绍协同过滤、双塔模型和其他召回通道。

推荐系统的 A/B 测试​

召回团队实现了一种新的召回通道,离线实验结果是正向的,下一步就需要做线上的小流量 A/B 测试。A/B 测试启到如下作用:

  1. 考察新的召回通道对线上指标的影响;
  2. 测试选择模型的最优参数。

随机分桶

A/B 测试需要设置对照组和实验组,对照组和实验组的实验通过随机分桶来实现。不妨设有全部 位用户,分成 个桶,每个桶有 位用户。随机分桶实现原理如下:

  1. 首先使用哈希函数将用户 ID 映射成某个区间内的整数,然后把这些整数均匀随机分成 个桶;
  2. 可以取其中若干个桶作为多个实验组采用不同的召回通道,再另取一个新桶为对照组使用原策略;
  3. 计算每个桶的业务指标;
  4. 如果某个实验组显著优于对照组,则说明对应的策略有效,值得推全。

Tip:从统计学角度出发,如果样本足够大,可以认为各个桶的特征相同。

分层实验

互联网大厂这种信息流公司有很多的团队和部门,需要同时负责推荐系统(召回、粗排、精排、重排)、用户界面、广告等业务的 A/B 测试。此时会遇到用户流量不够用的情况,分层实验是一项很好的举措:

分层:分成召回、粗排、精排、重排、用户界面、广告等等多个层。

同层互斥:某召回实验占用了召回层的 个桶,其他召回实验只能使用剩余的 个桶。

不同层正交:每一层独立随机对用户做分桶。每一层都可以独立使用全部桶的用户做实验。

基于以上原理,不妨以召回和召回的下一层(粗排层)为例说明。假设该系统有 个用户,召回层将用户分成了 个桶:,均匀打散后,粗排层可以也将用户分为 个桶: ,符合不同层正交的原理。那么有:

  1. 任意的召回桶 和粗排桶 满足 ;
  2. 同层互斥,不同的召回桶 和 的交集为 ;
  3. 不同层正交,不同的召回桶 和粗排桶 的交集大小为 。

Tip:这里的集合是桶的用户集合,取模就是计算桶中用户数量,2 中互斥的两个集合交集自然为空集,显然成立。对于 3 中等式左边的目标是求上下不同层的任意两个桶中的相同用户数量,如下分析:上一层每个桶中的用户被均匀分到下一层 个桶中,相当于上下任意两桶中只有 比例的用户是相同的,再考虑到任意桶中只有 个用户,所以上下两层任意桶中只有 个相同用户。

既然分层实验可以有效处理流量不足问题,那么是否存在所有实验都正交,则可以同时做无数组实验的情况呢?答案是否定的,原因如下:

  1. 同类的策略(比如召回层的不同通道)天然互斥,对于同一用户只能使用其中一种;
  2. 同类的策略可能相互抵消或相互增强,互斥可以避免同类策略相互干扰;
  3. 不同类的策略(比如添加召回通道和优化粗排模型)会通常不会相互干扰,才可以做正交的两层。

Holdout 机制

公司需要考察部门(如推荐系统)在一段时间内对业务指标的总体提升,需要每个实验(召回、粗排、精排、重排)独立汇报对业务指标的提升贡献,因此设置了 Holdout 机制,基本思想为:

  1. 取 10%的用户作为 Holdout 桶,推荐系统使用剩余 90%的用户做实验,两者互斥;
  2. 考察 10%Holdout 桶与 90%实验桶的差异(需归一化)作为整个部门的业务指标收益;
  3. 每个考核周期结束之后,清除 Holdout 桶,让推全实验从 90%用户扩大到 100%用户;
  4. 重新随机划分用户,得到 Holdout 桶和实验桶,开始下一轮考核周期;
  5. 初始的新 Holdout 桶与实验桶的各种业务指标的差异接近 0,随着召回、粗排、精排、重排实验上线和推全,差异会逐渐扩大。

实验推全和反转实验

实验推全: 在 Holdou 机制基础上,观测到某个策略对某个桶有明显提升,关闭 A/B 测试,将策略推全到整个 90%用户上。需要在召回层之前新建一个推全层,该层与其他层正交。

反转实验: 为了尽快推全新策略和长期观测实验指标,需要设立反转实验。故需要在实验推全的新层中设立一个旧策略的桶,长期观测实验指标。

  1. 譬如点击、交互这些指标会立刻受到新策略的影响,而譬如留存这类指标具有滞后性,需要长期观测。
  2. 同时,实验观测到显著收益后需要尽快推全全新策略,腾出桶给其他实验使用或基于新策尽快进行开发。

Tip:如下图所示,推全层中推全新策略的桶和使用旧策略的反转桶是互斥的。新推全层是与 Holdout 桶无关的,考核周期结束后清除 Holdout 桶不会影响反转桶。反转实验结束后关闭反转桶,真正做到推全到 100% 用户上。

本章小结​

推荐系统是给用户推荐实体或非实体物品的系统。

基于此,本章首先依次介绍了 推荐系统的基本概念、推荐依据、评价指标、链路、实验流程。

然后针对实验流程中的 A/B 测试 进行了知识扩充,详解了 随机分桶、分层实验、Holdout 机制、实验推全 和 反转实验 的概念与思想,这些基础知识将贯穿后续所有章节内容。

二. 召回​

召回是推荐系统链路中的第一个流程,目的是从几亿的 item 中选出几千 item。进行召回的模型方法是多种多样,包括但不仅限于基于统计学的、基于规则的和基于神经网络的。本章先从最基础的协同过滤开始介绍。

基于物品的协同过滤-ItemCF​

ItemCF 原理与实现

ItemCF 的基本思想在于:如果用户喜欢物品 ,而物品 与物品 相似,那么用户很可能喜欢物品 。根据该思想,ItemCF 的实现需要基于以下步骤:

  1. 基于转化流程中的动作得到某用户对物品的兴趣分数 ;
  2. 离线计算得到的物品之间的相似度 ;
  3. 如下图所示,线上预估用户对候选物品的兴趣 。

用户对候选物品的兴趣:2×0.1+1×0.4+4×0.2+3×0.6=3.2

物品相似度

一般来说,ItemCF 的思想认为两个物品的受众重合度越高,两个物品越相似。所以计算物品相似度是基于与两个物品交互的用户群体重合度的:

  1. 设喜欢物品 的用户群体为集合 ,喜欢物品 的用户群体为集合 ;
  2. 定义这两个集合的交集 ,那么简单计算两个物品的相似度为 。
  3. 考虑到用户对于不同物品的喜欢程度 对相似度的影响:
    ,实际上这就是常用的 余弦相似度 的表达形式。

ItemCF 召回的完整流程

在线上进行 ItemCF 召回之前,需要 事先做离线计算,存储计算结果并建立索引:

  1. 建立”用户 → 物品“的索引:用户物品,兴趣分数
    (1)记录每个用户最近点击、交互过的物品 ID;
    (2)给定任意用户 ID,可以利用索引找到该用户近期感兴趣的物品列表。
  2. 建立”物品 → 物品“的索引:物品最相似的个物品相似度
    (1)计算物品之间的两两相似度;
    (2)对于每个物品,索引该物品最相似的 个物品;
    (3)给定任意物品 ID,可以利用索引快速找到该物品最相似的 个物品。

基于事先建立的索引,实现 线上召回:

  1. 给定用户 ID,通过”用户 → 物品“索引,找到用户近期感兴趣的物品列表 ;
  2. 对于 列表中的每个物品,通过”物品 → 物品“的索引,找到 相似的物品;
  3. 对于所有取回的相似物品(最多有 个),用公式预估用户对物品的兴趣分数;
  4. 返回分数最高的若干个物品作为召回结果。

Tip:线上召回时索引可以避免暴力枚举所有物品。虽然离线计算量大,但是有效减少了线上计算量。

Swing 召回通道

前面说明过,ItemCF 计算物品相似度是基于与两个物品交互的用户群体重合度的,如果重合的用户是一个小圈子(比如微信群),受众完全不同的两个物品也容易被误判为相似度较高,实际落地应用效果较差。因此需要考虑用户之间的物品重合度大小,降低小圈子的权重。故此在 ItemCF 的基础上提出了 Swing 模型:

  1. 设用户 喜欢的物品集合为 ,用户 喜欢的物品集合为 ,喜欢物品 的用户群体为集合 ,喜欢物品 的用户群体为集合 ;
  2. 定义两个 用户的重合度 为: ,如果用户 和 的重合度高,则他们可能来自一个小圈子,计算物品相似度时需要降低他们的权重;
  3. 定义交集 ,则两个物品的相似度计算为
    ,其中 为超参数。这一公式体现了用户群体的重合度越大时,小圈子对物品相似度的贡献越小。

基于用户的协同过滤-UserCF​

UserCF 原理与实现

UserCF 的基本思想在于:如果用户 与用户 相似,而且 喜欢某物品 ,那么 很可能也喜欢该物品。根据该思想,UserCF 的实现需要基于以下步骤:

  1. 基于转化流程中的动作得到用户对某物品的兴趣分数 ;
  2. 离线计算得到的用户之间的相似度 ;
  3. 如下图所示,线上预估用户对候选物品的兴趣 。

用户对物品的兴趣:0.9×0+0.7×1+0.7×3+0.4×0=2.8 。

用户相似度

类似于 ItemCF 和物品相似度,UserCF 认为两个用户喜欢的物品重合度越高,两个用户越相似。所以计算物品相似度的计算方式如下:

  1. 设用户 喜欢的物品集合为 ,用户 喜欢的物品集合为 。
  2. 定义这两个集合的交集 ,那么简单计算两个用户的相似度为 。
  3. 上述公式等价于: ,该公式表示该用户的相似度计算时并没有区别对待冷门和热门物品,给予了它们同样的权重来影响相似度。由于热门物品只占所有物品的很小部分,而且很容易出现不同用户有相同的热门物品重合度,故越热门的物品越无法反映用户的独特的兴趣。
  4. 所以,为了 降低热门物品的权重,用户的相似度 计算公式更新为: ,其中 是喜欢物品 的用户数量,能够反映物品的热门程度。(对数中+1 的作用是为了避免负数的出现,相似度的值域 。)

UserCF 召回的完整流程

同样的,在线上进行 UserCF 召回之前,需要 事先做离线计算,存储计算结果并建立索引:

  1. 建立”用户 → 物品“的索引:用户物品,兴趣分数
    (1)记录每个用户最近点击、交互过的物品 ID;
    (2)给定任意用户 ID,可以利用索引找到该用户近期感兴趣的物品列表。
  2. 建立”用户 → 用户“的索引:用户最相似的个用户相似度
    (1)计算用户之间的两两相似度;
    (2)对于每个用户,索引该用户最相似的 个用户 ;
    (3)给定任意用户 ID,可以利用索引快速找到该用户最相似的 个用户。

基于事先建立的索引,实现 线上召回:

  1. 给定用户 ID,通过”用户 → 用户“索引,找到 相似的用户;
  2. 对于每个 相似用户,通过”用户 → 物品“的索引,找到用户近期感兴趣的物品列表 ;
  3. 对于所有取回的相似物品(最多有 个),用公式预估用户对每个物品的兴趣分数;
  4. 返回分数最高的若干个物品作为召回结果。

Tip:进行线上召回时,ItemCF 先通过用户 ID 索引该用户的感兴趣物品,再利用物品 ID 索引所有相似物品;UserCF 则先通过用户 ID 所有相似用户,再利用用户 ID 索引用户感兴趣的物品。两者的召回索引使用顺序有所区别,最后都是利用公式计算兴趣分数排序得到召回结果。

矩阵补全与最近邻查找​

离散特征处理

在介绍矩阵补全模型之前,先说明在推荐系统中做离散特征处理的常见方法:

  1. 建立字典:把离散特征的所有类别映射成序号。
  2. 向量化:把序号映射成向量,包括:
    (1)one-hot 编码:把序号映射成高维稀疏向量;
    (2)embedding(嵌入):把序号映射成低维稠密向量。

在前面通过 ItemCF 和 UserCF 进行召回时,在计算相似度时就是将用户和物品表示成了稀疏向量。但是在实际应用中,用户和物品的数量是极其巨大的,过于稀疏的向量计算复杂、计算量过大、存储困难,所以 embedding 是业界常用的一种方式。TensorFlow、PyTorch 等提供 embedding 层,这里不再介绍。

矩阵补全

矩阵补全, 顾名思义就是将一个含有缺失值的矩阵通过一定的方法将其补全为一个完全的矩阵。那么在推荐系统里,要用什么方式补全何种矩阵? 如下所示是基于 embedding 做推荐的模型:

模型训练所用数据集为(用户 ID,物品 ID,兴趣分数)的集合,记作 ,模型基本思想和训练流程为:

  1. 用户 embedding 参数矩阵记为 ,第 号用户对应矩阵第 列,用户 ID 通过 embedding 层映射为向量 ;物品 embedding 参数矩阵记为 ,第 号物品对应矩阵第 列,物品 ID 通过 embedding 层映射为向量 ;
  2. 计算内积 ; 即是第 号用户对第 号物品兴趣的预估值;
  3. 训练模型的目的是学习矩阵 和 ,使得预估值 拟合 真实观测的兴趣分数,所以需要求解如下最优化问题,得到 和 的参数: 。

由此,可分析何为矩阵补全模型:

如图所示,该矩阵即是通过求内积得到的用户对物品的兴趣分数矩阵。因为系统曝光给用户的物品只有很小部分,所以这个矩阵中只有绿色位置有用户对物品的兴趣分数;而因为系统没有曝光给用户某些物品,对应灰色位置没有分数。矩阵补全 就是利用绿色位置的数据集来训练模型,利用训练好的模型再来预估灰色位置的兴趣分数,以实现补全用户对物品的兴趣分数矩阵。换言之,系统想要预估用户对未曝光物品的兴趣分数,可以通过已有用户对曝光物品的兴趣分数数据集训练模型,利用这个模型实现预估。

但是,矩阵补全模型在实际落地效果并不理想,所以才有后续譬如双塔模型的提出。其主要问题在于:

  1. 仅仅使用 ID 做 embedding,没有考虑物品和用户的属性(多维特征)
  2. 负样本的选取方式不对。将曝光之后没有点击交互的物品当作负样本是错误的。在双塔模型里会详细讲解常用的正负样本选取方式。
  3. 做训练的方法不对。使用内积不如计算余弦相似度;损失函数用平方损失(预估值拟合真实观测分数,回归问题)不如使用交叉熵损失(分类问题)。

最近邻查找

在矩阵补充模型做完模型训练后,需要保存训练得到的矩阵 和 ,一般用 key-value 表(字典)存储矩阵 的列为 用户: ,而矩阵 的存储和索引比较复杂。存储好模型后就需要展开线上服务,在线进行召回,主要流程为:

  1. 根据用户 ID 作为 key 查询 key-value 表,得到该用户的向量 ;
  2. 最近邻查找:查找用户最有可能感兴趣的 个物品,作为召回结果。
    (1)第 号物品的 embedding 向量为 ;
    (2)内积 是用户对第 号物品兴趣的预估;
    (3)返回内积最大的 个物品。

Milvus、Faiss、HnswLib 等系统是支持最近邻查找的,衡量最近邻查找的标准也不仅仅限于欧式距离最小、向量内积最小、向量夹角余弦最大。

但最近邻查找存在显著的问题,它暴力枚举的所有方法,时间复杂度正比于物品数量,在实际落地很难应用(小红书的笔记数量以亿为单位)。所以,前人提出了诸多加速最近邻查找的算法。王老师在课程中以余弦相似度为例,说明了一种加速算法的思路:

近似最近邻查找的例子

  1. 有 个物品通过 embedding 得到物品向量,如下图所示,将其向量分布区域划分为 个小区域(余弦划分为扇形区域), 每个区域使用一个单位向量表示;
  2. 以该区域的表示向量作为 key,区域中所有物品(数量为 )的列表为 value, 个区域就有 个索引;
  3. 在线上快速做推荐,分别计算用户向量 与所有索引向量的相似度(时间复杂度为 );
  4. 找到相似度最高的索引,再分别计算用户向量 与该索引区域包含的所有 个物品向量的相似度(时间复杂度为 );
  5. 选取最相似的 个点,作为召回结果。
    显然在计算过程中,使用暴力枚举的时间复杂度为 ;加速算法将 (几亿)个物品分别划分到 个(几万)区域,每个区域只有 个(几万)物品,时间复杂度为 ,计算量远远小于暴力枚举。

双塔模型​

模型介绍

上一小节介绍了矩阵补全模型,但是它存在诸多问题。因此业界提出了落地有效的双塔模型:

双塔模型左右分别是 用户塔 和 物品塔,分别用于生成表示用户和物品的特征向量;充分使用了 用户和物品的多维特征属性;使用 余弦相似度 替代内积计算预估用户对物品的兴趣分数。如下图所示(以用户塔为例),这两个塔的结构一致,仅是特征变换的方法和神经网络的参数存在差异。

值得注意的是,通过大量实践证明,适用于 召回 的双塔模型是先分别通过神经网络生成表征,再计算两个表征之间的相似度(兴趣分数),称之为 后期融合,;而在 精排和粗排 中,则需要使用 前期融合,也就是先融合物品和用户的特征向量,再通过神经网络输出兴趣分数。

模型训练

小红书推荐系统的模型训练方法主要包括如下表所示三种:

训练方法选取样本基本思想(训练目标)损失函数
Pointwise独立看待每个正负样本1. 把召回看作二元分类任务
2. 鼓励用户与正样本的余弦相似度接近+1;
3. 鼓励用户与负样本的余弦相似度接近-1。
交叉熵损失
Pairwise每次取一个正样本、一个负样本鼓励用户与正样本的余弦相似度大于鼓励用户与负样本的余弦相似度。合页损失
Listwise每次取一个正样本、多个负样本1. 鼓励用户与正样本的余弦相似度尽量大;
2. 鼓励用户与每个负样本的余弦相似度都尽量小。
Sampled Softmax Loss

这里在解释其中 合页损失 和 Sampled Softmax Loss 的注释内容前,先做如下定义:

  1. 某个用户的特征向量,记作 ;
  2. 某个物品正样本的特征向量,记作 ;某个物品负样本的特征向量,记作 ;
  3. 个物品负样本的特征向量分别记作 ;
  4. 函数用于计算用户和物品余弦相似度。

现逐条分析注释内容:

合页损失:

  1. 根据 Pairwise 的思想 ,希望实现 。如果 时,没有损失;否则损失等于 。由此推理的合页损失为 Triplet Hinge Loss,公式表达为: ,其中 是用户和物品样本之间的差距(margin)。
  2. 另有一种被称为 Triplet Logistic Loss 的损失函数也可以实现 ,公式如下: 。
    Sampled Softmax Loss:如下图所示,实际上 Listwise 也是将召回看成二分类任务。 是模型输出的余弦相似度通过 Softmax 激活函数转化的结果; 是样本的真实标签,正样本标签为 1,负样本标签为 0。推理得到的损失函数为:

最后,使用梯度下降法,减少损失函数。

正负样本

在推荐系统中,一般将 曝光而且有点击的“用户-物品” 二元组作为训练的 正样本(用户对物品感兴趣)。但是存在一个实际问题,少部分物品受到了用户的大部分点击(热门物品),导致了正样本大多都是热门物品。所以,在选择正样本时,需要 过采样冷门物品,或者 降采样热门物品。

但是负样本的选取需要合理且正确,错误的负样本选取会影响模型召回效果。负样本 主要根据其分类难度,被分为 简单负样本 和 困难负样本,如下表所示:

负样本类型负样本来源选取思想
简单负样本全体物品1. 未被召回的物品,大概率是用户不感兴趣的,分类准确较高(简单)。因为被召回的物品只是很小一部分,所以未被召回的物品近似等于全体物品。
2. 非均匀抽样,打压热门物品。抽样概率正比为为点击次数的 0.75 次方。
简单负样本Batch 内负样本1. 一个 Batch 内有 n 个正样本(用户-物品对)。任意选取一个用户和 n-1 个物品组成负样本,则该 Batch 内有 n(n-1)个负样本。
2. 一个物品出现在 Batch 内的概率正比于点击次数,增大了热门物品成为负样本的概率,必须进行纠偏*。
困难负样本被排序淘汰的物品用户感兴趣但是兴趣不强的物品,分类比较困难。
困难负样本精排分数靠后的物品用户非常感兴趣但是排名靠后的物品,分类非常困难。
无用负样本(排序可用)曝光但没有点击的物品该物品作为负样本训练召回是错误的,但是可以作为排序的负样本。

纠偏*:因为在 Batch 内物品 被抽样的概率 正比于点击次数,需要通过纠偏来降低热门物品成为负样本的概率。设预估用户对物品 的兴趣分数为 ,则仅在训练时,将其调整为 。

在进行训练时,常见的作法是 混合 以上几种简单和困难的负样本,比如:

  1. 50%的负样本是全体物品(简单负样本);
  2. 50%的负样本是就没有通过排序的物品(困难负样本)。

线上召回和更新

与前面介绍的其他模型相同,在进行线上召回之前,双塔模型需要先事先进行计算、建立索引,通过数据库 离线存储物品向量:

  1. 完成训练后,用物品塔计算每个物品的特征向量 ;
  2. 把几亿个物品向量 存入向量数据库;
  3. 向量数据库建立索引,以便加速最近邻查找。

再进行 线上召回,查找用户最感兴趣的 个物品:

  1. 给定用户 ID 和画像(用户多维特征属性),线上用神经网络(用户塔)计算用户向量 ;
  2. 最近邻查找:
    (1)把向量 作为 query,调用向量数据库做最近邻查找;
    (2)返回余弦相似度最大的 个物品,作为召回结果。

这里需要提前计算存储物品向量 而只需线上计算用户向量 的原因在于:

  1. 每做一次召回所用到的用户向量数量为 1,而物品向量数量为几亿,线上计算物品向量的代价太大。
  2. 用户的兴趣是动态变化的,而物品特征相对稳定。虽然可以离线存储用户向量,但是不利于实时的推荐结果。

部署好模型后并非一劳永逸了,还需要根据前一段时间的数据结果做模型的更新,更新主要有 全量更新 和 增量更新 两种,如下表所示:

更新类型全量更新增量更新
基本思想今天凌晨,用昨天全体的数据,在昨天模型参数的基础上做模型训练。用户兴趣会随时变化,几十分钟就会更新用户兴趣。故做 online learing 更新模型参数。
基本流程1. 用昨天的数据训练 1 个 epoch,每天数据只用一遍;
2. 发布新的用户塔神经网络和物品向量,供线上使用;
1. 实时收集线上数据,做流式处理,生成 TFRecord 文件;
2. 对模型做 online learning,增量更新用户 ID embedding 参数;
3. 发布用户 ID embedding,供用户塔在线上计算用户向量。
注意事项1. 基于使用昨天的全体的数据以及昨天的全量模型,不是随机初始化模型,也不是昨天最后的增量模型。
2. 全量更新对数据量、系统的要求比较低。
增量更新只更新用户 ID embedding 层参数,不更新神经网络其他部分参数。

那么可以只做增量更新而不做全量更新吗?显然不能:

  1. 增量更新不同时间段的用户行为不一样,从统计学的角度出发,以天为总体,小时级的数据是有偏的,而分钟级别的数据偏差更大;
  2. 全量更新 random shuffle 了一天的数据,而增量更新按照数据从早到晚的顺序做训练。一般来说,训练时,随机打乱是优于按顺序排列的数据。故全量训练往往优于增量训练

自监督学习​

基于双塔模型的推荐系统存在严重的头部效应:因为少部分物品占据大部分点击次数,大部分物品点击次数不多,所以推荐系统对高点击物品的表征学的好,对长尾物品的表征学习困难。所以,引用自监督学习的思想,做 data argumentation,可以更好地学习长尾物品的表征。

基本思想与训练目标

这里的物品塔是同一个塔,共享参数。后面会补上一个高相似度的线路

召回中的 自监督学习,更像是设立一个辅助任务,帮助系统学到更多已有数据的监督信息(调整塔的参数),有效解决长尾问题;同时应用不同的特征变化能得到更多的向量表征,起到了数据增强或扩充数据集的作用。它的训练目标为:

  1. 希望物品 的两个向量表征 和 有较高的相似度,鼓励 尽量大;
  2. 希望物品 和物品 的任意向量表征(如 和 )都有较低的相似度,鼓励 尽量小。

特征变换

在召回中也常用到深度学习中的多种特征变换方法,如下表所示:

特征变换基本思想示例
Random Mask随机挑选一些离散特征,把它们遮住。处理前物品的特征集合 u ={ID、类目};处理后 u ={default}。
Dropout随机丢弃特征中 50%的值(仅对多值离散特征生效)。处理前某特征的向量 a = [1, 2];处理后 a = [1, 0] 。
互补特征将若干个特征随机分为两组,两组都是物品表征且特征互不重复。因为表示的都是同一物品,所以鼓励这两个特征向量相似。某物品具有 ID、类目、关键词、城市 4 个特征,随机分成 {ID,default,关键词,default} 和 {default,类目,default,城市} 这两种物品表征。
Mask 一组关联的特征1. 使用互信息(MI,mutual information)衡量关联度,离线计算特征两两之间的关联矩阵,根据关联矩阵进行特征的随机 Mask。
2. 它比以上三种方法效果都要好,但是比较复杂,实现难度大且不容易维护。
1. 设一共有 k 种特征,离线计算特征两两之间的 MI,得到 k×k 的矩阵;
2. 随机选一个特征作为 seed,找到该 seed 最相关的 k/2 种特征;
3. Mask 该 seed 及其最相关的 k/2 种特征,保留其余 k/2 种特征。

互信息:设特征 1 的类别集合为 ,特征 2 的类别集合为 , 为某特征取值为 的概率, 为某特征取值为 、另一个特征取值为 的概率。则互信息计算公式: 。

模型训练

结合前文描述,自监督学习的训练流程如下:

  1. 从全体物品中均匀抽样,得到 个物品,作为一个 batch;
  2. 做两类特征变换,物品塔输出两组向量 和 ;
  3. 第 个物品的损失函数为: ;
  4. 做梯度下降,减小自监督学习的损失: 。

为了解决长尾问题,现将自监督学习加入到双塔模型的训练之中:

  1. 对点击物品做随机采样,得到 对“用户-物品”二元组,作为一个 batch;
  2. 从全体物品中均匀抽样,得到 个物品,作为一个 batch;
  3. 做梯度下降,使得损失(双塔模型损失+自监督学习损失)减小: ,其中 是超参数,用于调整自监督学习的影响程度。

Deep Retrieval​

召回:用户 → 路径 → 物品

  1. 给定用户特征 ,用神经网络预估用户对路径 的兴趣,分数记作
  2. 用 beam search 寻找分数 最高的 s 条 path
  3. 利用索引 path->List<item> 召回每条路径上的 n 个物品
  4. 一共召回 个物品,对物品做初步排序,返回分数最高的 若干物品

与双塔模型的区别:

  • Deep Retrieval 是以路径作为用户和物品的中介
  • 双塔模型则是以向量表征作为用户和物品的中介

训练

同时学习 用户-路径 和 物品和路径

  • 一个物品被表征为 条路径:
  • 如果用户点击过物品,则更新神经网络参数,使分数增大:
  • 如果用户对路径的兴趣分数 较高,且用户点击过物品 item, 则 item 与 path 具有相关性高
  • 寻找与 item 最相关的 条 path,且避免一条路径上物品过多

其他召回通道​

在小红书的推荐系统中,还有如下表所示的几种简单召回通道:

召回通道原理索引召回流程
GeoHash 召回用户可能对附近发生的事感兴趣,根据用户定位的 GeoHash 取回该地点最新的若干篇笔记。GeoHash→ 优质笔记列表(按时间倒排)无个性化召回(所以选择推荐优质笔记)
同城召回用户可能对同城发生的事情感兴趣。城市 → 优质笔记列表(按时间倒排)无个性化召回
作者召回用户对关注的作者发布的笔记感兴趣。用户 → 关注的作者
作者 → 发布的笔记(按时间倒排)
用户 → 关注的作者 → 最新的笔记
有交互的作者召回如果用户对某笔记感兴趣(点赞、收藏、转发),那么用户可能对该作者的其他笔记也感兴趣。1. 用户 → 有交互的作者
2*. 作者 → 发布的笔记(按时间倒排)
用户 → 有交互的作者 → 最新的笔记
相似作者召回如果用户喜欢(关注、交互)某作者,那么用户喜欢相似的作者(类似 ItemCF)。1*. 用户 → 感兴趣的作者
2. 作者 → 相似作者
3*. 作者 → 发布的笔记(按时间倒排)
用户 → 感兴趣的作者 → 相似作者 → 最新的笔记

Tip: 在视频中,有交互和相似作者召回这两者召回通道的索引都只写了一条,个人根据召回理解进行了补充(带*号)。本人理解作者的意思在于,按照介绍顺序,先前的召回通道已经建立了这些索引,所以仅列举出新的召回通道需要添加的新索引。也可能在实际中,小红书的推荐系统无需这些这些索引,可以直接进行实时的线上计算。此处存在争议,请以视频为准。

除此之外,还有一种被称为缓存召回的召回方法。在精排到重排的过程中,从几百篇笔记中只筛选了几十篇作为推荐结果,大部分精排结果并没有被曝光。因此,缓存召回 希望复用前 次推荐精排但没有曝光的结果,将它们缓存起来,作为一条召回通道。但是缓存的大小固定,所以需要设置 退场机制,如下是几个简单的退场机制例子:

  1. 一旦笔记成功曝光,就从缓存退场;
  2. 如果超过缓存大小,就移除最先进入缓存的笔记;
  3. 笔记最多被召回若干次,达到这个次数就退场;
  4. 每篇笔记最多保存若干天,达到这个天数就退场;
  5. 想让低曝光笔记缓存更长时间,基于曝光次数设置退场规则。

曝光过滤 & Bloom Filter​

曝光过滤

在小红书和抖音的推荐系统中,为了避免重复推荐物品,如果用户看过某个物品,则系统不再把该物品曝光给该用户,这个思想称之为 曝光过滤。一般来说,曝光过滤是在召回层实现的,它的基本流程如下:

  1. 对于每个用户,记录已经曝光给他的物品。(小红书只召回 1 个月以内的笔记,因此只需要记录每个用户最近 1 个月的曝光历史)
  2. 对于每个召回的物品,判断它是否已经给该用户曝光过,排除掉曾经曝光过的物品。

Bloom Filter

如果一位用户看过 个物品,本次召回 个物品。如果暴力对比需要的时间复杂度为 ,计算过于巨大。所以在实践中使用 Bloom Filter 来判断一个物品 ID 是否在已经曝光的物品集合中:

  1. 如果判断为 no,那么该物品一定不在集合中;
  2. 如果判断为 yes,那么该物品很可能在集合中(可能误伤,错误判断未曝光物品为已曝光,将其过滤掉)。

如下所示是 Bloom Filter 的实现原理:

  1. Bloom Filter 把物品集合表征为一个 维的二进制向量;
  2. 每个用户有一个曝光物品的集合,表征为一个向量,需要 bit 的存储空间;
  3. Bloom filter 有 个哈希函数,每个哈希函数把物品 ID 映射成介于 和 之间的整数;
  4. 以下图( )为例,已曝光物品 ID 通过哈希函数映射进了二进制向量中对应的位置,如果该位置为 0 则调整为 1,若为 1 无需调整;
  5. 对于召回的物品 ID,通过哈希函数映射,若对应位置全为 1,则说明该物品已曝光,否则未曝光。

根据前面的描述,Bloom Filter 明显会产生误判。设曝光物品集合大小为 ,二进制向量维度为 ,使用 个哈希函数,则 Bloom Filter 的误伤概率 为 :

  1. 越大,向量中的 1 越多,误伤概率越大(未曝光物品的个位置恰好都是 1 的概率大);
  2. 越大, 向量越长,越不容易发生哈希碰撞;
  3. 太大、太小都不好, 有最优取值;
  4. 若人为设定可容忍的误伤概率为 ,那么最优参数为: , 。这里的推导可 参考一位大佬的文章。

除了会产生误判外,Bloom Filter 还有一个缺点。在每次往集合内添加一个物品,只需要把向量 个位置的元素置为 1。因此如果删除一个物品时,就无法直接将 个位置的元素置为 0,这会删掉向量中其他物品的信息。所以,Bloom Filter 只支持添加物品,不支持删除物品。如果从集合中移除物品,则无法消除它对向量已经发生过的影响。

本章小结​

召回的目的在于快速从几亿的物品中初步筛选出几千物品。无论是基于统计学、基于规则还是基于神经网络的召回方法都是行之有效的手段。协同过滤就是一种基础和经典的模型思想。

本章首先是对 ItemCF 和 UserCF 这两种协同过滤的介绍,它们使用物品和用户的 ID 计算相似度,结合用户对物品的交互信息,来计算 用户对物品的兴趣分数 进行排序作为召回结果。但在工业实践中初始物品数量都以亿为单位,协同过滤使用的稀疏向量过于庞大和稀疏,计算复杂度过高。

因此,引入了使用 embedding 处理离散特征(比如物品类别)的 矩阵补全 模型。但是矩阵补全模型仅使用 ID 做 embedding、负样本选取错误而且求内积做训练的方式(回归任务)不对,在实际应用中效果不佳。

针对这些问题,前人在矩阵补全的基础上改进得到了 双塔模型。双塔模型使用 用户和物品的多维特征 属性进行 embedding 后,通过特征变化再输入神经网络(后期融合)通过计算得到 余弦相似度;在负样本选取上,考虑到对 简单负样本 和 困难负样本 的混合选取;并将训练任务转化为分类问题,根据不同的训练方式推理了对应的 交叉熵损失或合页损失。

但是双塔模型也存在严重的头部效应,不能很好地处理长尾数据,只对高点击物品的表征学的好。所以引入 自监督学习 的思想,使用多种不同的 特征变换(Mask、Dropout、互补等),更好地 处理长尾数据、更充分地 学习用户和物品的表征信息。

同时,除了基于用户和物品的协同过滤外,本章还介绍了一些基于 地理位置、作者 的召回通道。另外介绍了一种 缓存召回,通过设置 退场机制,可以重新利用被精排过滤的召回结果。

以上都是对模型和训练思想的介绍,而在实际中训练完模型要将模型推全上线。进行 线上计算 的时候,需要使用 最近邻查找 进行召回结果的输出。原始的最近邻查找的计算代价太大,前人提出了多种加速最近邻查找的方法。除此之外,为了降低线上模型的计算复杂度和时间,需要做 线下计算存储物品的表征, 并 建立多种索引 方便快速查找 。 而在模型上线后,使用 全量更新 和 增量更新 进行模型的更新迭代 。

最后,在推荐系统中,为了避免出现给用户重复推荐物品的问题,需要在召回层进行 曝光过滤。Bloom Filter 是一种常用的方法,但是它只 支持添加物品、不支持删除物品, 而且存在一定的 误伤概率。

三. 排序​

前面介绍过,虽然所用的神经网络的深度与规模不同,但粗排和精排都是对召回后的物品再进行排序的操作,总体上思想与框架相同。所以这一章大部分内容都以排序(模型主要为精排,粗排单独分节)为主体进行介绍,无特殊说明则不区分粗排和精排。

多目标模型​

用户与笔记的交互

在介绍转化流程中有说过,用户与物品的交互可以作为系统推荐的依据。在小红书中,对于每篇笔记,系统记录曝光次数、点击次数、点赞次数、收藏次数、转发次数,由此计算得到 消费指标,可以衡量一篇笔记受欢迎的程度:

  1. 点击率 = 点击次数 / 曝光次数;(注意点击率这里是曝光次数)
  2. 点赞率 = 点赞次数 / 点击次数;
  3. 收藏率 = 收藏次数 / 点击次数;
  4. 转发率 = 转发次数 / 点击次数。(转发很少,但是很重要)

排序的依据

在得到消费指标后,那么如何实现衡量物品受欢迎程度呢?前面介绍在召回中,模型利用用户和物品的多维特征属性(ID,画像等),通过计算得到用户对物品的兴趣分数。而在排序中的基本思想如下:

  1. 排序模型预估点击率、点赞率、收藏率、转发率等多种物品;
  2. 融合这些分数;(比如加权和,权重由 A/B 测试调整选出)
  3. 根据融合的分数做排序、截断。

多目标模型

工业界常用多目标模型作为排序模型,模型基本结构如图所示:

Tips:

  1. 统计特征包括用户和物品的统计特征,比如用户在 30 天内点赞了多少篇笔记、候选物品在 30 天内获得了多少次曝光机会等;
  2. 场景特征包括用户所在的时间、地点等,比如候选物品在不同的城市、季节以及节假日影响,用户对其有完全不同的兴趣程度;
  3. 在精排中,这里的神经网络被称为 shared bottom ,是非常大、结构非常复杂的神经网络。

模型训练

通过上述模型可以得到譬如点击率、点赞率、收藏率、转发率的预估值,不妨设这些预估值为 ,这些指标的真实值为 ,真实值为 表示无该动作、真实值为 表示发生该动作。模型的训练就是一个预估值拟合真实值的过程,在该任务中实际上就是要解决四个二分类问题,分别判断用户是否点击、点赞、收藏、转发物品。二分类问题通常使用交叉熵损失,所以综合考虑四个二分类问题的损失,多目标模型的训练 如下:

  1. 总的损失函数: ,其中超参数 是各个损失的权重。
  2. 对损失函数求梯度,做梯度下降更新参数。

而在训练中,也存在 困难,最大的问题就是 类别不平衡:

  1. 每 100 次曝光,约有 10 次点击、90 次无点击;
  2. 每 100 次点击,约有 10 次收藏、90 次无收藏。

显然,负样本的数量要远远多于正样本。常见的 解决方案 是进行 负样本降采样(down-sampling):

  1. 保留一小部分负样本,让正负样本数量平衡;
  2. 减少了负样本数量,节约计算。

预估值校准

在模型输出各个指标预估值之后,需要先进行 预估值校准,才能做后续的排序。主要 原因 在于:

  1. 以点击率为例,设正样本、负样本数量为 和 ;
  2. 真实点击率: (期望)。
  3. 对负样本做降采样会抛弃一部分负样本, 设 为采样率,则训练时使用了 个负样本;
  4. 预估点击率: (期望),显然由于负样本变少,分母变小,导致预估点击率大于真实点击率。

实际上预估值校准就是希望通过函数调整预估值,使得其能与真实值一致,根据上述两个点击率的等式可得对点击率预估值的 校准公式为: 。这里个人给出公式推导过程:

  1. 对于预估点击率 ,等式右边的分子、分母同时除以 得到 ;
  2. 等式两边同乘以等式右边的分母得 ;
  3. 展开等式左边的括号并移项得 ;
  4. 所以两边同除以系数得到 ,也就是 ;
  5. 现在将上一步中由预估点击率推导的 和 的关系式代入真实点击率公式 ,得到 ;
  6. 对该公式上下同除以 、乘以 后整理得到校准公式:,推导完毕。

Tip:这里会思考一个问题,如果只做排序,校准与否不会影响排序的结果,那校准的意义在于什么呢?可能存在以下的原因:

  1. 以点击率为例,如果只是单纯优化点击这一项,通过降采样后各个物品的点击率的相对顺序不会变化,不做校准不会影响;
  2. 但是多目标模型涉及到多个指标结果的相乘或计算,而且多目标任务不校准无法统一量纲,所以必须进行校准;
  3. 另外在广告系统中,点击率需要参与广告计费的计算,必须需要校准后的精确值,当然校准方法也不仅限于预估值校准了。

Multi-gate Mixture-of-Experts (MMoE)​

MMoE 模型

MMoE 模型是对经典多目标模型的改进,它的 基本思想 就是对于不同的目标,在融合特征之后,先利用“专家”得到多个表征向量,同时分别利用神经网络得到不同的权重,最后对向量做加权平均输出预估值,具体模型架构如下图所示:

Tips:

  1. 图中第 1、2、3 号神经网络就是该模型的三个“专家”(experts),该专家数是超参数,在实际训练中多会尝试四个和八个的情况;
  2. 如果有 个专家,则会输出 个向量 ,那么计算权重时每个 Softmax 的输出和输入也都是 维向量;
  3. 对于多个目标就需要对应数量的神经网络组合来计算不同权重和预估值。

极化现象

现实应用中,使用 Softmax 激活函数会不可避免的出现 极化现象(Polarization):

  1. 极化(Polarize):Softmax 的输出只有一个接近 ,其余接近 ;
  2. 譬如在介绍 MMoE 模型的示意图中,假设左边的 Softmax 输出是 ,相当于后续的预估值计算时只使用了第三号神经网络输出的向量;假设右边的 Softmax 输出是 ,相当于只使用了第二号神经网络。那么第一号神经网络在模型的训练中没有起到任何作用,相当于它“dead”了,使用 Mixture-of-Experts 的意义也就失去了。

解决极化问题 的基本方案就是在训练时,对 Softmax 的输出 使用 Dropout:

  1. Softmax 输出的 个数值被 Mask 的概率都是 10%;
  2. 也就是说每个专家被随机丢弃的概率都是 10%,使得每个任务只使用部分专家做预测,强迫每个专家都参与训练。

预估分数融合​

通过多目标模型,我们得到了点击率、点赞率、收藏率等的预估值 等。在排序之前,需要融合这些预估分数,常见的方法如下:

  1. 简单的加权和: 。
  2. 点击率乘以其他项的加权和: 。由指标的计算公式可知,其实这里相当于把其他项的分母由点击次数替换成了曝光次数。
  3. 海外某短视频 APP 的融合分公式: 。其中 是对短视频观看时长的预估, 和 都是超参数,需要通过 A/B 测试调整,后面出现不再赘述。
  4. 国内某老铁短视频 APP 的融分公式(Ensemble sort):
    (1)根据预估时长 ,对 篇候选视频做排序;
    (2)如果某视频排名第 ,则它得分为 ,时长越长排序越靠前则得分越高;
    (3)对点击、点赞、转发、评论等预估分数做类似处理;
    (4)对以上处理完的分数做加权和,得到最终融合分数: 。
  5. 某电商的融分公式:
    (1)电商的转化流程:曝光 → 点击 → 加购物车 → 付款;
    (2)模型预估:点击率、加购物车率、付款率,分别记作 ;
    (3)最终融合分数: 。

视频播放建模​

前面介绍了对于图文笔记这类排序的主要依据,包括但不仅限于点击、点赞、收藏、转发、评论等。而在视频的排序依据还有 播放时长 和 完播,一般对于视频来说,这两个指标的重要性远高于其他指标。

视频播放时长

视频的播放时长是连续型变量,但是直接用回归拟合播放时长效果并不好。建议使用 YouTube 的时长建模,这里假设有一个计算排序预估值的多目标模型,先不考虑点击率等指标,仅研究播放时长:

  1. 不妨设模型最后的全连接层输出一个预估值 ,对 做 sigmoid 变换得到 ;
  2. 模型的 训练目标 是让 拟合 ,其中 为真实视频播放时长,使用交叉熵损失 ;
  3. 注意观察 和 的表达式,显然如果 则 ,所以在进行 推理时, 就是对播放时长 的 预估;
  4. 最后,将 作为融分公式的一项。

视频完播率

对视频完播率的建模方法主要有回归和分类的两种方法,基本思想概括为:

  1. 回归方法:用预估播放率 拟合实际播放率 ,使用交叉熵损失 做训练,模型的输出 是预估完播率。
  2. 二元分类方法:定义完播 的时长作为完播指标,做二元分类训练模型(播放 > vs 播放 < ),此时的模型输出 表示

但是这里千万注意,与前面介绍的不同,我们不能直接将预估的完播率用到融分公式中。原因在于视频的时长越长,它的完播率越低,模型训练没有考虑视频时长的影响,不能平等对待长短视频。因此,做如下处理:

  1. 线上预估完播率,然后做调整:
  2. 将 作为融分公式中的一项

排序模型的特征​

特征类别

在召回和排序中,都需要用到用户和物品的多维特征,主要包括:

特征类别特征描述
用户画像(User Profile)1. 用户 ID(在召回、排序中做 embedding,常用 32 维和 64 维);
2. 人口统计学属性:性别、年龄;
3. 账号信息:新老、活跃度等;*
4. 感兴趣的类目、关键词、品牌等。
物品画像(User Profile)1. 物品 ID(在召回、排序中做 embedding);
2. 发布时间(或者年龄);**
3. GeoHash(经纬度编码)、所在城市;
4. 标题、类目、关键词、品牌等;
5. 字数、图片数、视频清晰度、标签数等;
6. 内容信息量、图片美学等。
用户统计特征1. 用户最近若干时间的曝光数、点击数、点赞数、收藏数等;
2. 按照笔记图文/视频分桶 ;***
3. 按照笔记类目分桶;****
笔记统计特征1. 笔记最近若干天的曝光数、点击数、点赞数、收藏数;
2. 按照用户性别分桶、按照用户年龄分桶等;
3. 作者特征:发布笔记数、粉丝数、消费指标等。*****
场景特征(Context)随着推荐请求传来,不用从用户和物品画像中获取。
1. 用户定位 GeoHash(经纬度编码)、城市;
2. 当前时刻(分段,做 embedding);
3. 是否周末、是否节假日;
4. 手机品牌、手机型号、操作系统。******

Tips:表中注释的扩充内容如下

* :新老、高低活用户的行为差距很大,模型需要针对做专门的优化;

** :一般小红书中笔记发布时间越久价值越低,尤其是与新闻舆论相关的时效性只有几天;

*** :例如最近 7 天,该用户对图文笔记的点击率、对视频笔记的点击率;

**** :例如最近 30 天,用户对美妆笔记的点击率、对美食笔记的点击率、对科技数码笔记的点击率;

***** :反映作者的受欢迎程度和作品的平均品质;

******:安卓和 ios 的指标差异特别大

特征处理

对于不同类型的特征进行处理的方式如下:

特征类型处理方式特征描述
离散特征做 embedding1. 用户 ID、笔记 ID、作者 ID 等;(消耗内存较大)
2. 类目、关键词、城市、手机品牌。
连续特征做分桶,变成离散特征年龄、笔记字数、视频长度等
连续特征其他变化1. 曝光数、点击数、点赞数等数值做 变换 ;
2. 转化为点击率、点赞率等值,并做平衡。

上表中的 变换针对长尾数据,可以处理异常值。当然,在做特征处理时,除了要考虑异常值还需要考虑 特征覆盖率。实际上,大多数特征无法覆盖 100%样本(不写年龄、设置隐私权限等)。显然,提高特征覆盖率可以让精排模型更准,所以在特征处理时还需要考虑如何做缺失值的补全。

Tip:本节内容还有一部分与线上服务的系统架构相关的内容,这里省略。

粗排模型​

虽然本章内容不具体细分粗排和精排,但是前序内容主要还是描述精排模型。所以这节单独介绍粗排模型。

粗排 vs 精排

粗排是在精排之前进行快速初步筛选的操作,所以粗排和精排有存在一些区别:

粗排精排
任务给几千篇笔记打分给几百篇笔记打分
推理代价单次推理代价必须小单次推理代价很大
准确性预估的准确性不高预估的准确性更高

精排模型 vs 双塔模型

精排模型双塔模型
融合方式前期融合:先对所有特征做 concatenation,再输入神经网络。后期融合:把用户、物品特征分别输入不同的神经网络,不对用户、物品特征做融合。
推理代价线上推理代价大:如果有 n 篇候选笔记,整个大模型要做 n 次推理。线上计算量小:用户塔只需要做一次线上推理,而物品表征通过线下计算事先存储在数据库中,物品塔在线上不做推理。

显然,双塔模型的预估准确性不如精排模型,后期融合适合快速做召回,而前期融合更适合去精准排序。

粗排的三塔模型

小红书的粗排模型是 三塔模型,效果介于精排和双塔模型之间,模型架构如下图所示:

如图可见,实际上粗排模型的输出、训练与精排完全一致,主要区别在于下面的三个塔,该模型介于前期融合和后期融合之间(其实如果把三个塔看作 embedding 的一部分, 两者就是相同的)。这样设计的原因在于:

  1. 只有一个用户,用户塔只用做一次推理。因此即使用户塔很大,总计算量也不大。
  2. 有 个物品,理论上物品塔需要做 次推理。所以需要缓存物品塔的输出向量,避免绝大部分推理。
  3. 交叉塔的输入(统计特征等)动态变化,缓存不可行。而有 个物品,交叉塔必须要做 次推理,所以交叉塔必须要小。

而在模型的上层,有 个物品必须要做 次推理。上层推理的计算量要高于交叉塔,也是粗排的大部分计算量所在。这里总结下 三塔模型的推理:

  1. 从多个数据源取特征:
    (1) 个用户的画像、统计特征;
    (2) 个物品的画像、统计特征。
  2. 用户塔:只做一次推理。
  3. 物品塔:未命中缓存时需要做推理。
  4. 交叉塔:必须做 次推理。
  5. 上层网络做 次推理,给 个物品打分。

本章小结​

本章主要讲解了排序中的 粗排模型 与 精排模型。

精排模型为 多目标模型,先融合用户和物品的多个特征输入神经网络(shared bottom),输出各个指标的预估值(前期融合)。

在多目标模型的基础上,前人提出了 MMoE 模型。它的基本思想是对于不同的目标,先利用“专家”得到多个表征向量,同时分别利用神经网络得到不同的权重,最后对 向量做加权平均 输出预估值。该模型因为使用 Softmax 函数,会不可避免的出现 极化现象,通过使用 Dropout 可以强迫每个 expert 都参与训练决策。

而小红书的粗排模型是 三塔模型。 它与精排模型的不同在于下层结构是先通过塔(神经网络)得到特征向量。再融合向量输出预估值,是 介于前期融合和后期融合(双塔模型)之间的一种思想。这种思想有利于粗排快速推理,降低线上计算代价。

虽然以上模型架构有所区别,但是它们同归排序模型,具有 相同的训练方式。在训练之前,与召回相似,需要收集 用户与物品的多维特征 并进行 特征处理(embedding、异常值、缺失值等)。在模型训练时,将问题转化为二分类问题,使用 交叉熵损失 训练。训练的时候存在 类别不平衡 问题,需要进行 负样本降采样。而且,在模型训练后,需要做 预估值校准,才能进行排序。训练完模型进行线上排序时,需要融合模型输出的多个指标预估值再排序,而针对不同的任务有不同的 融分公式。

除此之外,另外单独介绍了对 视频播放的建模 方法。对视频播放建模还需要单独考虑 播放时长 和 完播率,并给出了对应的预估值和训练、推理方式。

四. 特征交叉​

特征交叉是对多个单独特征进行组合(内积、外积、笛卡尔积等)来合成特征的过程,实现对样本空间的非线性变换, 来增加模型的非线性能力。

Factorized Machine(FM)​

早些年常用的特征交叉手段是 Factorized Machine(FM),不妨先逐步了解下 FM 的基本思想。

线性模型

线性模型对输入的特征取加权和,作为对目标的预估,基本思想如下:

  1. 设有 个特征,记作 ;
  2. 则线性模型公式为: ;
  3. 线性模型有 个参数:权重 和偏置 ;
  4. 显然,预测值 是特征的加权和(只有加,没有乘)。

二阶交叉特征(POLY2)

如果先做特征交叉,再用线性模型,通常可以取得更好的效果。二阶交叉特征的基本思想如下:

  1. 设有 个特征,记作 ;
  2. 二阶特征交叉: ;
  3. 线性模型 + 二阶特征交叉: ;
  4. 模型有 个参数(主要是二阶特征交叉中的权重 )。

特征交叉使得线性模型中的特征不仅仅只是相加,还能相乘,有效地提升了模型的表达能力。

Factorized Machine(FM)

在实际做二阶特征交叉时,因为参数量大导致的计算量大,而且还容易造成过拟合。因此,基于二阶特征交叉改进的 FM 的基本思想如下:

  1. 对于二阶交叉特征中的权重系数 ,通常组成权重矩阵 来方便计算;
  2. 由于矩阵 是 维的,可以进行 低秩矩阵分解,得到 维的矩阵 满足 ;
  3. 所以对应的权重系数满足 ,替换线性模型 + 二阶特征交叉的组合,得到 Factorized Machine 的公式: ;
  4. FM 模型有 个参数,这里的 。

因此,总结下 FM 的主要优点在于:

  1. FM 是线性模型的替代品,能用线性回归、逻辑回归的场景都可以用 FM ;
  2. FM 使用二阶交叉特征,表达能力比线性模型更强;
  3. 通过做近似 ,FM 把二阶交叉的权重数量从 降到了 ,大大加速了计算。

Tip:现在早已不再使用 FM 做特征交叉了。

DCN 深度交叉网络​

在召回双塔模型、粗排三塔模型以及精排模型应用的神经网络时(MMoE 的“专家”神经网络),可以使用全连接网络、本节将要介绍的深度交叉网络或者任何更好地网络架构。深度交叉网络(Deep & Cross Networks,DCN)由一个 深度网络 和一个 交叉网络 组成,交叉网络的基本组成单元是 交叉层 (Cross Layer),也是本节最重要的内容。

交叉层

如下图所示,是交叉层的基本结构:

简单来说,单个交叉层的基本流程为:

  1. 初始输入向量 ,经过若干层神经网络后输出向量 ,这两个都是交叉层的输入;
  2. 将向量 输入全连接层,输出向量 ;
  3. 初始输入 和向量 的 Hadamard 乘积(对应位置逐个元素相乘)得到向量 ;
  4. 将向量 和 加和得到交叉层的输出 。

所以,交叉层的主要参数在所使用的全连接层中,其他求和和求 Hadamard 乘积的操作不涉及参数。故交叉层也可以写成公式: ,其中 和 是全连接层的权重和偏置、 表示 Hadamard 乘积(逐元素相乘)。

交叉网络

如下图所示, 是 Cross Network V2 的基本架构:

其中值得注意的是,第一个交叉层的输入只有一个初始向量 ,故该交叉层的输出 计算公式为: 。随后可以根据实际需要,多次叠加交叉层。

深度交叉网络

如下图所示,深度交叉网络的基本思想就是将用户和物品的特征拼接起来,分别输入全连接网络和交叉网络,将得到的两个向量拼接后输入全连接层,得到最后的输出。

LHUC(PPNet)​

LHUC(Learing Hidden Unit Contributions)也是一种 神经网络结构,与 DCN 的思想有些类似,只能用于 精排。LHUC 的起源是语音识别,后来被应用到推荐系统,快手将其称为 PPNet,现在已经在业界广泛落地。

语言识别中的 LHUC

语音识别的输入是一段语言信号,目标是对该信号做变换得到表征,可以实现识别出其中文字。而不同的人的语速、腔调都不同,所以需要加入一些个性化因素,需要将说话者的特征也作为输入。如下图所示是语音识别中的 LHUC 架构:

其中值得注意的是:

  1. 图中两个“神经网络”的输入都是初始输入中说话者的特征,与上面全连接层不同;
  2. 图中“神经网络”的结构为多个全连接层+Sigmoid 变换后乘以 2,这样与语音信号做 Hadamard 乘积时,可以放大或缩小一些特征,实现个性化;
  3. 如果需要更深层的网络,可以继续如上图操作叠加。

推荐系统排序模型中的 LHUC

在精排模型中,LHUC 将“语言信号”替换为“物品特征”,“说话者的特征”替换为“用户特征”,其他结构不变。

SENet & Bilinear Cross​

SENet 和 Bilinear 交叉一般应用在 排序 模型中,都有一定的正收益。

SENet

SENet 是计算机视觉中的一种技术,可以用在推荐系统中对特征做 动态加权。在推荐系统中的 SENet 架构如下:

图中输入 的维矩阵每行就是用户和物品每个特征的 embedding 。通过一系列变换操作,得到的 维矩阵实际上就是权重矩阵。因为 row-wise multiply 是将两个矩阵按行相乘,得到的矩阵与初始矩阵维数一致,显然相当于每行(每个特征)赋予了不同的权重,调整了矩阵元素的值。

所以 SENet 的基本思想为:

  1. SENet 对离散特征做 field-wise 加权;
  2. 如上图所示,field 如下解释:若某特征的 embedding 是 维向量,称向量中的 个元素归为一个 field,获得相同的权重;
  3. 如果有 个 field ,那么权重向量是 维的;
  4. 值得注意的是,不同的特征 embedding 向量维度可以不同。

Bilinear Cross

前面使用过的内积和 Hadamard 乘积都是在 field 间做简单特征交叉方法,不妨设有两个同为 维的 field 记为 和 ,则有如下公式:

  1. 内积: ;
  2. Hadamard 乘积:。

如果有 个 filed,那么求内积得到 个实数;而求 Hadamard 乘积得到 个向量,数据量爆炸,必须人工选择少数向量参与。而且,当参与交叉的 两个 field 形状不一样也无法求内积和 Hadamard 乘积。因此,基于内积和 Hadamard 乘积,一种先进的特征交叉方法被提出,即 Bilinear Cross。此时不妨设有 和 维的 field 记为 和 ,则公式表达如下:

  1. 基于内积的 Bilinear Cross: ,其中 为 维的参数矩阵;
  2. 基于 Hadamard 乘积的 Bilinear Cross: ,其中 为 维的参数矩阵;

同样如果有 个 filed,那么第一种交叉方法需要保存 个参数矩阵,数据量还是过大,需要做人工的特征选择或者矩阵分解;第二种交叉方法得到 个向量,同样需要做人工筛选。

FiBiNet

FiBiNet 是 SENet 与 Bilinear Cross 的结合,模型架构如下:

该模型与排序模型的区别主要在离散特征的处理上,引入了 Bilinear Cross 做特征交叉和使用 SENet 进行特征 embedding 的动态加权。在小红书的实际应用中,并没有招搬该模型,比如其中在 SENet 之后的 Bilinear Cross 被认为是无意义的。

本章小结​

本章主要是对特征交叉和基于特征交叉改进的模型的介绍。

特征交叉 有利于捕获特征间的共现关系,从而提升模型准确度。同时,通过特征交叉可以生成新的特征,甚至未知的特征组合,有利于提升模型泛化能力。最后,现实世界是高度非线性的,通过 内积、外积、Hadamard 积、Bilinear Cross 等特征交叉方式,可以提升模型非线性能力。

早些年常用的 Factorized Machine(FM) 是基于 线性模型 和 二阶特征交叉组合 的,FM 使用低秩 矩阵分解,将二阶特征交叉中的权重矩阵近似分解为两个低秩矩阵,以减少计算量,防止过拟合。不过业界早已不再使用 FM。

随后介绍了两种可用于替换召回或排序模型中神经网络的模型架构,它们都是基于 Hadamard 积和特征交叉进行改进的。第一个是 深度交叉网络(DCN),可被用于 召回和排序 中。它由一个 深度网络 和一个 交叉网络 组成,交叉网络的基本组成单元是 交叉层,交叉层即是对输入特征的一种特征交叉 。 DCN 的基本思想就是将用户和物品的特征拼接起来,分别输入全连接网络和交叉网络,将得到的两个向量拼接后输入全连接层得到最后的输出。

第二个是 Learing Hidden Unit Contributions (LHUC),它是被用于 精排 中的一种神经网络结构。LHUC 源于语言识别,而它在推荐系统中利用物品特征和用户特征做特征交叉,思想与 DCN 相似。其中对于用户特征的输入使用多层全连接层+Sigmoid 乘以 2 以实现调整物品特征表征的权重,以实现个性化。

最后,本章还介绍了一种由 SENet 和 Bilinear Cross 组合的模型 FiBiNet , 常用于 排序 中。该模型与排序模型的区别主要在离散特征的处理上,引入了 Bilinear Cross 做 特征交叉 和使用 SENet 进行特征 embedding 的 动态加权。在小红书的实际应用中,对 FiBiNet 诸多地方有所调整优化。

五. 行为序列​

用户最近对物品的点击、点赞、收藏、转发等行为都是推荐系统中重要的特征,可以帮助 召回 和 排序 变得更精准。一般称这些用户的行为序列为 ,表示用户最近交互过 个物品。本章介绍对用户行为序列建模的方法,重点关注用户特征中的 行为序列。

用户行为序列建模​

最简单的用户行为序列建模方法就是对用户行为取简单的 平均,作为特征输入召回、排序模型。

特征

特征可以反映用户过去一段时间内对物品的兴趣,主要思想为:

  1. :用户最近 次交互(点击、点赞等)的物品 ID;
  2. 对物品 ID 做 embedding,得到 个向量;
  3. 将个 向量取平均,作为用户的一种特征;
  4. 使用于 召回双塔模型、粗排三塔模型、精排模型。

小红书的实践

如下图所示,在小红书的实际应用中,将点击、点赞等交互行为的 做 embedding,通过对每类的 embedding 向量求平均得到多个 特征,最后将这些特征拼接起来,输入召回或排序模型实现任务。

虽然对 embedding 向量求平均很常用,但实际效果更好的是 attention,不过计算量更大。实际应用时,也会将物品其他特征与物品 ID 的 embedding 拼接到一起输入。

DIN 模型(注意力机制)​

DIN 模型

DIN 模型是对 序列建模的一种方法,使用 加权平均 代替平均,本质是 注意力机制(attention),权重 即是候选物品与用户 物品的 相似度。如下图所示,基本思想如下:

  1. 设有某候选物品向量为 ,用户 物品向量 ;
  2. 对于该候选物品,计算它与用户 物品的相似度 ;
  3. 以相似度为权重,求用户 物品向量的加权平均,结果是一个向量 ;
  4. 把得到的向量 作为一种用户特征,输入排序模型,预估(用户,候选物品)的点击率、点赞率等指标。

image-20250731140851905

如果这里将用户 物品向量作为注意力机制中的 和 、候选物品向量作为 ,输入单头注意力层,就能起到与 DIN 模型一致的效果。

简单平均 vs 注意力机制

在进行用户 序列建模时,使用注意力机制的效果优于简单的平均,但是需要考虑注意力机制的适用性问题。如下表所示:

简单平均注意力机制
适用模型适用于双塔模型、三塔模型、精排模型适用于精排模型,不适用于双塔模型和三塔模型
原因分析1. 简单平均只需要用到 lastN,属于用户自身的特征;
2.只需将向量 lastN 的平均作为用户塔的输入。
1. 注意力机制需要用到 lastN 和候选物品;
2. 用户塔无法看到候选物品,无法将注意力机制应用在用户塔。

DIN 模型的缺点:

  • 注意力层的计算量 (用户行为序列的长度)
  • 只能记录最近几百个物品,否则计算量太大
  • 关注短期兴趣, 遗忘长期兴趣

SIM 模型(长序列建模)​

SIM 模型是为了解决 DIN 模型的缺点而诞生的,主要目的就是 保留用户的长期兴趣。

DIN 模型的缺点与改进

上一小节介绍了本质为注意力机制的 DIN 模型。在它做注意力层计算时,计算量正比于用户行为序列的长度(也就是交互的物品数 )。所以为了防止计算量过大,它只能记录最近几百个物品,这就存在一个 问题:DIN 模型 只关 注短期兴趣、遗忘长期兴趣。而在实践中,长序列(长期兴趣)的效果是要优于短序列(短期兴趣)的。

所以,为了能使 DIN 模型能保留用户长期行为序列( 很大),且计算量不会过大,有如下的 改进思路:

  1. 使用 DIN 模型对用户 物品向量做加权平均,权重是相似度
  2. 如果某 物品与候选物品的差异很大,则权重接近零,可以过滤掉
  3. 这样可以快速排除掉与候选物品无关的 物品,降低注意力层的计算量

简单点就是说给 DIN 输入加一个层级漏斗

这个改进思路就是 SIM 模型,在工业中实践有效。

SIM 模型

依据对 DIN 模型的改进思路,SIM 模型的 基本思想 为:

  1. 保留用户长期行为记录, 的大小可以是几千;
  2. 对于每个候选物品,在用户 记录中做 快速查找,找到 个相似物品;
  3. 把 变成 ,然后输入到 注意力层;
  4. SIM 模型实现了计算量的减小(从 降到 )。

根据上文的描述,SIM 模型主要包括两个步骤。第一步:查找。查找的方法主要有两种,如下表所示:

方法Hard SearchSoft Search
基本思想根据候选物品的类目,保留 LastN 物品中类目相同的。1. 对物品做 embedding 变成向量;
2. 将候选物品向量作为 query ,做(近似)k 近邻查找,保留 LastN 物品中最接近的 k 个。
特点简单、快速,无需训练。效果更好,编程实现更复杂。

具体使用何种方法做筛选,根据工业实际应用时的硬件条件来做选择。而第二步是:注意力机制。SIM 模型的注意力机制结构与 DIN 一致,只是将输入的 向量变成 向量。在这个环节,还在存在一个有用的 trick,就是 使用时间信息:

  1. 设用户与某个 物品的交互时刻距今为 ;
  2. 对 做离散化,再做 embedding,变成向量 ;
  3. 将物品的 embedding 向量 与时间向量 做 concatenation,用于表征这个 物品。

相比于 DIN,SIM 使用时间信息的的出发点在于:

  1. DIN 的序列短,记录用户近期行为;
  2. SIM 的序列长,记录用户长期行为;
  3. 时间越久远,重要性越低。

所以,作为记录用户长期兴趣的 SIM 模型,很有必要去考虑时间信息对特征的影响。

本章小结​

本章主要介绍了对用户行为序列的建模方法,可以帮助 召回 和 排序 变得更精准。换言之,本章就是介绍对 用户 物品特征 的应用,最常用的方法是对特征的 embedding 向量求 平均。

DIN 模型 则使用 加权平均 代替简单平均,本质上是 注意力机制 的应用。DIN 通过计算候选物品向量与用户 物品特征向量的相似度得到权重,根据这个权重求用户 物品特征向量的加权平均,得到特征用于后续任务。同时,也可以将用户 物品特征向量看成 和 、候选物品向量看成 输入注意力层,得到与 DIN 模型一致的结果。但是注意力机制还需要考察候选物品向量,无法在用户塔中实现,所以 DIN 模型只适用于 精排。

同时,由于注意力机制的复杂性较高,DIN 模型还存在一个缺点:关 注短期兴趣、遗忘长期兴趣。 基于此,提出了 保留用户长期兴趣 的 SIM 模型。 SIM 模型的原理是对用户行为序列做快速筛选,缩短序列长度,使得 DIN 可以用于长序列。实际上就是通过 快速查找,找到 向量来替换 向量输入 注意力机制 中,得到所需特征向量。在 SIM 的注意力机制环节中,可以 使用时间信息。主要考虑时间的久远对用户对物品兴趣的影响,将时间信息向量与物品向量拼接输入,可以得到更好的结果。

六. 重排​

重排是对精排结果的顺序进行再次微调,一方面是为了实现全局视角的最优排序,另一方面是为了满足特定业务诉求和提升用户体验。实际上重排是对推荐系统中多样性的考察,多样性更能体现用户的个性化。如果多样性做得好,可以显著提升推荐系统的核心业务指标。

推荐系统中的多样性​

这节是对多样性相关基础知识的介绍。在介绍多样性算法前,先了解对物品相似度的度量方法和提升多样性的方法。

物品相似性的度量

度量两个物品相似度的方法主要有两种。第一种是基于 物品属性标签 的方法:

  1. 物品属性标签:类目、品牌、关键词等;
  2. 譬如,可以根据一级类目、二级类目、品牌计算相似度:
    (1)物品 :美妆、彩妆、香奈儿;物品 :美妆、香水、香奈儿;
    (2)相似度: ,,。
    对以上三个相似度求加权和得到物品相似度,权重由人为设定。

第二种是基于 物品向量表征 的方法。前文介绍过,在召回的双塔模型中,物品塔学习物品的向量计算相似度,但是由于长尾数据的问题,这种方法实际效果并不好。一般来说,更多地应用 基于内容的向量表征,在小红书中就是 用 CV 和 NLP 模型提取图片和文字特征向量。简单介绍如下:

  1. 小红书的笔记都是文字+图片的组合,一般来说图和文字相关性较大;
  2. 以只有一张图的情况为例,通过 CNN 模型将图片转化为向量,通过 BERT 模型将文字转化为向量;
  3. 将这两个向量拼接起来就是该图文笔记的向量表征,可以输入后续的任务中。

但是,这里存在一个问题,CNN 和 BERT 两个模型如何训练得到?如果使用数据进行训练,得到的模型并不适用于小红书的任务场景;如果人工标注数据,任务量非常大。所以,CLIP 是当前 公认最有效的预训练方法,它的基本思想为 :

  1. 思想:对于“图片—文本”二元组,预测图文是否匹配。
  2. 正负样本:来自同一篇笔记的图文作为正样本,来自不同笔记的图文作为负样本(batch 内负样本).
  3. 优势:无需人工标注。小红书的笔记天然包含图片和文字,大部分笔记图文相关。

提升多样性的方法

推荐系统中希望提高曝光物品的多样性,也就是尽量使得物品之间两两不相似。前面主要介绍了粗排和精排的流程思想,但实际在粗排后精排之后需要进行 后处理:

  1. 粗排 和 精排 用多目标模型对物品做 pointwise 打分。对于物品 ,模型输出点击率、交互率等的预估,融合成分数 。 表示用户对物品的兴趣,即物品本身的价值。那么给定 个候选物品,排序模型打分为 。
  2. 后处理 则从 个候选物品中选出 个,既要它们的总分高,也需要它们有多样性。

后处理的作用就是提升了多样性,有利于业务指标的增长。精排之后的后处理就是 重排;而粗排之后一般也存在后处理,不可忽视。

MMR 多样性算法(用于精排后处理)​

Maximal Marginal Relevance(MMR)是最早来自于搜索排序的算法,使用相关性进行排序。要解决的问题设定如下:

  1. 精排给 个候选物品打分,融合之后的 分数 为 ;
  2. 把第 和 个物品的 相似度 记作 ;
  3. 根据以上两个值,从 个物品中选出 个作为曝光的结果,要求既要有高精排分数,也要有多样性。

MMR 多样性算法

不妨记选择的物品集合为 ,未选中的物品集合为 。那么计算集合 中每个物品 的 Marginal Relevance 分数: ,其中 是超参数,用于调整精排分数与多样性的权重占比。

基于该分数,此则 MMR 的基本思想 为:

  1. 已选中的物品 初始化为空集,未选中的物品 初始化为全集 ;
  2. 选择精排分数 最高的物品,然后从集合 移到 ;
  3. 重复上一步做 轮循环:
    (1)计算集合中 中所有物品的分数 ;
    (2)选出分数最高的物品,将其从 移到 。

滑动窗口

根据前面的解释,标准 MMR 公式: 。在实际应用,该公式存在 问题:

  1. 已选中的物品越多(即集合 越大时),越难找出物品 ,使得 与 中的物品都不相似;
  2. 具体分析下原因:设 的取值范围为 。当 很大时,多样性分数 总是约等于 ,导致 MMR 算法失效。

针对这个问题提出的 解决方案 就是:设置一个滑动窗口 (比如最近选择的 10 个物品),用 代替公式中的 。则得到 使用滑动窗口的 MMR 公式: 。

在工业界滑动窗口是非常常用的,实践中滑动窗口的效果更优。滑动窗口的应用存在 直观解释:给用户曝光的物品应当具有多样性,也就是物品两两之间不相似;但没有必要让第 30 个物品与第 1 个物品不相似,用户看到第 30 个物品时大概率已经忘记了第 1 个物品是什么了。换言之,两个离得远的物品可以相似,并不会影响用户体验;但如果两个离得近物品就应当有较大差异,否则用户能感知到缺乏多样性。

业务规则约束下的多样性算法​

工业应用为了 保护用户体验,会设定很多 业务规则。进行重排时必须要满足这些规则。

重排的规则

这里举出小红书中的几个典型例子,

规则规则说明
最多连续出现 k 篇某种笔记1. 小红书的推荐系统的物品分为图文笔记和视频笔记;
2. 最多连续出现出现 篇图文笔记,最多连续出现 篇视频笔记;
3. 如果排序 到 都是图文笔记,那么排在 的必须是视频笔记。
每 k 篇笔记最多出现 1 篇某种笔记1. 运营推广笔记的精排分会乘以大于 1 的系数(boost),帮助笔记获得更多的曝光;
2. 为了防止 boost 影响体验,限制每 k 篇笔记最多出现 1 篇运营推广笔记;
3. 如果排第 i 位的是运营推广笔记,那么排 i+1 到 i+k-1 的不能是运营推广笔记。
前 t 篇笔记最多出现 k 篇某种笔记1. 排名前 t 篇笔记最容易被看到,对用户体验最重要;(小红书 top4 的为首屏)
2. 小红书推荐系统有带电商卡片的笔记,过多可能会影响体验;
3. 前 t 篇笔记最多出现 k 篇带电商卡片的笔记。

MMR + 重排规则

这里说明如何将这些规则与多样性算法相结合:

  1. MMR 每一轮选出一个物品: 。
  2. 重排结合 MMR 与规则,在满足规则的前提下最大化 :
    (1)每一轮先用规则排除掉 中的部分物品,得到子集 ;
    (2)MMR 公式中的 替换成子集 :,这样选中的物品符合规则。

DPP 多样性算法​

行列式点过程 (Determinantal Point Process, DPP) 是一种经典的机器学习方法,它的目标就是如何从一个集合中选出多样化的物品,与重排的目标契合。所以,DPP 是目前推荐系统重排多样性公认的最好方法。DPP 的数学比较复杂,需要先从其数学基础理论开始介绍。

数学基础

首先需要介绍下 超平行体 的概念。在二维和三维空间中,超平行体就是平行四边形和平行六面体。而在任意维上的定义为:

  1. 在 维空间中,一组向量 可以确定一个 维超平行体: ;
  2. 这里要求 ,例如 空间中有 维平行四边形。

对于超平行体如何求面积(二维)和体积(三维),实际上使用的是 施密特(Schmidt)正交化 的思想,将不正交的向量组转化为正交的向量组,方便计算面积与体积。这里需要思考的是,如果都是单位向量时,什么条件下超平行体能取最大和最小的体积呢?显然如下结论:

  1. 不妨设 都是单位向量;
  2. 当三个 向量正交 时,平行六面体为正方体,体积最大化 ;
  3. 当三个 向量线性相关 时,体积最小 化 。(三个向量都在一个平面上,显然体积为 。)

基于以上特点,我们可以如此利用体积来 衡量物品多样性:

  1. 给定 个物品,将它们表征为单位向量 ;()
  2. 用超平行体的体积衡量物品的多样性,体积介于 和 之间;
  3. 如果 两两正交(多样性好),则体积最大化, ;
  4. 如果 线性相关(多样性差),则体积最小化, ;

在实际应用中,则:

  1. 给定 个物品,将它们表征为单位向量 ;()
  2. 把它们作为矩阵 的列;
  3. 设 ,则行列式与体积满足: ;
  4. 因此,可以 用行列式 衡量向量 的多样性。

Tip:这里以二维超平行体为例,个人对行列式与体积的等式进行简单的验证推导:

  1. 不妨设列向量 ,其中 ,两向量夹角为 ,组合向量得到矩阵 和它的转置 ;
  2. 首先,如下图所示,对于二维向量组成的平行四边形,不妨以 为底,则面积由底 和由 转化与底正交的向量 的模相乘得到,所以等式左边: ;
  3. 根据行列式的定义,有 ,整理后得到: ;
  4. 根据向量夹角和余弦的的定义: ,所以得到 ,代入上步式子中有: ,显然该式与第 2 步中推理的等式左边相等,证毕。

多样性问题

前面对于超平行体的体积与多样性的关系进行了阐述,因此之前所介绍的多样性问题可以被如下描述:

  1. 设有 个物品,向量表征为: ,精排给这些物品打分为: ;
  2. 现在从 个物品中选出 个物品,组成集合 ,要求:
    (1)价值大:分数之和 越大越好;
    (2)多样性好: 中 个向量组成的超平行体 的体积越大越好。
  3. 将集合 中的 个物品向量组成矩阵 ,其中 。此时有 ,说明行列式等价于体积,故实际 使用行列式衡量多样性。

行列式点过程

DPP 求使得行列式的对数最大化的集合 : 。Hulu 的论文将 DPP 应用在推荐系统: ,其中 是权重参数。

Hulu 对该应用研究的主要贡献在于提出了 快速求解的方法。 一般来说,DPP 的求解思想 如下:

  1. 设 为 的矩阵,它的 元素为 ;给定向量 ,则需要 时间计算 ;
  2. 那么 是 的一个 子矩阵,如果 时,则 是 的一个元素;替换后的 DPP 应用在推荐系统的公式写作: 。
  3. DPP 是个组合优化问题,从集合 中选出一个大小为 的子集 。用 表示已选中的物品,用 表示未选中的物品,使用 贪心算法 求解: ,寻找下一个物品 且该物品价值尽量大、多样性尽量好。
  4. 其中 可以这样理解:寻找下一个物品 ,给集合 添加一个新物品,所以在原本 的基础上添加了一行一列。同时,我们希望添加的物品 使得行列式尽可能大,也就是说不能与集合 中的物品相似,否则行列式接近于零。

现分析使用 贪心算法暴力求解的时间复杂度:

  1. 求解: ;
  2. 对于单个 ,计算 的行列式(矩阵乘法)需要 时间;
  3. 那么对于所有的 ,计算行列式需要 时间;
  4. 然后需要求解上式 次才能选出 个物品,如果暴力计算行列式,则其总时间复杂度为: ;
  5. 再考虑需要计算矩阵 需要 时间,所以暴力算法的总时间复杂度为: 。

可见,简单粗暴求解行列式花费了大量的代价,但系统留给多样性算法的时间非常有限(10 毫秒左右)。因此 Hulu 的论文设计了一种 快速数值算法,使用 Cholesky 分解 花费 时间计算所有行列式,仅仅需要 的时间从 个物品中选出 个物品。该算法思想如下:

  1. Cholseky 分解 ,其中 是下三角矩阵,对角线以上的元素全为 ;
  2. Cholseky 分解得到可供计算 的行列式:
    (1)下三角矩阵 的行列式 等于 对角线元素乘积;
    (2)故 的行列式为 ;
  3. 每一轮循环,基于上一轮的 ,可以快速求出所有 的 Cholseky 分解,因此可以快速算出所有 的行列式。

DPP 的扩展

首先,在 MMR 中介绍的 滑动窗口 同样可以用于 DPP :

  1. 相似地,随着集合 的增大,其中相似物品越来越多,物品向量会趋于线性相关。
  2. 此时,行列式 会坍缩到零,取对数就会趋于负无穷。
  3. 所以设置一个滑动窗口 ,用 代替公式中的 。基于贪心算法求解公式,得到 使用滑动窗口的 DPP 算法公式: 。

同样,也可以对 DPP 添加 规则约束:

  1. 贪心算法每轮从 中选出一个物品: 。
  2. 用规则排除掉 中的部分物品,得到子集 ,然后求解: 。

本章小结​

本章主要介绍推荐系统链路中的最后一环“重排”。实际上重排是对推荐系统中 多样性 的考察,多样性更能体现用户的个性化。

一般来说,多样性是通过 物品相似度 来度量的,而物品相似度可以通过 物品属性标签 或者 物品向量表征 来度量。因为小红书的笔记天生包括文字和图片,所以小红书 常用 CV 和 NLP 模型提取图片和文字特征向量;因为文字和图片相关性高,所以模型预训练使用 CLIP 方法,无需人工标注 使用成对的文字图片组合训练。

推荐系统中希望提高曝光物品的多样性,也就是尽量使得物品之间两两不相似。所以在精排和粗排后都有 后处理,目的在于对排序结果进行调整,要求物品在 兴趣分数高 的同时 具有较好的多样性。所以,本章后续介绍了两种提升多样性的算法。

第一种 Maximal Marginal Relevance(MMR)多样性算法 来源于搜索排序,使用相关性进行排序。MMR 的基本思想就是从全集(未选中)中选择兴趣分数和多样性(物品相似度)加权分高的物品,放到选中集中,保证 所选物品在兴趣分数高的同时与选中集中的物品相似度低。

第二种 行列式点过程 (Determinantal Point Process, DPP) 是一种经典的机器学习方法,目标就是如何从一个集合中选出多样化的物品,与重排的目标契合。它的基本思想就是在 MMR 的基础上使用物品向量组成的超平行体 体积 替换物品相似度的度量,实际应用中,使用 物品向量组成的矩阵行列式 来度量更为方便简单。同时 DPP 的提出者给出了一种使用 Cholseky 分解 的 快速求解 方法,也是该论文的主要贡献所在。

以上的多样性算法都存在一个通病,当被选取集合越来越大时,待选物品与该集合的相似度越来越高趋近于 ,将导致算法失效。因此,设置一个 滑动窗口(比如最近选择的 10 个物品),用其代替公式中的被选中集合。除了解决这个问题外,滑动窗口的应用也存在 现实合理性:两个离得远的物品可以相似,并不会影响用户体验;但如果两个离得近物品就应当有较大差异,否则用户能感知到缺乏多样性。

在实际应用中,多样性算法还需要根据业务需求设置 规则约束。规则约束基本目标是对于笔记、广告、营销卡片等的重复出现做了限制。具体应用时,需要 先通过规则约束过滤 一遍未选中集合,再用该集合参与多样性算法 进行物品的筛选。

七. 物品冷启动​

物品冷启动指的是如何 对新发布的物品做分发,比如:

  1. 小红书上用户新发布的笔记;
  2. B 站上用户新上传的视频;
  3. 今日头条上作者新发布的文章。

它们的主要内容都是由用户上传的,故主要研究 UGC(User-Generated Content)的物品冷启动。UGC 比 PGC(主要内容都是由平台采购的)的冷启动更难,这是因为 UGC 的新物品数量巨大、内容质量良莠不齐,分发非常困难。

优化目标 & 评价指标​

在介绍完冷启动之后,首先要考虑一个问题:为什么要特殊对待新笔记(新物品)?做 新物品冷启动 主要原因在于:

  1. 新笔记缺少与用户的交互,导致推荐的难度大、效果差;
  2. 扶持新发布、低曝光的笔记,可以增强作者发布意愿。

优化冷启的目标

那么再考虑第二个问题:优化冷启动想要达成什么目标?实际上,工业界是有共识的:

  1. 精准推荐:克服冷启的困难,把新笔记推荐给合适的用户,不引起用户反感;
  2. 激励发布:流量向低曝光新笔记倾斜,激励作者发布;
  3. 挖掘高潜:通过初期小流量的试探,找到高质量的笔记,给予流量倾斜。

评价指标

一般来说,对于优化冷启动效果的评价指标主要包括 作者侧指标、用户侧指标 和 内容侧指标,远比普通笔记的推荐复杂(普通笔记只需要考察用户侧指标)。作者侧指标反映用户的发布意愿,对 低曝光的笔记 扶持越好则该指标越高;用户侧指标反映 推荐是否精准、用户是否反感,故分为新笔记指标和大盘指标;内容侧指标则反映冷启动是否能挖掘出 优质笔记。 基于以上类别,主要指标包括:

指标类型指标描述基本思想意义
作者侧指标发布渗透率、人均发布量1. 发布渗透率 = 当日发布人数* / 日活人数;
2. 人均发布量 = 当日发布笔记数 / 日活人数。
发布渗透率、人均发布量反映作者的发布积极性:
1. 冷启动的重要优化目标是促进发布,增大内容池;
2. 所以新笔记获得的曝光越多,首次曝光和交互出现得越早,作者发布积极性越高。
用户侧指标新笔记的消费指标考察新笔记的点击率、交互率等基础上,分别考察高曝光、低曝光新笔记。只考察新笔记的点击率等指标的话,曝光的基尼系数很大,少数头部新笔记占据了大部分的曝光。所以需要区别对待高、低曝光笔记。
用户侧指标大盘消费指标大盘的消费时长、日活、月活。低曝光笔记缺少用户交互、推荐不准。一味大力扶持低曝光新笔记会导致损害用户体验,降低大盘消费指标。所以希望在做新的消费实验时候,大盘指标基本持平,确保新策略不会伤害用户体验。
内容侧指标高热笔记占比小红书的场景下,高热笔记为前 30 天获得 1000+ 次点击的笔记。高热笔记占比越高,说明冷启动阶段挖掘优质笔记的能力越强。

* :发布一篇或以上,就算一个发布人数。

冷启动的优化点

后续章节将详细介绍冷启动的优化方式,主要包括以下方向:

  1. 优化全链路:包括优化召回和排序。
  2. 流量调控:流量怎么在新物品、老物品中分配。

简单的召回通道​

召回的依据

在小红书中,新笔记自带图片、文字、地点,并被打上了算法或人工标注的标签。但是缺乏用户点击、点赞等信息,没有笔记 ID embedding,导致了 冷启动召回的困难:

  1. 缺少用户交互,还没学好笔记 ID embedding,导致 双塔模型效果不好;(召回和排序中同样存在问题)
  2. 缺少用户交互,导致 ItemCF 不适用物品冷启动:新笔记交互少,与其他笔记的用户重合度未知,无法计算相似度。

因此诸多 召回通道 的适用性如下:

召回通道物品冷启动适用性
ItemCF 召回不适用
双塔模型改造后适用
类目、关键词召回适用
聚类召回适用
Look-Alike 召回适用

本节就主要介绍改造后的双塔模型和类目、关键词召回通道。

改进的双塔模型

因为没有新笔记 ID embedding,导致双塔模型效果不好。因此对于 ID embedding,有如下改进方法:

  1. 改进方案一:新笔记使用 default embedding。
    (1)物品塔做 ID embedding 时,让所有新笔记 共享一个 ID,而不是用自己真正的 ID。共享的 ID 对应的 embedding 向量即是 default embedding,该向量是通过训练学习得到的。
    (2)到下次模型训练的时候,新笔记才有自己的 ID embedding 向量。
  2. 改进方案二:利用相似笔记的 embedding 向量。
    (1)新笔记发布后,查找 内容最相似的高曝笔记;(高曝笔记向量学的好)
    (2)把 个高曝笔记的 embedding 向量取平均,作为新笔记的 embedding。

通常在实践中,还需要设置 多个向量召回池,让新笔记有更多曝光机会:

1 小时新笔记;2. 6 小时新笔记;3. 24 小时新笔记;4. 30 天笔记。

以上的召回池共享同一个双塔模型,所以多个召回池不增加训练的代价。

类目、关键词召回

用户画像中记录了用户信息,包括感兴趣的类目、关键词等,可被用于召回。基于类目的召回 基本思想如下:

  1. 系统维护类目索引(如下图):类目 → 笔记列表(按时间倒排);
  2. 用类目索引做召回:用户画像 → 类目 → 笔记列表;
  3. 取回笔记列表上前 篇笔记(即最新的 篇)。

基于关键词的召回 与类目召回本质完全相同,仅将以上介绍的思想中“类目”替换成”关键词“。

但是这种召回通道存在明显的 缺点:

  1. 只对刚刚发布的新笔记有效:
    (1)只取回某类目/关键词下最新的 篇笔记;
    (2)发布几小时之后,就再没有机会被召回。
  2. 弱个性化,不够精准。

聚类召回​

聚类召回

聚类召回 基于笔记的图文内容 做推荐,基本思想 如下:

如果用户喜欢一篇笔记,那么他会喜欢内容相似的笔记。

  1. 事先训练一个 神经网络,基于笔记的类目和图文内容,把笔记 映射到向量;
  2. 对笔记向量做 聚类,划分为 1000 cluster,记录每个 cluster 的中心方向。(k-means 聚类,用余弦相似度)

在新笔记发布后,需要建立对应的 聚类索引:

  1. 一篇新笔记发布之后,用神经网络把它映射到一个特征向量;
  2. 从 1000 个 cluster 向量中找到最相似的向量,作为新笔记的 cluster;
  3. 建立 聚类索引:cluster → 笔记 ID 列表(按时间倒排)。

之后就可以做 线上召回:

  1. 给定用户 ID,找到他的 交互的笔记列表,把这些笔记作为种子笔记;
  2. 把每篇种子笔记映射到向量,寻找最相似的 cluster;(知道了用户对哪些 cluster 感兴趣)
  3. 从每个 cluster 的笔记列表中,取回最新的 篇笔记;
  4. 最多取回 篇新笔记

而且,聚类召回与类目、关键词召回相似,只对刚刚发布的新笔记有效。

内容相似度模型

前文描述中,聚类召回需要调用一个神经网络,将笔记图文内容映射为向量。如果两篇笔记内容相似,则这两篇笔记应该有较高的余弦相似度。所以,如下搭建神经网络:

该模型将笔记的图文内容分别通过 CNN 和 BERT 生成向量,拼接后输入全连接层输出笔记内容表征向量,再计算两篇笔记内容向量的余弦相似度。其中 CNN 和 BERT 是预训练好的模型,但全连接层的参数需要通过训练学习。

该 模型的训练方法 与双塔模型类似,基本思想:

  1. 设正样本笔记、种子笔记、负样本笔记通过神经网络得到的向量为 ;
  2. 鼓励 大于 ;
  3. 实际就是在双塔模型中所描述的 Pairwise 方法,使用 Triplet hinge loss 或者 Triplet logistic loss。

其中 < 种子笔记,正样本> 二元组中 正样本的选取 有如下方法:

  1. 人工标注二元组的相似度,选取高相似度的作为正样本;
  2. 算法自动选正样本:
    (1)只用高曝光笔记作为二元组,因为有充足的用户交互信息;
    (2)且要求两篇笔记由相同的二级类目,比如都是“菜谱教程”;
    (3)再用 ItemCF 的物品相似度选正样本。

而其中 < 种子笔记,负样本> 二元组中 负样本的选取 有如下:

从全体笔记中随机选出满足条件的:

  1. 字数较多(神经网络提取的文本信息有效);
  2. 笔记质量高,避免图文无关。

Look-Alike 召回​

Look-Alike (人群扩散算法)是广告中常用的方法,也可使用在推荐系统中召回低曝光笔记。

互联网广告中的 Look-Alike

以 Tesla 为例,它们知道 Telsa Model 3 的典型用户满足这样几个特点:年龄 25-35;本科学历以上;关注科技数码;喜欢苹果电子产品。需要重点在这些人群中投放广告,所以满足这些条件的用户作为 种子用户,但是种子用户的数量很少,而潜在的用户受众很多却缺少部分信息无法寻找。因此,通过种子用户进行 人群扩散 找到与种子用户相似的 Look-Alike 用户。

Look-Alike 是一个框架,具体做人群扩散的方法很多,主要任务在于如何 计算两个用户的相似度:

  1. UserCF:两个用户有共同的兴趣点;
  2. Embedding:两个用户向量的余弦相似度较大。

Look-Alike 人群扩散召回

在小红书的应用场景下,Look-Alike 的 基本思想 如下:

  1. 点击、点赞、收藏、转发等交互说明用户对笔记可能感兴趣;
  2. 把有交互的用户作为新笔记的种子用户;
  3. 用 Look-Alike 在相似用户中扩散。

当用户 发布新笔记 后:

  1. 取回有交互用户的特征向量(比如双塔模型),将有交互的用户的向量的平均作为新笔记的特征向量;
  2. 每当有用户交互该物品,更新笔记的特征向量。(小红书做到近线更新特征向量)

在 线上召回 时:

  1. 用向量数据库存储新笔记的特征向量;
  2. 用户刷小红书,就给他做一次推荐;
  3. 使用双塔模型计算用户的特征向量,以该向量作为 query ,在向量数据库中做最近邻查找,取回几十篇笔记。

Tip:结合前面小节的描述,物品从发布到热门,主要的透出渠道会经历三个阶段:

  1. 类目召回、聚类召回。它们是基于内容的召回通道,适用于刚刚发布的物品。
  2. Look-Alike 召回。它适用于有点击,但是点击次数不高的物品。
  3. 双塔、ItemCF、Swing 等等。它们是基于用户行为的召回通道,适用于点击次数较高的物品。

我的理解:

  • UserCF 基于交互
  • Look-Alike 基于特征向量

流量调控​

流量调控是冷启动的第二种优化点,也是物品冷启动最重要的一环。它直接控制流量怎么在新笔记、老笔记中分配,直接影响作者发布指标。工业界一般将流量向新笔记倾斜,扶持新笔记 的目的在于:

  1. 促进发布,增大内容池:
    (1)新笔记获得的曝光越多,作者创作积极性越高;
    (2)反映在发布渗透率、人均发布量上。
  2. 挖掘优质笔记:
    (1)做探索,让每篇新笔记都能获得足够曝光;
    (2)挖掘的能力反映在高热笔记占比上。

这里举一个 工业界的做法 例子:

  1. 假设推荐系统只分发年龄小于 30 天的笔记;
  2. 假设采用自然分发,年龄小于 24 小时的新笔记曝光占比为 1/30;
  3. 扶持新笔记,让新笔记的曝光占比远大于 1/30。

而为了扶持新笔记,业界的流量调控技术 发展经历了如下阶段:

  1. 在推荐结果中强插新笔记;
  2. 对新笔记的排序分数做提权(boost);
  3. 通过提权,对新笔记做保量;
  4. 差异化保量。

新笔记提权(boost)

在推荐系统的链路中,粗排对物品排序进行了截断,而重排进行了抽样。这两个步骤都过滤了大量的笔记,想让新笔记占到更多的曝光,就得在 粗排 和 重排 中做新笔记提权。提权的 优点 在于 容易实现、投入产出比好,缺点 也很明显:

  1. 曝光量对 提权系数 很敏感;
  2. 很难精确控制 曝光量,容易过度曝光和不充分曝光。

新笔记保量

保量 指的是不论笔记质量高低,都保证 24 小时获得 100 次曝光。如下图所示,在原有提权系数的基础上,乘以额外的提权的系数。当发布时间越接近 24 小时,而曝光次数与 100 次差的越多,那么乘的额外系数就越大,给笔记更多的曝光机会。

更先进的 动态提权保量,基本思想是以下四个值计算提权系数:

  1. 目标时间:比如 24 小时;
  2. 目标曝光:比如 100 次;
  3. 发布时间:比如笔记已经发布 12 小时;
  4. 已有曝光:比如笔记已经获得 20 次曝光。

上面的例子中,得到 提权系数 满足: 提权系数 ,前一个数越大、后一个数越小,则提权系数越大。

实际应用中,保量的 难点 在于:

  1. 保量成功率远低于 100% :
    (1)很多笔记在 24 小时内达不到 100 次曝光;
    (2)召回、排序存在不足;
    (3)提权系数调得不好。
  2. 线上环境变化会导致保量失败:
    (1)线上环境变换:新增召回通道、升级排序模型、改变重排打散规则等;
    (2)线上环境变换后,需要调整提权系数,十分麻烦。

那么为了提升保量的成功率,大幅增加额外系数是否可行?实际上,给新笔记分数 boost 越多,对新笔记的影响是双面的:

  1. 好处:短期来说,分数提升越多,曝光次数越多;
  2. 坏处:但会将笔记推荐给不太合适的受众:
    (1)点击率、点赞率等指标会偏低;
    (2)长期会受推荐系统打压,难以成长为热门笔记。

所以,保量的系数调整十分关键。

差异化保量

差 异化保量 的基本思想在于 不同的笔记有不同的保量目标,比如普通笔记保 100 次曝光、内容优质的笔记保 100-500 次曝光,具体的保量目标由算法判定。大致实现如下:

  1. 基础保量:24 小时 100 次曝光;
  2. 内容质量:用模型(多模态神经网络)评价内容质量高低,给予额外保量目标,上限是加 200 次曝光;
  3. 作者质量:根据作者历史上的笔记质量,给予额外保量目标,上限是加 200 次曝光;
  4. 一篇笔记最少有 100 次保量,最多有 500 次保量。

达到保量目标后,便会停止扶持,自然分发,与老笔记公平竞争。

冷启动的 AB 测试​

冷启动的 AB 测试远比正常推荐系统的麻烦:推荐系统常用的 AB 测试只考察用户侧消费指标,而推荐系统的 AB 测试还需要额外考察作者侧发布指标。后者远比前者复杂,而且所有已知的实验方案都存在缺陷。

用户侧实验

如下图所示,冷启动的用户侧实验与标准的推荐系统一致,基本思想就是将全部用户划分为对照组和实验组,使用新旧不同策略在全部笔记上做测试,得到新笔记点击率、用户消费时长等指标的 diff。

但这种 AB 测试存在小瑕疵,主要 问题 在于:

  1. 限定:保量 100 次曝光;
  2. 假设:新笔记曝光越多,用户使用 APP 时长越低;(通常来说,新笔记推荐不够准,用户体验不好)
  3. 新策略:把新笔记排序时的权重增大两倍;
  4. 结果(只看用户消费指标):
    (1)AB 测试的 diff 是负数(实验组不如对照组);
    (2)如果 推全,diff 会缩小(比如 -2% → -1%)。

这里分析下推全后 diff 会缩小的大致原因:当做测试时,实验组看到更多新笔记导致消费指标变差,对照组看到更少新笔记导致消费指标变好,因此测试时 diff 较大;推全时实际并不会此消彼长,diff 不会下降过多。

作者侧实验

作者侧的 AB 测试实验并不好做,主要有三种方案、第一种方案:不对用户和老笔记做分组,区分新笔记和老笔记,并将新笔记根据不同策略划分为对照组和实验组。老笔记自然分发不受新旧策略影响,从全量的老笔记中选择用户最喜欢的推荐给用户。而新笔记的不同组都有机会触达所有用户,对比得到新笔记新旧策略的指标 diff 。

第一种方案的 第一个缺点 在于 新笔记之间会抢流量:

  1. 设定:新老笔记走各自队列,没有竞争;重排分给新笔记 1/3 流量,分给老笔记 2/3 流量。
  2. 新策略:把新笔记的权重增大两倍。
  3. 结果(只看作者发布指标):
    (1)AB 测试的 diff 是正数(实验组优于对照组);
    (2)如果推全,diff 会消失(比如 2% → 0)。

这里推全后 diff 消失的原因就在于抢流量:分给新笔记的流量是固定的,实验组提高了新笔记的权重,实验组新笔记的曝光得到增加,而对照组的新笔记曝光就会减少,这样两组的发布指标会产生明显的 diff;当推全新策略,就不会出现抢流量的情况,也就不会产生 diff 。

第二个缺点 在于 新笔记和老笔记抢流量:

  1. 设定:新老笔记自由竞争;
  2. 新策略:把新笔记排序时的权重增大两倍;
  3. AB 测试时,50% 新笔记(带策略)跟 100% 老笔记抢流量;
  4. 推全后,100% 新笔记(带策略)跟 100% 老笔记抢流量;
  5. 推全前后设定发生了变化,故 AB 测试结果与推全结果有差异。

如下图所示是 作者侧实验的方案二, 与方案一的区别在于:将用户侧也分为对照组和实验组,对照组只能看到对照组的新笔记,实验组只能看到实验组的新笔记。

因此,方案二的改动比方案一的 优缺点 在于:

  1. 优点:新笔记的两个桶不抢流量,实验结果更可信;
  2. 相同问题:新笔记和老笔记抢流量,AB 测试结果与推全结果有差异;
  3. 缺点:新笔记内容池减小一半,对用户体验造成负面影响。

而如下图所示,作者侧实验的方案三 更为极端。它在方案二的基础上,将老笔记也分为对照组和实验组,同样对照组只能看见对照组的新老笔记和用户。这就相当于把小红书分为两个 app 独立测试了,相比于其他方案的测试结果十分准确,指标的变化都是真实有效的。

但实际上并不可行,把小红书切为两个 app,内容池缩小一半,严重影响用户体验,消费指标一定大跌。为了 AB 测试损害公司业务,这个代价过于庞大。

综上所述,实际上各种 AB 测试的方案都有缺点(哪怕是小红书的方案)。所以一般在设计方案的时候,要 关注问题如下:

  1. 实验组、对照组新笔记会不会抢流量?
  2. 新笔记、老笔记怎么抢流量?
  3. 同时隔离笔记、用户,会不会让内容池变小?
  4. 如果对新笔记做保量,会发生什么?

本章小结​

在红书中,主要研究 UGC(User-Generated Content)的物品冷启动,也就是用户新发布笔记的分发曝光。优化冷启动的目的就在于 精准推荐、激励发布、挖掘高潜,针对这些目的一般来说要同时考虑 作者侧指标、用户侧指标 和 内容侧指标,能够反映用户的发布意愿、推荐的精准率和是否能挖掘出优质笔记。基于此,冷启动的主要优化包括两种,优化全链路 和 流量调控。

本章主要介绍了在推荐系统的链路中,针对 冷启动的召回优化。第一种是类目召回、聚类召回,它们是基于内容的召回通道,适用于刚刚发布的物品。 类目召回 是根据用户画像中感兴趣类目,通过索引找到 该类目下的最新笔记进行推荐。显然类目召回只对刚刚发布的新笔记有效,且个性化弱。而 聚类召回 利用神经网络,将新笔记图文内容映射为向量,再对这些向量做 聚类。线上召回的时候将用户交互过的笔记作为种子笔记,寻找 与种子笔记最相似的类,将 该类索引的最新笔记 进行推荐。同样聚类召回也只对刚刚发布的新笔记有效。

第二种是 Look-Alike 召回。它适用于有点击,但是点击次数不高的物品,实际上思想与 UserCF 相似。它的基本思想就是通过 寻找与种子人群相似的 Look-Alike 人群,将新笔记扩散推荐给 Look-Alike 人群。值得注意的是在实践中,将有交互的用户的向量的平均作为新笔记的特征向量,每当有用户交互该物品,更新笔记的特征向量。

第三种是双塔、ItemCF、Swing 等等。它们是基于用户行为的召回通道,适用于点击次数较高的物品。不过因为新笔记缺少用户交互和物品 ID embedding,因此标准推荐系统中的双塔、ItemCF 无法使用。但是针对冷启动 改进的双塔模型 行之有效,主要思想就是直到下次训练前,使用 default embedding 或 相似笔记的 embedding 来作为新笔记的向量。

然后介绍的是 冷启动的流量调控。推荐系统需要扶持新笔记,可以增大内容池、提高用户发布意愿,所以流量调控就是解决流量怎么在新老笔记之间分配的问题。基本的方法就是 使用单独的召回通道、在排序阶段提权。提权易于实现、性价比高,但提权系数和曝光量不好确定。因此需要做 保量,可以帮助新笔记在前 24 小时获得 100 次曝光。但简单保量的失败率很高,为了成功率直接增大系数也实际不可取,所以要对不同的笔记做 差异化保量。 也就是根据内容质量、作者质量,决定给予不同的保量目标。

最后介绍了 冷启动的 AB 测试。因为要同时考虑作者侧和用户侧的指标,冷启动的测试远比标注推荐系统的复杂。在 用户侧实验时,与推荐系统一致,对用户划分对照组和实验组分别测试获得新旧策略指标的 diff。但是存在一些瑕疵,导致 结果在推全时会缩小。在 作者侧实验 时,主要有三种方案。第一种不划分老笔记和用户,将新笔记划分对照组和实验组分别测试获得新旧策略指标的 diff。但问题是 新笔记之间会抢流量,推全时 diff 会消失;新笔记和老笔记抢流量,测试与推全 diff 差异大。第二种不划分老笔记,对应划分用户和新笔记为对照组和实验组分别测试获得新旧策略指标的 diff。虽然解决了方案一的新笔记之间的抢流量问题,但是是 新老笔记抢流量问题仍然存在,且 新笔记内容池减小一半,对用户体验造成负面影响。第三种方案则将老笔记也划分, 类似于将小红书划分为两个 app 分别测试新旧策略获得 diff。虽然该方案的 推全结果准确,但是这种切分方法将内容池缩小一半,严重影响用户体验,危害公司业务。综上所述,实际上冷启动各种 AB 测试的方案都有缺点(哪怕是小红书的方案)。

到这章为止,所有的推荐系统流程中的基本知识已经全部学习完毕,下一章是对实践中涨指标的一些 trick 的介绍。

八. 涨指标的方法​

1 概述​

1.1 推荐系统的评价指标​

  • 日活用户数(DAU)和留存 是最核心的指标

  • 目前工业界最常用 LT7 和 LT30 衡量留存。

    • 某用户今天(​)登录 APP,未来 7 天(​)中 天登录 APP,那么该用户今天的 LT7 等于 4
    • LT 增长通常意味着用户体验提升。(除非 LT 增长,DAU 下降)
  • 其他核心指标:用户使用时长、总阅读数/总点击数、总曝光数。

  • 非核心指标:点击率、交互率等等。

  • 对于 UGC 平台,发布量和发布渗透率也是核心指标。

1.2 涨指标的方法​

  • 改进召回模型,添加新的召回模型
  • 改进粗排和精排模型
  • 提升召回、粗排、精排中的多样性
  • 特殊对待 i 虚拟用户、低活用户等特殊人群
  • 利用关注、转发、评论这三种交互行为

2 召回​

  • 双塔模型和 Item-to-Item(I2I)是最重要的两类召回模型,占据大部分召回配额
  • 很多小众的模型,占据的配额很少。在召回总量不变的前提下,添加某些召回模型可以提升核心指标
  • 通过添加优质内容池,可以提升核心指标
  • 同一个模型可以用于多个内容池,得到多条召回通道

2.1 双塔模型​

2.1.1 优化正样本、负样本

  • 简单正样本:有点击的(用户,物品)二元组
  • 简单负样本:随机组合的(用户,物品)二元组
  • 困难负样本:排序靠后的(用户,物品)二元组

2.2.2 改进神经网络结构

  • Baseline:用户塔和物品塔分别是全连接网络
  • 改进:用深度交叉网络 DCN 代替全连接网络
  • 改进:在用户塔中使用用户行为序列(last-n)
  • 改进:使用多向量模型代替单向量模型(如标准的双塔模型,二分类任务)-> 用户塔输出多个向量,通过不同向量和物品塔输出的一个向量(一个是为了节省数据库的存储成本)的内积进行预估指标(类似排序中的多目标模型)

2.2.3 改进模型的训练方法

  • Baseline:二分类,区分正、负样本
  • 改进:结合二分类、batch 内负采样(需要对热门物品做纠偏)
  • 改进:利用自监督学习方法,让冷门物品的 embedding 学得更好

2.2 Item-to-Item​

  • I2I 基于相似物品做召回

  • 最常见的用法师 U2I2I

  • 如何计算物品相似度?

    • 方法一:ItemCF 及其变体(线上同时使用多种 I2I 模型,各分配一定配额)
    • 方法二:基于物品向量表征,计算向量相似度(双塔模型、图神经网络等等)

2.3 小众模型​

2.3.1 类似 I2I 的模型

  • U2U2I(推荐相似用户喜欢的物品)
  • U2A2I(推荐用户喜欢作者的物品)
  • U2A2A2I(推荐与用户喜欢作者类似的作者的物品)

2.3.2 更复杂的模型

  • Path-based Deep Network(PDN)
  • Deep Retrieval
  • Sparse-Interest Network(SINE)
  • Multi-task Multi-view Graph Representation Learning(M2GRL)

3 排序模型​

3.1 精排模型的改进​

3.1.1 基座

  • 基座的输入包括离散特征和连续特征,输出一个向量,作为多目标预估的输入。
  • 改进 1:基座加宽加深,计算量更大,预测更准确。
  • 改进 2:做自动的特征交叉,比如 bilinear 和 LHUC
  • 改进 3:特征工程,比如添加统计特征、多模态内容特征等

3.1.2 多目标预估

  • 改进 1:增加新的预估目标,并把预估结果加入融合公式。
  • 改进 2:MMoE、PLE 等结构可能有效,但往往无效。
  • 改进 3:纠正 position bias 可能有效,也可能无效。

3.2 粗排模型的改进​

粗排模型的打分量比精排大 10 倍,因此粗排必须够快。

3.2.1 粗排模型

  • 简单模型:多向量双塔模型
  • 复杂模型:三塔模型效果好,但工程实现难度较大

3.2.2 粗精排一致性建模

  • 蒸馏精排训练粗排
    • pointwise 蒸馏
      • 设 y 是用户真实行为,p 是精排的预估
      • 用 ​作为粗排拟合的目标
    • pairwise 或 listwise 蒸馏
      • 给定 k 个候选物品,按照精排预估做排序。
      • 做 learning to ranke(LTR),让粗排拟合物品的序(而非值)
  • 优点:粗精排一致性建模可以提升核心指标。
  • 缺点:如果精排出 bug,精排预估值 p 有偏,会污染粗排训练数据。

3.3 用户行为序列建模​

  • 改进 1:增加序列长度,让预测更准确,但是会增加计算成本和推理时间。
  • 改进 2:筛选的方法,比如用类目、物品向量表征聚类。
  • 改进 3:对用户行为序列中的物品,使用 ID 以外的一些特征。

目前大都沿着 SIM 的方向发展,让原始序列尽量长,然后做筛选降低序列长度,最后将筛选结果输入 DIN。

3.4 在线学习​

全量更新 vs 增量更新

  • 在线学习的资源消耗:
    • 既需要在凌晨做全量更新,也需要全天不间断做增量更新。
    • 假设线上有 m 个模型,其中 1 个是 holdout,一个是推全的模型, 个测试的新模型。每套在线学习的机器成本都很大,因此 m 数量很小,制约模型开发迭代的效率。

3.5 老汤模型​

  • 老汤模型:老模型训练得非常好,很难被超越。

3.5.1 如何快速判断新模型结构是否由于老模型?(只去看结构,老模型训练更久,新模型想要追平比较困难)

  • 对于新、老模型结构,都随机初始化模型全连接层。
  • Embedding 可以是随机初始化,也可以复用老模型训练好的参数。
  • 用 n 天的数据训练新老模型(从旧到新,训练 1 epoch)
  • 如果新模型显著优于老模型,新模型很可能更优。

3.5.2 如何更快追平线上的老模型?

  • 方法 1:尽可能多地复用老模型训练好的 Embedding 层(embedding 学的比全连接慢)。
  • 方法 2:用老模型做 teacher,蒸馏新模型。

4 多样性​

4.1 排序的多样性​

4.1.1 精排多样性

  • 精排阶段,结合兴趣分数和多样性分数对物品 i 排序
  • 常用 MMR、DPP 等方法计算多样性分数,精排使用滑动窗口(精排决定最终的曝光,曝光页面上邻近的物品相似度应该小),粗排不适用滑动窗口(考虑整体的多样性)
  • 除了多样性分数,精排还是用 打散策略 增加多样性

4.1.2 粗排多样性

  • 根据兴趣分数进行排序,将分数最高的部分物品送入粗排。
  • 在剩余的物品中,对每个物品 i 计算兴趣分数 和多样性分数 ,选择综合分数最高的部分物品进入精排。

4.2 召回的多样性​

4.2.1 双塔模型:添加噪声

  • 线上做召回时(在计算出用户向量之后,在做 ANN 检索之前),往用户向量中添加随机噪声。
  • 用户的兴趣越窄,添加的噪声需要越强。
  • 添加噪声在推荐准确度和多样性之间进行平衡。

4.2.2 双塔模型:抽样用户行为序列

  • 保留用户行为序列中最近的 r 个物品(),从剩余 个物品中随机抽样 t 个物品()。
  • 将得到的 个物品作为用户行为序列,而不是用全部 n 个物品。

Q:为什么抽样用户行为序列可以涨指标?

A:(1)提升多样性;(2)可以捕捉用户较长时间之前的兴趣。

4.2.3 U2I2I:抽样用户行为序列

  • 种子物品覆盖的类目数可能非常少,且类目不平衡。
  • 做非均匀随机抽样,从 n 个物品中选出 t 个,让类目平衡。用抽样得到的 t 个物品代替 U2I2I 的种子物品。(多样性提升+覆盖的类目更多)

4.3 探索流量​

  • 每个用户曝光的物品中又 2%是非个性化的,用作兴趣探索。
  • 维护一个精选内容池,其中物品均为交互率指标高的优质物品。(用高质量弥补兴趣)
  • 提权/强插
  • 兴趣探索在短期内负面影响核心指标,但是长期会带来正面影响。

5 特殊对待特殊用户人群​

  • 为什么要特殊对待特殊人群?
    • 新用户、低活用户的行为很少,个性化推荐不推荐。
    • 新用户、低活用户容易流失,要想办法留存。
    • 特殊用户的行为不同于主流用户,基于全体用户行为训练出的模型在特殊用户人群上有偏。

5.1 构造特殊内容池​

  • 特殊人群的行为很少,个性化召回不准确(用高质量弥补准确度)。
  • 针对特定人群的特点构造特殊内容池,提升用户满意度。

5.1.1 如何构造特殊内容池

  • 方法一:根据物品获得的交互次数、交互率选择优质物品。

    • 圈定人群,构造内容池。
    • 内容池有弱个性化的效果。内容池需要定期更新。该内容池只对该人群生效。
  • 方法二:做因果推断,判断物品对人群留存率的贡献,根据贡献值选物品。

5.1.2 特殊内容池的召回

  • 双塔模型是个性化的,对于新用户,可能不准,但是可以靠 高质量、弱个性化 做弥补。

  • 额外的训练代价?No

    • 正常用户,只训练一个双塔模型。
    • 对于新用户,由于历史交互记录少,需要单独训练一个双塔模型。
  • 额外的推理代价?Yes

    • 内容池定期更新,然后做更新 ANN 检索。
    • 线上做召回时,需要做 ANN 检索。
    • 特殊内容池很小,所以增加的额外算力不会很大。

5.2 使用特殊排序策略​

5.2.1 排除低质量物品

  • 对于特殊人群,业务上只关注留存,不在乎消费(少出广告、甚至不出广告)。
  • 新发布的物品不在新用户、低活用户上做探索,避免伤害用户体验。

5.2.2 差异化的融分公式

  • 新用户、低活用户的点击、交互行为不同于正常用户。
  • 低活用户的人均点击量很小。
    • 融分公式中提高预估点击率的权重。
    • 保留几个曝光坑位给预估点击率最高的几个物品。

5.3 特殊的排序模型​

5.3.1 差异化的排序模型

  • 问题:排序模型被主流用户主导,对特殊用户做不准预估。

  • 方法:

    • 大模型+小模型
      • 用全体用户行为训练大模型,其预估 p 拟合用户行为 y
      • 用特殊用户的行为训练小模型,小模型的预估 q 拟合大模型的残差 。
      • 主流用户只用大模型预估 p,特殊用户融合两个模型预估 。
    • 融合多个 experts,类似 MMoE。(小神经网络的输入只有用户特征)
    • 大模型预估之后,用小模型做校准。
      • 大模型做主流用户的预估,小模型输入大模型的输出,做 refine。
  • 错误的做法:每个用户人群设计一个大模型(短期有益,长期有害,维护成本高)


6 利用交互行为​

  • 如何利用交互行为?
    • 最简单的方法:将模型预估的交互率用于排序。

6.1 关注​

6.1.1 关注作者数量对用户留存的价值

  • 用户留存率 r 与他关注的作者数量 f 正相关。

  • 如何利用关注关系提升用户留存?

    • 用排序策略提升关注量。

      • 对于用户 u,模型预估候选物品 i 的关注率 ​。
      • 设用户 u 已经关注了 f 个作者。
      • 定义单调递减函数 ,在排序融分公式中添加 ​,用于促关注。
    • 构造促关注内容池和召回通道:

      • 如果用户关注的作者数较小,则对该用户使用该内容池。

6.1.2 粉丝数对促发布的价值

  • 交互 可以提升作者发布积极性。
  • 用排序策略帮助低粉新作者涨粉

6.1.3 隐式关注关系

  • 召回通道 U2A2I

  • 隐式关注关系:用户 u 喜欢看作者 a 发布的物品,但是 u 并没有关注 a。

6.2 转发(分享)​

6.2.1 促转发(分享回流)

Q:简单提升转发次数是否有效?

A:否。增大融分公式中预估转发率的权重,可以促转发,但是会负面影响点击率和其他交互率。

6.2.2 KOL 建模

  • 目标:在不损害点击和其他交互的前提下,尽量多吸引站外流量。

  • 其他平台的 Key Opinion Leader(KOL) 可以吸引大量站外流量。

  • 如何判断 本平台的用户是不是其他平台的 KOL?

    • 该用户历史上的转发能带来多少站外流量。

6.2.3 促转发的策略

  • 识别出站外 KOL 之后,如何用于排序和召回?
    • 方法一:排序融分公式中添加额外的一项
    • 方法二:构造促转发内容吃和召回通道,对站外 KOL 生效。

6.3 评论​

6.3.1 评论促发布

  • 如果新发布的物品尚未获得很多评论,则对预估评论率提权,让物品尽快获得评论。

6.3.2 评论的其他价值

  • 有些用户喜欢留评论,喜欢跟作者、评论区互动(添加促评论的内容池,有利于提升用户留存)。
  • 有些用户常留高质量评论(点赞量高),高质量评论对作者、其他用户的留存有贡献。