文章目录
- 1. 背景
- 2. 方法
- 2.1 长语义id
- 2.1.1 获取 item embedding
- 2.1.2 item embedding 离散化
- 2.2 并行生成语义 id
- 2.2.1 训练(item串行,token并行)
- 2.2.2 高效 logit 打分
- 暴力枚举式打分:
- 高效实现:
- 复杂度分析:
- 2.3 图约束推理 Top-k
- 3. 实验
- 3.1 主试验
- 3.2 推理效率分析
- 3.3 消融实验
- 3.4 语义id长度
- 3.5 冷启动
- 3.6 推理参数 b/k/q
- 4. 总结
来学一下 KDD2025 的一篇 Meta 的关于 生成式推荐的文章:RPG( Recommendation with Parallel semantic ID Generation)。
论文链接:https://arxiv.org/pdf/2506.05781
代码链接:https://github.com/facebookresearch/RPG_KDD2025
1. 背景
生成式推荐大部分都是将每个 item 通过 codebook 拆分成多个 语义id(sid),这点就不说了。文中提到一个效率瓶颈,就是说这种自回归的方式延迟高,比如一个 item 用 3 个 sid 表示,就需要经过 3 次 decoder,还需要 beam-search 等策略生成多个候选,每一步都要维护多个”备选拼法“,比如我们想要通过 beam-search 得到 top 512,就需要在通过 bos 生成 sid0 的时候保留 top 512,然后再第二步的时候,需要将这 512 个同时输入 decoder,并将生成的 sid1 也保留 top 512,在这 262144 的概率组合中,选择 top512,再继续将这 512 个 sid0-sid1组合 输入到 decoder 第三步得到 sid2 的 top 512,然后再从 262144 个概率组合中,选择 top 512 的 sid0-sid1-sid2,得到 top 512的结果。这样需要跑大量的推理,耗时算力都比较大。
上面的方法还是说 用 3 个语义id 去表示一个 item 的情况,但是 token 太少,表达力不够,现实中一个 item 可能属性、内容很丰富,只用 3 个 token来描述肯定难以把 item 丰富的语义细致地编码出来,也就是说:token 越少,模型能表达的内容越有限;token越多,推理资源越扛不住。当然上面这种 3 个语义id 的方法 肯定需要 RQ 的,不然其实 3 个 token 表达的信息真的太少了,用了 RQ 其实应该还好。RQ 的话每层 codebook 就是有递进关系的了。
本文对比这篇 VQ-Rec 这篇文章是采用 Product Quantization(PQ)的方式,这种方式就是将一个 item embedding 比如 1024 维度,如果要分成 8 个 token,就是切成 8 份,每份 128 维,每份就是一个独立的子空间,每份子空间都配一个独立的 codebook,每个 codebook 大小就取决于需求了,假设是 8192 个吧,训练 codebook 采用 K-means 聚类,对每个子空间,用 K-means 聚类算法,聚出 8192 个中心点 表示 8192 个语义id。对于一个 item,我们可以将其切分,然后用其 每个 128 维 embedding 去各个 codebook 中找对应的 sid,拼成 8 个 sid,这 8 个 sid 就可以看做是这个 item 的语义id。实际推荐或下游任务,如果需要变回向量,直接把 8 个 sid 对应的 8 个中心向量查出来,拼接成最终的 item embedding。
对于并行生成 RPG 来说有两个挑战:
- 解码空间稀疏:所有 token 并行生成后,每个 token 之间没有顺序以来,互不影响,”合法“的 sid 组合在巨大的组合空间中其实极其稀少,比如 8 个 sid 每个 codebook 有 8192 个 token 就 81928 大约 1030 个组合,现实实际中,item 最多 也是 亿级 10 9 ,所以就会有大量 sid 组合 在实际商品池力根本不存在。
- 高效无序解码:推荐系统要为每个用户生成 top-k ,如果把所有可能得 token 组合都枚举出来就失去了 并行生成的效率优势。传统 beam-search 方法, token是有顺序的,可以依次生成,但是 RPG 方法里,token 是无序并行生成的,不需要按照固定顺序生成,所以不能用传统的有序解码策略。怎样才能在不遍历所有 token 组合的情况下,快速精准的找到真实存在的得分最高的 item id?
2. 方法
2.1 长语义id
2.1.1 获取 item embedding
本文采用两种将 text --> embedding 的 embedding模型 sentence-t5-base 以及 更强大的 openAI 的 text-emb-3-large,实验如下:
作者结论:对于 基于 OPQ 的 RPG 来说,换用更好的 embedding 模型,效果提升;但是对于 基于 RQ 的 TIGER 来说,效果差异不大。
2.1.2 item embedding 离散化
主流离散化方式有两种:RQ、PQ。
本文选择 PQ/OPQ,因为 PQ 并行预测友好,生成的 token 可以同时独立预测,不像 RQ 那样每一步都依赖前面的 token;表达均衡且可扩展:RQ 生成的 token 序列会出现 ”某些 token 很重要,某些 token 没啥用“的现象(信息分布不均),还容易随着 token 变多而失控(可扩展性差)。而 PQ/OPQ 各个 token 携带的信息比较均衡、规模也好扩展。
2.2 并行生成语义 id
2.2.1 训练(item串行,token并行)
训练目标是让模型能一次性并行预测所有 token,而不是像传统自回归那样一步步生成。
假设用户历史行为序列编码成向量 s s s,预测目标 item 的 sid ( c t , 1 , … , c t , m ) (c_{t,1}, \dots, c_{t,m}) (ct,1,…,ct,m)。
训练,最大化整个语义ID各个位的概率乘积(即并行多位分类):
L = − ∑ j = 1 m log P ( j ) ( c t , j ∣ s ) \mathcal{L} = -\sum_{j=1}^{m} \log \mathbb{P}^{(j)}(c_{t,j} | s) L=−j=1∑mlogP(j)(ct,j∣s)
其中,第 j j j 位token的概率 P ( j ) ( c t , j ∣ s ) \mathbb{P}^{(j)}(c_{t,j} | s) P(j)(ct,j∣s) 通过下式计算:
P ( j ) ( c t , j ∣ s ) = exp ( e c t , j ⊤ ⋅ g j ( s ) / τ ) ∑ c ∈ C ( j ) exp ( e c ⊤ ⋅ g j ( s ) / τ ) \mathbb{P}^{(j)}(c_{t,j}|s) = \frac{\exp(\mathbf{e}_{c_{t,j}}^\top \cdot \mathbf{g}_j(s)/\tau)}{\sum_{c \in C^{(j)}} \exp(\mathbf{e}_c^\top \cdot \mathbf{g}_j(s)/\tau)} P(j)(ct,j∣s)=∑c∈C(j)exp(ec⊤⋅gj(s)/τ)exp(ect,j⊤⋅gj(s)/τ)
- g j ( s ) \mathbf{g}_j(s) gj(s)是将序列表示 s s s 投影到第 j j j 个 codebook 空间的映射, τ \tau τ 是温度超参数。
2.2.2 高效 logit 打分
在模型训练好后,推理阶段的目标是:给定用户历史行为(编码为 s s s),计算每个候选商品的 sid组合 的匹配分数,挑出 Top-K 推荐。
暴力枚举式打分:
- 理论上:每个 item i 有自己的 sid ( c i , 1 , … , c i , m ) (c_{i,1},…,c_{i,m}) (ci,1,…,ci,m)。
- 按照训练时的loss公式,可以为每个 item i 打分: score i = ∑ j = 1 m log p c i , j ( j ) \text{score}i = \sum{j=1}^{m} \log p_{c_{i,j}}^{(j)} scorei=∑j=1mlogpci,j(j)
- 这里的 p c i , j ( j ) p_{c_{i,j}}^{(j)} pci,j(j) ,就是用户序列 s s s 在第 j j j 位 token 上,预测它是 c i , j c_{i,j} ci,j 的概率。
高效实现:
对于每一层 codebook(总共 m m m 层),先将用户行为序列 s s s 经过投影( g j ( s ) \mathbf{g}_j(s) gj(s))和温度缩放( τ \tau τ),与所有 codebook 的 embedding 计算点积(可以理解为分类 logit),再 softmax,得到该层所有 token 的概率分布 p ( j ) p^{(j)} p(j):
p ( j ) = softmax ( E j ⋅ g j ( s ) τ ) ∈ R M p^{(j)} = \text{softmax}\left( \frac{E_j \cdot \mathbf{g}_j(s)}{\tau} \right) \in \mathbb{R}^{M} p(j)=softmax(τEj⋅gj(s))∈RM
- E j E_j Ej 是第 j j j 层 codebook 的 embedding 表, M M M 是每层 codebook 的 token 数量(比如256)。
- 这一步只算 m m m 层,每层 M M M 个logit,和商品数量无关
对于任意一个商品 i i i,它的 sid组合 是 ( c i , 1 , … , c i , m ) (c_{i,1}, …, c_{i,m}) (ci,1,…,ci,m),直接取出每层对应 token 的概率 p c i , j ( j ) p_{c_{i,j}}^{(j)} pci,j(j),取对数相加:
score i = ∑ j = 1 m log p c i , j ( j ) \text{score}_i = \sum_{j=1}^{m} \log p_{c_{i,j}}^{(j)} scorei=j=1∑mlogpci,j(j)
只需查表+加法,就能算出每个商品的得分,最后选 Top-k 即可。
复杂度分析:
- 传统方式复杂度: O ( N m d ) O(Nmd) O(Nmd) (遍历所有商品,每个商品 m 位 codebook,每位与用户表示做一次点积)
- 优化后复杂度: O ( M n d + N m ) O(Mnd + Nm) O(Mnd+Nm) (M 远小于 N)前面是 每位 codebook 和用户序列 算一次点积,后面是查表累加。
2.3 图约束推理 Top-k
理论上,上面推理就可以了,遍历所有 item,把每个 item id 的所有 token logit 分数相加,得到总分,选分数最高的 Top-k。
但是:
- 实际 item 数量巨大,这样遍历太慢。
- 直接全遍历可能选出的 Top-k 商品 token 组合,有些组合其实在真实语义空间里不合法。因为每一位都是独立最大化,可能拼成不存在的 item id。
故提出 图约束推理:
核心思想:只允许在真实出现过的 item 之间做 Top-k 搜索,避免出现非法组合。
每个节点就是一个 item (sid 组合),边用 ”语义相似性“ (两个 item 如何 sid 组合接近 他们就相似)连起来:
- 两个节点 A = ( c 1 , 1 , … , c 1 , m ) A=(c_{1,1},…,c_{1,m}) A=(c1,1,…,c1,m) 和 B = ( c 2 , 1 , … , c 2 , m ) B=(c_{2,1},…,c_{2,m}) B=(c2,1,…,c2,m)。
- 相似度 S ( A , B ) = ∑ j = 1 m e j , c 1 , j T e j , c 2 , j S(A, B) = \sum_{j=1}^m \mathbf{e}_{j,c_{1,j}}^T \mathbf{e}_{j,c_{2,j}} S(A,B)=∑j=1mej,c1,jTej,c2,j
对每个节点,只保留相似度最高的 k 个邻居,构成稀疏图。
图推理流程:
- 随机采样一批节点作为候选集,比如上图中,随机采样 b 个节点,图中 2 个(实验中 10 个)
- 扩展候选集:对当前每个节点,找它在图中的 k 个邻居,图中 2 个(实验中 50-100-500 个)
- 打分:对候选集中每个节点,计算其 sid 分数(每一位 token 的 logit 相加)
- 保留得分最高的 b 个,作为新一轮候选
- 迭代 q 次(实验中 2-3-5 次)
- 最终保留 b 个节点
3. 实验
3.1 主试验
3.2 推理效率分析
原因:
- 高效的 token 级并行机制
- 图约束的稀疏检索机制
对比 TIGER:
- 推理速度慢:每一步都要 forward 一次模型,token 越多,推理越慢,复杂度随商品的 token 数量 和 beam-search 步数线性增加。
- infer 内存消耗大:beam-search 过程中要维护多个候选路径。
3.3 消融实验
3.4 语义id长度
小数据集支撑不了太多层 codebook,大数据集适合更多层 codebook
3.5 冷启动
3.6 推理参数 b/k/q
4. 总结
很有意思的工作!