白话生成式推荐系列一:Tiger-Recommender Systems with Generative Retrieval
文章目录
标题: Recommender Systems with Generative Retrieval
会议: NeurIPS2023
团队:Google
论文链接:Recommender Systems with Generative Retrieval
代码(非官方code):https://github.com/XiaoLongtaoo/TIGER(官方未开源,此代码为大佬复现)
摘要
现代推荐系统通过将查询(用户历史 / 会话)和候选物品嵌入到同一向量空间,并通过近似最近邻(ANN)检索来获取候选集合。
如:使用双塔模型将user和item映射为向量,然后比较向量之间的距离,距离越近表示两者越适合。
本文提出了一种新的 生成式检索(generative retrieval) 方法:检索模型自回归地解码目标候选的标识符(ID)。为此,我们为每个物品构建由语义 codeword 组成的有意义的元组,称为 Semantic ID(语义 ID)。
文中的检索,其实就是我们常说的召回。
在用户会话中,将物品的语义 ID 作为序列输入,使用基于 Transformer 的序列到序列模型去预测用户下一个将交互的物品的语义 ID。
实验表明,采用该范式训练的推荐系统在多个数据集上显著优于当前 SOTA 模型。另外,将语义 ID 融入 seq2seq 模型还能增强模型的泛化能力(例如对无交互历史的物品的检索性能有明显提升)。

如图1所示,生成式检索的大概步骤如下:
Step1: 将用户历史交互的item 经过 【Semantic ID Generator: 语义ID生成器,后文介绍是使用RQ-VAE】生成语义ID;
Step2: 将语义ID组成序列,然后输入到【Generative Retrieval:生成式检索模型,基于transformer】,然后输出Next item的语义ID;
Step3: 根据Next item的语义ID查询对应item。(这里会提前将所有的item都映射成对应的语义ID)
1.引言
推荐系统在视频、应用、商品、音乐等诸多领域中广泛应用。现代系统通常采用“检索 + 排序”(retrieve-and-rank)策略:检索阶段生成候选集,随后使用更复杂的排序模型对候选进行精排。由于排序模型只在接收到的候选上工作,检索阶段输出高质量候选至关重要。
召回-粗排-精排:这种级联结构,每个独立阶段的效果都成为后续排序阶段的性能上限,从而限制了整个排序系统的性能。
传统检索方法(如矩阵分解、双塔/dual-encoder 架构)将查询与候选映射到同一高维向量空间,使用点积/内积并借助 ANN 进行检索。近年来,双塔结构也扩展到了顺序推荐领域,以考虑用户交互顺序。
但本文提出一种替代范式:使用 end-to-end 生成模型直接预测候选 ID,并将 Transformer 的参数/记忆视为可微分的、端到端的检索索引(参考 Transformer memory / DSI 的思想)。我们将该方法命名为 Transformer Index for GEnerative Recommenders(TIGER)。TIGER 的核心在于一种称为 Semantic ID 的新型物品语义表示:先用预训练文本编码器(例如 Sentence-T5)将物品文本特征编码为稠密嵌入,再对嵌入进行量化(quantization),生成有序的 token/codewords 元组作为该物品的 Semantic ID。最终,利用这些语义 ID 训练用于序列推荐任务的 Transformer 模型。
表示物品为语义 token 序列有多项优点:
在语义意义明确的数据上训练 Transformer 内存,可实现相似商品间的知识共享; 传统推荐系统把每个物品当成一个孤立的整数 ID(如item 123,item 456),模型不能从 item 123 学到任何对 item 456 有用的信息 除非 这两个 item在训练集中“恰好经常一起出现”。
而 TIGER 的 Semantic ID(语义 ID)是由内容语义生成的离散 token,如:
注意到它们前两个 token 完全一样:
→ 表示它们属于同一类(phone case)。
→ Transformer在训练时会学到:只要用户喜欢语义 ID 前缀相同的商品,通常会继续看类似的。
- 摒弃了以前常用的原子随机 item id,更不易陷入推荐系统的反馈环路(feedback loop);
(1)什么是 feedback loop(反馈环): 传统推荐系统常用随机整数 ID 表示物品,比如: Item A → 123 ItemB → 456 Item C → 789 这些数字 没有语义、没有相似性、没有类别结构。 这会导致一个严重问题:
一旦模型开始推荐某些热门物品,它会不断加强它们的曝光,从而让训练数据中只有那些“热门 item”的点击记录。 如:
- Item A 在过去比较热门
- Item B 是很好的新商品,但没人点(因为没展示)
- Item C 是中等热门
由于模型只看到 A 的点击量最高,它会继续推荐 A → A 更热门: 这形成 正反馈: A(热门) → 推荐更多A → 更多点击 A → 更热门 → 再推荐更多A 同时 B 作为新商品,因为没有点击历史,随机 ID
没有任何语义结构帮助它,因此永远不会被推荐 → 永远得不到点击 → 永远不会变热门。 这就是“反馈环”。
(2)TIGER(语义ID)如何打破反馈环?
语义 ID 会让模型理解物品之间的内容相似性: 如:
iPhone 15 手机壳 → (10,21,50)
iPhone 14 手机壳 → (10,21,35)
iPhone 13 手机壳 → (10,21,40)
当用户常买 iPhone手机壳类商品时,模型会产生这样的学习:
用户喜欢 (10,21,XX) 这个语义类别的商品。
于是即使某个新商品从未出现过,但它的语义ID 显示它属于同类,模型仍可能会推荐它。
- 对新加入的物品(冷启动)更有泛化能力;
- 使用多 token 的组合极大扩展可表示的 item 空间(组合数是每个 token 基数的乘积),相较于为每个物品学习独立 embedding 更节省记忆。
本文主要贡献总结:提出 TIGER 框架、证明在多个数据集上优于 SOTA、并展示其在冷启动与可控多样性上的新能力。
2. 相关工作
本文相关方向包括顺序推荐、语义 ID / 向量量化方法、以及生成式检索三大类,这里概述如下:
- 顺序推荐:早期 GRU4Rec、NARM、SASRec、BERT4Rec、Transformers4Rec、S3-Rec 等,均以学习 item 高维 embedding 并用 ANN/MIPS 检索下一项作为主流。TIGER 则使用生成式检索直接预测下一个物品的语义 ID。
- 语义 ID:此前工作如 VQ-Rec 使用基于内容的信息生成“codes”来表示物品,但没有将其用于生成式检索;本工作使用 RQ-VAE(Residual-Quantized VAE)生成分层语义 ID,这带来了层级化表征的优点。也有并行工作的表明层级语义 ID 能改善模型泛化。
- 生成式检索:文献如 GENRE、DSI、NCI、CGR 等在文档检索领域提出通过生成 token-by-token 返回文档名或 ID 的思路;本文为首个将生成式检索与 RQ-VAE 风格的语义 ID 结合应用于推荐系统的工作(据作者所知)。
3.方法

如上图所示,总体分两阶段:
Stage1: 使用内容特征生成 Semantic ID:先用预训练内容编码器(例如 Sentence-T5)将物品内容(标题、描述、品牌、类别等)编码成向量,然后对向量进行量化,得到一组有序 codewords 的元组,作为 Semantic ID。
Stage2: 在 Semantic ID 空间上训练生成式推荐模型:把用户的交互序列转换为语义 token 序列(每个物品展开为其 m 个 codewords),用 Transformer encoder-decoder(seq2seq)模型自回归地预测下一个物品的 Semantic ID(逐 token 生成)。
下面详细说明 Semantic ID 的生成方法与生成式检索的训练方式。
3.1 Semantic ID 生成
假设每个物品具有内容特征,可用预训练编码器(Sentence-T5、BERT 等)产生语义embedding
x
∈
R
d
x \in \mathbb{R}^d
x∈Rd。然后使用量化方法将embedding映射为长度为
m
m
m 的 codeword 元组(每个 codeword 来自不同的 codebook)。理想特性:语义相近的物品应拥有高重叠的 Semantic ID(例如 (10,21,35) 与 (10,21,40) 应比 (10,23,32) 更相近)。本文主要采用 RQ-VAE(残差量化 VAE) 来学习分层 codebooks。RQ-VAE结构如下图所示:

(1)RQ-VAE 要点:
Encoder 将输入
x
x
x 编码为潜向量
z
z
z。在第 0 层取残差
r
0
:
=
z
r_0 := z
r0:=z。每层 d 有 codebook
C
d
=
{
e
k
}
C_d = \{e_k\}
Cd={ek}(大小 K)。将当前残差
r
d
r_d
rd 映射到最接近的 codebook 向量
e
c
d
e_{c_d}
ecd,然后计算新残差
r
d
+
1
=
r
d
−
e
c
d
r_{d+1} = r_d - e_{c_d}
rd+1=rd−ecd,迭代
m
m
m 次得到
m
m
m 个索引
c
0
,
…
,
c
m
−
1
c_0,\dots,c_{m-1}
c0,…,cm−1。最终量化向量为
z
^
=
∑
d
e
c
d
\hat z = \sum_{d} e_{c_d}
z^=∑decd ,送入 decoder 重构。训练损失包含重构项和量化项(VQ 类似的 stop-gradient 项与 commitment loss)。为了避免 codebook collapse,作者使用 k-means 在首批训练样本上初始化 codebooks。
上述逻辑看起来很难,但RQ-VAE的计算还挺好理解的,举个例子:
假设:
- 某个物品被内容编码器(如 Sentence-T5)编码后得到2维潜向量
z
=
[
5.2
,
3.1
]
z = [5.2,\; 3.1]
z=[5.2,3.1]
(2 维只是为了举例,论文里是 32 维) - RQ-VAE 有 两层(m=2) 残差量化
- 每层都有一个 codebook,里面是一些“典型向量”
我们设定两个 codebook 都有 3 个向量(现实中通常 256 个)。
其中,第0层 Codebook C 0 C_0 C0对应的向量如下:

那么第 0 层量化过程如下:
初始残差:
r
0
=
z
=
[
5.2
,
3.1
]
r_0 = z = [5.2,\; 3.1]
r0=z=[5.2,3.1]
计算与 codebook 中各向量的距离:
- 距离
[
4
,
2
]
[4, 2]
[4,2]
∣ ∣ [ 5.2 , 3.1 ] − [ 4 , 2 ] ∥ = 1.2 2 + 1.1 2 ||[5.2,3.1]-[4,2]\| = \sqrt{1.2^2 + 1.1^2} ∣∣[5.2,3.1]−[4,2]∥=1.22+1.12 - 距离
[
6
,
3
]
[6, 3]
[6,3]
∣ ∣ [ 5.2 , 3.1 ] − [ 6 , 3 ] ∥ = ( − 0.8 ) 2 + 0.1 2 ||[5.2,3.1]-[6,3]\| = \sqrt{(-0.8)^2 + 0.1^2} ∣∣[5.2,3.1]−[6,3]∥=(−0.8)2+0.12 - 距离
[
5
,
3
]
[5, 3]
[5,3]
∣ ∣ [ 5.2 , 3.1 ] − [ 5 , 3 ] ∥ = 0.2 2 + 0.1 2 ||[5.2,3.1]-[5,3]\| = \sqrt{0.2^2 + 0.1^2} ∣∣[5.2,3.1]−[5,3]∥=0.22+0.12
显然第三个最近,因此:
c 0 = 2 , e c 0 = [ 5 , 3 ] c_0 = 2, \quad e_{c_0} = [5,\; 3] c0=2,ec0=[5,3]
更新残差:
r 1 = r 0 − e c 0 = [ 5.2 , 3.1 ] − [ 5 , 3 ] = [ 0.2 , 0.1 ] r_1 = r_0 - e_{c_0} = [5.2, 3.1] - [5, 3] = [0.2,\; 0.1] r1=r0−ec0=[5.2,3.1]−[5,3]=[0.2,0.1]
第2层 Codebook C 1 C_1 C1对应的向量如下:

对应的第 1 层量化过程如下:
现在残差是:
r
1
=
[
0.2
,
0.1
]
r_1 = [0.2,\; 0.1]
r1=[0.2,0.1]
我们根据上面的计算向量距离,再次找最接近的向量:
- 距离
[
0.1
,
0
]
[0.1, 0]
[0.1,0]
0.1 2 + 0.1 2 \sqrt{0.1^2 + 0.1^2} 0.12+0.12 - 距离
[
0.3
,
0.1
]
[0.3, 0.1]
[0.3,0.1]
( − 0.1 ) 2 + 0 2 \sqrt{(-0.1)^2 + 0^2} (−0.1)2+02 - 距离
[
0.0
,
0.2
]
[0.0,0.2]
[0.0,0.2]
0.2 2 + ( − 0.1 ) 2 \sqrt{0.2^2 + (-0.1)^2} 0.22+(−0.1)2
最近的是:
c 1 = 1 , e c 1 = [ 0.3 , 0.1 ] c_1 = 1, \quad e_{c_1} = [0.3,\; 0.1] c1=1,ec1=[0.3,0.1]
更新最终残差(但已经不用再量化了):
r 2 = r 1 − e c 1 = [ − 0.1 , 0 ] r_2 = r_1 - e_{c_1} = [-0.1,\; 0] r2=r1−ec1=[−0.1,0]
最终量化结果:
我们得到的两个 codeword:
( c 0 , c 1 ) = ( 2 , 1 ) (c_0,\; c_1) = (2,\; 1) (c0,c1)=(2,1)
这就是原始向量 z = [ 5.2 , 3.1 ] z=[5.2,3.1] z=[5.2,3.1] 对应的语义ID。
我们的量化后的向量:
z ^ = e c 0 + e c 1 = [ 5 , 3 ] + [ 0.3 , 0.1 ] = [ 5.3 , 3.1 ] \hat{z} = e_{c_0} + e_{c_1} = [5,3] + [0.3,0.1] = [5.3,\; 3.1] z^=ec0+ec1=[5,3]+[0.3,0.1]=[5.3,3.1]
这与原始向量 z = [ 5.2 , 3.1 ] z=[5.2,3.1] z=[5.2,3.1] 已非常接近,因此 reconstruction loss 很小。
直观理解, 可以把 codebooks 想象成“词库”,里面每个向量都是一个“语义 token”。 - 第一层 codebook → 表示“粗类别”(如手机壳 vs. 电脑周边)
- 第二层 codebook → 表示更细类别(如 iPhone 系列 vs. Samsung 系列)
通过逐层逼近残差: - 第 0 层捕捉整体形状(粗语义)
- 第 1 层捕捉更精细的差异(细语义)
最终一个物品就被编码成:
( c 0 , c 1 ) (c_0,\, c_1) (c0,c1)
也就是论文中的 Semantic ID。
(2)替代方法与碰撞处理:
- 可选的量化方法包括 LSH(局部敏感哈希)、分层 k-means、VQ-VAE 等。文中消融显示 RQ-VAE 通常优于 LSH;VQ-VAE 在候选检索上与 RQ-VAE 相近,但失去层级表示带来的能力。
- 若多个物品映射到同一 Semantic ID(碰撞),论文建议在 ID 末端追加额外 token 使其唯一(碰撞检测仅在 RQ-VAE 训练完成后执行一次,通过查表实现)。这一查表在内存上比高维 embedding 更节省。
3.2 使用 Semantic ID 的生成式检索
对每个用户,将其交互按时间排序成
(
i
t
e
m
1
,
…
,
i
t
e
m
n
)
(item_1, …, item_n)
(item1,…,itemn)
将每个 item 展开为其 m 个 codewords,使输入序列为
(
c
1
,
0
,
…
,
c
1
,
m
−
1
,
c
2
,
0
,
…
,
c
n
,
m
−
1
)
(c_{1,0}, …, c_{1,m-1}, c_{2,0}, …, c_{n,m-1})
(c1,0,…,c1,m−1,c2,0,…,cn,m−1)
seq2seq 模型的目标是生成
i
t
e
m
n
+
1
item_{n+1}
itemn+1 的 codeword 元组
(
c
n
+
1
,
0
,
…
,
c
n
+
1
,
m
−
1
)
(c_{n+1,0}, …, c_{n+1,m-1})
(cn+1,0,…,cn+1,m−1)
由于生成是自回归的,模型有时可能生成不映射到任何物品的 ID(invalid IDs),但作者在数据上的实验表明概率低(对于 Top-10 预测,invalid ID 比例约 0.1% − 1.6%),可通过增加 beam size 并过滤无效 ID 或使用 prefix matching(前缀匹配,利用层级 ID)等方法处理。
4.实现细节及新能力
4.1 实现细节
RQ-VAE 实现细节
- 使用 Sentence-T5 预训练模型将物品内容(title、price、brand、category 等拼成一段文本)编码为 768 维语义向量。
- RQ-VAE encoder: 中间层尺寸 512、256、128,最终 latent 维度 32。采用三层残差量化(m=3),每层 codebook 大小 256,每个 codebook 向量维度 32。训练参数 β=0.25。训练 20k epoch(目标是 codebook 使用率 ≥ 80%),优化器 Adagrad,lr=0.4,batch=1024。生成的 3 元组再加一个用于碰撞与唯一性的第 4 token(若无碰撞则置 0),因此最终每个 item 的 Semantic ID 长度为 4。
序列到序列模型实现
- 基于 T5X 框架实现 encoder-decoder(双向 encoder + decoder),词表包含 semantic codeword token(总计 256×4 = 1024)以及 2000 个 user-id token(采用 hashing trick 将原始 user-id 映射到这 2000 个 token)。输入序列为 user-id token + 一系列语义 codeword token(表示用户历史)。作者表示增加 user-id 有助于个性化。
- Transformer: encoder/decoder 各 4 层,self-attention head 数 6,每 head 维度 64,MLP/hidden size 1024,输入维度 128,dropout 0.1,总参数约 13M。训练步数:Beauty & Sports 200k steps,Toys 100k steps,batch=256,学习率初始 0.01(前10k steps),随后 inverse-square-root 衰减。
4.2 新能力
作者在文中通过实验证明了生成式推荐在冷启动和推荐多样性上有着优秀的表现:

(1)冷启动(Cold-start):模拟新物品(将测试集中 5% 的物品从训练集中移除,作为 unseen items),在训练后仍用 RQ-VAE 为 unseen items 生成 Semantic ID。检索阶段允许候选集中包含与预测 Semantic ID 前 3 个 token 相同的 unseen items(并通过参数 ε 控制允许的 unseen items 比例)。作者把 TIGER 与基于语义空间的 KNN(Semantic_KNN)比较,实验显示 TIGER(在 ε ≥ 0.1 时)稳定优于 Semantic_KNN,在 Recall@K 上取得更好效果(Fig.5)。这说明基于语义 ID 的生成式检索在冷启动场景能更好地把新物品纳入候选。

(2)推荐多样性(Diversity):生成式解码可以采用 temperature-based 采样,来调节生成分布的多样性。利用语义 ID 的层级结构,可以在不同层级上进行采样以控制粗粒度或细粒度的多样性。例如对第一个 token 采样可获得不同粗类,采样第二/三 token 可在某一类内采样更细粒度项。作者用 Entropy@K 衡量预测项的类别分布熵(表格 3),并给出温度 T 对熵与 top-10 的质的影响(表 4)。实验表明,升高温度能有效增加预测结果类别的多样性。

5. EasDeepRecommand个人推荐系统开源项目介绍

链接如下:EasyDeepRecommand
一个通俗易懂的开源推荐系统(A user-friendly open-source project for recommendation systems).
本项目将结合:代码、数据流转图、博客、模型发展史 等多个方面通俗易懂地讲解经典推荐模型,让读者通过一个项目了解推荐系统概况!
持续更新中…, 欢迎star🌟, 第一时间获取更新,感谢!!!
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐




所有评论(0)