CoFiRec: Coarse-to-Fine Tokenization for Generative Recommendation
University of Illinois Urbana-Champaign × Meta × University of California San Diego
把「物品语义的粗到细层级」显式写进 Semantic ID:不再把类目/标题/描述拼成一个向量做 RQ-VAE,而是按 类目→标题→描述 三个语义层各自编码、各自量化成一个 token,再用预训练 SASRec 的 CF 向量量化成最后一个 token。生成时按粗到细顺序解码,并给每个 token 加 level/position 嵌入;在 Instruments/Yelp/Beauty 上比 TIGER、IDGenRec 等平均高约 6-7%,冷启动子集增益约 10%。
核心思路
现有 SID 方法(TIGER、LETTER 等)把物品的类目、标题、描述等字段拼成一段文本、编码成一个向量后做 RQ-VAE 残差量化。残差量化带来的是「数值误差的层级」,不是「语义粒度的层级」:第一位 code 不一定对应类目,前缀和类目对不齐。
CoFiRec 的做法是让 SID 的每一位对应一个明确的语义粒度:第 1 位=类目,第 2 位=标题,第 3 位=描述,第 4 位=协同过滤(CF)信号。每个字段独立编码、独立量化,生成时严格按粗到细顺序解码,模拟用户「乐器 → 电吉他 → Yamaha Pacifica 系列 → 某一把」逐步收敛的过程。CF token 放最后,用来在语义相近的物品之间做行为层面的消歧。
理论上,作者把逐层条件解码建模为 V 叉树遍历,证明在每层正确率 p>1/V 时,其预测物品与真值的期望树距离小于「独立均匀采样」。
整体实现思路
两阶段,与 TIGER 相同:
- Tokenizer 阶段:每个物品构造 4 层输入 —— 类目文本、标题文本、描述文本(均用 LLaMA-7B 取嵌入)和 SASRec 的 768 维物品嵌入。三个文本层共享 MLP 编码器/解码器、各有独立码本;CF 层有独立的编码器、码本、解码器。每层量化成 1 个 token,得到长度 K=4 的 SID,如
<a_105><b_208><c_157><d_50>。 - 生成阶段:T5 编码器-解码器读入用户最近 20 个物品的 SID 序列,输入嵌入 = token ID 嵌入 + 层级嵌入 + 历史位置嵌入;按层级顺序自回归生成下一物品的 4 个 token,每层在本层词表内做 softmax 排序损失;推理 beam=20。
子模块实现(可复现细节)
层级构造
- 用数据集中现成的 category / title / description 三个字段作为 Level 1-3,Level 4 为 CF。
- 少量类目缺失的物品,用简单信息抽取从标题或描述里抽类目词补齐;元数据完全缺失的物品直接丢弃。
- 附录给了无结构元数据的替代方案 AHC:用 GPT-4o 根据标题+描述生成 4 级层级(Level 4 是含品牌/型号/功能的一句话摘要)。
语义 Tokenizer
- 每层文本 x^(k) 用预训练 LLaMA-7B 编码得到 e^(k)。
- 共享 MLP 编码器:h^(k) = f_Sem(e^(k));每层独立码本 Q_k:s^(k) = argmin_j ||h^(k) - c_j^(k)||^2。
- 共享 MLP 解码器 g_Sem 从码字重建 e^(k)。作者的理由是共享编解码器让各层落在一致的码空间里。
CF Tokenizer
- 取预训练 SASRec 的物品嵌入 e_cf(768 维)。
- 独立的 f_CF / Q_K / g_CF,因为 CF 空间和文本空间分布不同。
Tokenizer 损失与训练
- L_Tokenizer = L_Recon + L_Commit
- L_Recon = Σ_{k=1..K-1} ||e^(k) - g_Sem(c^(k))||^2 + ||e_cf - g_CF(c^(K))||^2
- L_Commit = Σ_k ||sg[h^(k)] - c^(k)||^2 + μ ||h^(k) - sg[c^(k)]||^2,μ = 0.25,直通估计器回传梯度
- AdamW,lr 1e-3,训练 10,000 epoch;码本大小在 {256, 512, 1024} 中搜索,主配置 [256, 256, 512, 512]
生成模型
- 骨干 T5(沿用 TIGER 设置);另在采样数据上试了 LLaMA-3.2-1B / 3B。
- 输入嵌入:e_t^(k) = E_id(s_t^(k)) + E_level(k) + E_pos(t),t 是物品在历史中的位置。
- 排序损失:L_Rank = -Σ_{k=1..K} log [ exp(φ(s^(k))/τ) / Σ_{v∈V^k} exp(φ(v)/τ) ],τ = 1。注意归一化只在本层词表 V^k 内做。
- lr 在 {3e-4, 4e-4, 5e-4, 6e-4} 中搜索;历史截断 20;beam size 20。
理论命题
- 层级解码:每层条件正确率 p,第 k 层出错时距离为 K-k,E_hier = K - Σ_{k=1..K} p^k。
- 独立解码:建模为在 V^K 个叶子上均匀采样,E_indep = K - Σ_k (1/V^k)·(1-p^K)/(1-1/V^K)。
- 借助 ψ(p) = (K - Σp^k)/(1-p^K) 在 [0,1] 严格递减,以及 p > 1/V,得到 E_hier < E_indep。
- 推断:这里的「独立解码」等价于随机猜测,并不对应 TIGER 的实际解码方式(TIGER 同样是逐层条件解码),所以这个命题解释不了 CoFiRec 相对 TIGER 的优势,只说明了「条件解码优于随机」。
实验设置与结果
数据(5-core,leave-one-out,历史截断 20):
| 数据集 | 用户 | 物品 | 交互 | 平均序列长 |
|---|---|---|---|---|
| Instruments | 24,772 | 9,922 | 206,153 | 8.32 |
| Yelp | 30,431 | 20,033 | 316,354 | 10.40 |
| Beauty | 22,363 | 12,101 | 198,502 | 8.88 |
主结果(节选,Table 1):
| 数据集 | 指标 | SASRec | CID | LETTER | TIGER | IDGenRec | CoFiRec |
|---|---|---|---|---|---|---|---|
| Instruments | R@10 | 0.0947 | 0.0987 | 0.0982 | 0.1035 | 0.0999 | 0.1118 |
| Instruments | N@10 | 0.0690 | 0.0751 | 0.0760 | 0.0782 | 0.0785 | 0.0820 |
| Yelp | R@10 | 0.0296 | 0.0338 | 0.0259 | 0.0270 | 0.0323 | 0.0395 |
| Yelp | N@10 | 0.0152 | 0.0181 | 0.0147 | 0.0173 | 0.0195 | 0.0208 |
| Beauty | R@10 | 0.0588 | 0.0597 | 0.0427 | 0.0353 | 0.0550 | 0.0679 |
| Beauty | N@10 | 0.0313 | 0.0347 | 0.0213 | 0.0283 | 0.0311 | 0.0370 |
Yelp 上 LightGCN R@10 为 0.0383,是该集最强基线;Yelp N@5 上 IDGenRec(0.0165) 略高于 CoFiRec(0.0162)。正文称比最强基线高 6.4%,引言称平均高 7.27%。另外 Table 1 里 LightGCN 在 Instruments 的 R@10 = 0.0100 低于其 R@5 = 0.0794,TIGER 在 Beauty 的 R@10(0.0353) 几乎等于 R@5(0.0349),疑似录入错误或基线没训好。
消融(Instruments,Table 2a):
| 变体 | R@5 | R@10 | N@5 | N@10 |
|---|---|---|---|---|
| 反转层序 | 0.0859 | 0.1047 | 0.0724 | 0.0785 |
| 随机层序 | 0.0834 | 0.0991 | 0.0725 | 0.0775 |
| 去掉 E_level & E_pos | 0.0885 | 0.1072 | 0.0753 | 0.0813 |
| CF token 换成语义 token | 0.0870 | 0.1082 | 0.0740 | 0.0808 |
| VAR 式多尺度池化 | 0.0675 | 0.0798 | 0.0599 | 0.0639 |
| CoFiRec | 0.0897 | 0.1118 | 0.0752 | 0.0820 |
码本配置(Table 3) 与碰撞率(Table 6/7):
| 配置 | R@10 | N@10 | 碰撞率 |
|---|---|---|---|
| [256,256,256,256] | 0.1078 | 0.0795 | 0.0001 |
| [256,256,512,512] | 0.1111 | 0.0822 | 0.0000 |
| [256,256,512,1024] | 0.1065 | 0.0804 | 0.0000 |
码本利用率(主配置):L1 203/256(79.30%)、L2 226/256(88.28%)、L3 386/512(75.39%)、L4 510/512(99.61%)。同为 256 码本时 RQ-VAE vs CoFiRec 碰撞率:Instruments 0.0027 vs 0.0001,Yelp 0.0410 vs 0.0002,Beauty 0.0009 vs 0.0002。
冷启动(Table 4,冷物品 = 作为序列末项出现频次最低的 2%):
| 场景 | 方法 | R@10 | N@10 |
|---|---|---|---|
| Warm | TIGER | 0.1038 | 0.0784 |
| Warm | CoFiRec (+4.7%) | 0.1101 | 0.0816 |
| Cold | TIGER | 0.0801 | 0.0688 |
| Cold | CoFiRec (+10.0%) | 0.0943 | 0.0767 |
换骨干(Table 5,采样版 Instruments):
| 骨干 | TIGER R@10 | CoFiRec R@10 | TIGER N@10 | CoFiRec N@10 |
|---|---|---|---|---|
| T5 | 0.0484 | 0.0605 | 0.0307 | 0.0327 |
| LLaMA-1B | 0.0282 | 0.0444 | 0.0226 | 0.0342 |
| LLaMA-3B | 0.0282 | 0.0403 | 0.0205 | 0.0373 |
GPT-4o 自动层级(AHC,1% 用户 / 2,258 物品):R@10 0.0484(同 TIGER),全元数据 CoFiRec 0.0605;N@5 上 AHC 0.0313 反而高于全元数据版 0.0288。
开销(Table 10):生成训练 402.3 vs 400.7 s/epoch(TIGER),推理 0.0943 vs 0.0998 s/step;tokenizer 显存 < 1.8 GB,T5 生成 < 4 GB。论文没有线上实验。
思考与可参考价值
值得借鉴的点
- 字段级分层 SID:电商天然有类目树、标题、详情、行为四类信号。把类目放第一位,可以直接得到「前缀即类目」的 SID,方便做类目约束 beam、类目打散和可解释性分析。
- CF 作为最细层:语义 token 解决「是什么」,CF token 解决「谁会一起买」。消融里把 CF 换成语义 token,R@10 从 0.1118 掉到 0.1082。对已有 RQ-VAE SID 的系统,在末尾挂一个 CF 码本是成本很低的实验。
- 码本容量随层递增:粗层 256、细层 512 最好,再大反而掉点;同时盯利用率和碰撞率。
- 冷启动:新品没有行为,但类目/标题层可以给出正确前缀,论文里冷启动增益(+10%)是 warm(+4.7%) 的两倍。
需要警惕的点
- 实验规模只有 1-3 万物品,K=4、每层 1 个 token 在千万级商品池里能否区分,需要先测碰撞率。推断:类目层只有 256 个码,平台叶子类目通常更多,可能要让类目层直接用真实类目 ID 或者给类目分配多个 token。
- 基线有明显异常值(LightGCN、TIGER@Beauty),加上 CoFiRec 同时换了特征编码器(分字段 LLaMA-7B)、加了 CF token 和层级嵌入,增益来源没有拆清楚。最该补的对照是「RQ-VAE + 同一个 CF token + 同样的损失」。
- 顺序消融显示反转层序只掉约 6%,粗到细顺序本身的贡献有限;理论命题的对照组是随机猜测,不能说明字段层级优于残差层级。
- CF 码本依赖 SASRec 嵌入,行为分布漂移后要重训,SID 稳定性(老物品 ID 是否变化)论文没有讨论。
落地前要验证:自家数据上同口径对比 RQ-VAE+CF;千万级商品下的碰撞率和各层利用率;类目层用真实类目 ID 和用量化后的类目文本哪个更好;CF 码本的刷新周期和 SID 稳定性。