本学习日志主要面向细节知识的补全和梳理,对于常见的实现方式和概念会精简描述,推荐再读原文,真的深入浅出讲的很好
快速候选召回
召回工程实现
召回算法
召回在推荐系统中有着举足轻重的地位,尤其在工业界中动辄上亿的数据量,如何快速的召回有效数据一直是一个难题。因此召回算法普遍较为简短,不过也具有很强的可操作性。
ItemCF:基于物品相似度的协同过滤
原理
- 协同过滤的原理是物以类聚,人喜欢相似的东西,相似的人喜欢相似的东西,因而相似度的计算是十分关键的。
- ItemCF基于此套假设使用余弦相似度来根据同时喜欢两件物品的人的数量或行为估计两件物品的相似度。
\(w_{ij} = \frac{C[i][j]}{\sqrt{N(i)\cdot N(j)}}\)
实现
- 由于用户的交互记录有可能很长,因此实际使用时一般取Top-k作为候选集合。
- 当有显式评分数据时,皮尔逊相关系数能更好的捕获物品间的相似性,同时需要关系的是中心化处理。
\(w_{ij} =
\frac{
\sum_{u \in U_{ij}} (r_{ui} - \bar{r}_i)(r_{uj} - \bar{r}_j)
}{
\sqrt{\sum_{u \in U_{ij}} (r_{ui} - \bar{r}_i)^2}
\sqrt{\sum_{u \in U_{ij}} (r_{uj} - \bar{r}_j)^2}
}\)
Swing:面向工业场景的相似度优化
原理
- 实际工业应用中会存在诸如随机点击和冷热物品的情景,因此Swing通过分析 用户-物品交互 来过滤噪声提升计算鲁棒性。
- 其核心洞察是:如果多个用户在其他共同购买行为较少的情况下,同时购买了同一对物品,那么这对物品之间的关联性就更可信。
- 用户权重调整:为了降低活跃用户对计算结果的过度影响,我们引入用户权重 $w_u = \frac{1}{\sqrt{\lvert I_u \rvert}}$
- Surprise算法重点考虑两个因素:购买顺序的重要性以及时间间隔的影响 \(s(i,j) = \sum_{u \in U_i \cap U_j} \sum_{v \in U_i \cap U_j} w_u \cdot w_v \cdot \frac{1}{\alpha + \lvert I_u \cap I_v \rvert}\)
UserCF:基于用户相似度的协同过滤
原理
- 相比于ItemCF通过用户行为估计物品,UserCF更强调借鉴相似的人的行为,跳过物品这一块。
实现
- 对于两种协同过滤实现,小数据与用户量时使用二维表来表示并计算是可行的,但是当数据量有一定体量时,更推荐使用用户与物品的特征向量来进行计算。
I2I(Item-to-Item)召回
- Item2Vec:最直接的迁移
- 采用 Word2Vec 的 Skip-Gram 简化架构
- 将每个用户的交互历史视为一个集合而非序列,忽略了交互的时间顺序。
- EGES:用属性信息增强序列(Enhanced Graph Embedding with Side Information)
- 将物品序列的概念从简单的用户交互扩展为更精细的会话级序列
- 引入商品的辅助信息(如类别、品牌、价格区间等)来增强商品的向量表示。
- Airbnb:将业务目标融入序列
- 面向业务的序列构建
- 会话切分机制:基于用户的点击会话(Click Sessions)构建序列,当用户连续点击间隔超过30分钟时,系统会自动开始一个新的会话。
- 行为权重差异化:最终的预订行为相比于简单的点击浏览,包含了更强烈的用户偏好信号,因此在模型训练中应当给予更高的权重。
- 全局上下文机制
- 市场感知的负采样
- 改进了负采样策略:增加了“同市场负采样”策略,一部分负样本从与正样本相同的地理市场中选择
双塔模型(U2I召回)
双塔模型给出的方案是把匹配问题拆成两个独立的编码问题。用户塔处理用户的历史行为、画像特征和上下文信息,输出一个用户向量 $u$;物品塔整合物品的 ID、类别和属性特征,输出一个物品向量 $v$。匹配度通过两个向量的内积来衡量:
- 改进了负采样策略:增加了“同市场负采样”策略,一部分负样本从与正样本相同的地理市场中选择
- 面向业务的序列构建
FM(因子分解机):双塔模型的雏形
- FM的核心贡献在于,它首次将用户-物品的复杂交互,优雅地分解为两个低维向量的内积操作。
- FM 模型的完整数学表达式为: \(\hat{y}(x) := w_0 + \sum_{i=1}^{n} w_i x_i + \sum_{i=1}^{n} \sum_{j=i+1}^{n} \langle v_i, v_j \rangle x_i x_j\)
- 通过数学上的重新组织,我们可以得到 FM 的双塔表示:
- 用户向量: \(V_{\text{user}} = \left[ 1;\ \sum_{u \in U} v_u x_u \right]\)
- 物品向量: $$ V_{\text{item}} = \left[ \sum_{t \in I} w_t x_t
- \frac{1}{2} \sum_{f=1}^{k} \left( \left( \sum_{t \in I} v_{t,f} x_t \right)^2 - \sum_{t \in I} v_{t,f}^2 x_t^2 \right) ;\ \sum_{t \in I} v_t x_t \right] $$
DSSM:深度结构化语义模型
- DSSM将召回任务视为一个极端多分类问题,将物料库中的所有物品看作不同的类别。模型的目标是最大化用户对正样本物品的预测概率,因而直接训练DNN从特征得到嵌入向量计算相似度。
YoutubeDNN:从匹配到预测用户下一行为
YouTube 深度神经网络推荐系统(Covington et al., 2016)是双塔召回里的一个代表性工作。
-
它最大的变化不是把双塔做得更复杂,而是把召回任务重新定义成“预测用户下一次会看什么视频”。
-
YouTubeDNN 采用非对称双塔结构:用户塔编码观看历史、搜索历史和画像等特征,物品塔则更简单,基本上就是一个视频 ID 的嵌入表。这种设计的好处是,训练时可以利用丰富的用户侧信息,服务时只需要预计算视频向量,再实时计算用户向量即可。
-
从目标上看,它本质上是一个极大规模的多分类问题。由于视频库太大,不能直接做全量 Softmax,所以训练时一般会用 Sampled Softmax,只在正样本和少量负样本上计算损失。
- 在工程上,YouTubeDNN 还强调两个点:一是时序切分,预测目标只能看它之前的历史行为,避免未来信息泄露;二是负采样和样本均衡,避免高活跃用户主导训练。整体来看,它提供了一种很实用的范式:训练复杂、服务高效,召回阶段再配合 ANN 检索即可。
序列召回
- 前面的双塔模型倾向于将用户所有的历史行为“压扁”成一个单一的静态向量。这种做法高效,但有两个明显的局限:
- 压缩后难以再拆分分化用户兴趣,难以提取出多兴趣倾向
- 隐蔽了行为的时效性,难以提取短时和长时
- 序列召回要解决的就是这些问题
MIND:用多个向量捕捉用户的多元兴趣
MIND使用了”胶囊网络”处理序列,准确来说它并不是非常适配序列的特性,没利用时效周期性质,但是依旧有不错的效果。它的主要思想就是序列的每一项对不同的兴趣特征做动态贡献,再由这多个兴趣特征进行推荐计算。
- 共享变换矩阵:统一维数与规格
- 随机初始化路由系数:类似于多头的想法,让他们自主的分化
- 自适应兴趣数量:对多行为的用户提更多兴趣,有一定计算上的合理之处
SDM:融合长短期兴趣,捕捉动态变化
SDM将长短期兴趣拆分,使用用户画像作为查询做注意力计算,并使用LSTM和门逻辑辅助获得特征。
- 大批量使用了多头和注意力机制,在短期兴趣捕捉前用LSTM预处理,最后用门逻辑融合长短期兴趣
流式索引召回
召回阶段还有另一个问题:索引的时效性。传统的向量索引需要定期重建,重建间隔内新提交的内容和用户兴趣的即时变化都无法被及时捕捉。在内容快速更迭的平台上,这种延迟意味着推荐系统可能错过用户当前的真实需求。流式索引就是解决这一问题的有效方案。
聚类统计的全量兴趣召回
Trinity不再把用户行为压缩成向量,而是将物品映射到聚类空间,用统计直方图来记录用户在每个聚类上的行为计数。直方图没有容量限制,行为序列再长也不会丢失任何兴趣主题。在此基础上,Trinity设计了多元兴趣、长尾兴趣和长期兴趣三个互补的召回器。
实时更新的流式索引
Streaming VQ解决的是索引时效性问题。它让物品到聚类的映射关系随训练流程实时更新,聚类中心通过指数移动平均持续适应数据分布的变化,不再需要定期中断重建。同时通过流行度调节和扰动机制保持索引的平衡性,避免热门物品聚集在少数头部聚类。
ANN相关
对于动辄上亿的物品数据量,在做推荐系统时,召回的时间复杂度必须是亚线性级的,即在短时间求出操作序列或用户特征K近邻,但精准近邻在维度过大时容易坍缩成线性复杂度,因此我们需要近似近邻算法(ANN)。 部分算法的实现较为复杂,因此这里仅做介绍。
LSH:Locality-Sensitive Hashing
LSH 是最“数学定义最清楚”的 ANN 路线之一。
- 设计一族哈希函数 $\mathcal{H}$,使得: 如果 $x,y$ 相似,则 \(\Pr_{h\sim \mathcal H}[h(x)=h(y)]\) 较大;
- 如果 $x,y$ 不相似,则该概率较小。
- 这样,通过哈希桶把“可能近邻”的点聚集起来。
IVF-PQ
构建
- 用 k-means 训练 coarse centroids
- 给每个点分配簇 $a(i)$(实际就是Kmeans)
- 计算残差 $r_i=x_i-c_{a(i)}$
- 训练 PQ 子码本
- 对每个残差编码,存入其簇的 posting list
查询
- 给定 $q$:
- 计算 $q$ 到所有 coarse centroids 的距离
- 取最近 $n_{\text{probe}}$ 个簇
- 对每个访问簇,构造 ADC 距离查找表
- 扫描这些簇中的 PQ code,快速估计距离
- 维护 top-k heap
- 可选:对前 $R$ 个候选做原始向量 rerank
HNSW
Small-world 图有两个特征:
- 大部分边是局部边
- 少量长程边使图直径很小 这样查询时:
- 长程边帮助快速跳到大概区域
- 局部边帮助精细逼近最近邻 NSW的本质就是建立一个物品间的可导航Small-world图,以相似的前提建边,使得新增物品和查找的时间复杂度在图下被大幅度压缩。
- 但是其单层图存在不稳定和对插入顺序极其敏感的缺点 HNSW工业界目前最流行的召回ANN图索引算法,使用了分层NSW,极大改善了NSW的问题
- 它的核心思想是每个节点拥有一个最高层数上限,通过等可能的赋值可以使得多层图中上层稀疏下层密集,让上层作为引导,可以非常快的查找下一层。