文章目錄
- 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∑m?logP(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∑m?logpci,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=1m?ej,c1,j?T?ej,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. 總結
很有意思的工作!