CCFRec-人大高瓴-KDD2025-序列推荐中充分融合协同信息与语义信息

发布于:2025-07-27 ⋅ 阅读:(27) ⋅ 点赞:(0)


这里记录一下人民大学高瓴学院-KDD2025的一篇关于语义与协同对齐的文章:《Bridging Textual-Collaborative Gap through Semantic Codes for Sequential Recommendation》

论文链接:https://arxiv.org/abs/2503.12183

代码链接:https://github.com/RUCAIBox/CCFRec?tab=readme-ov-file

1. 背景与问题

序列推荐任务下,主流做法都是侧重于 ID 协同过滤(只看用户和商品的 ID,忽略内容),可以很好的捕捉用户和商品间的互动关系,但现代平台的商品文本内容(标题、品牌、描述)极为丰富,这些信息能更精准刻画商品本身,也有助于解决冷启动问题。

近年来有一些方法把文本信息和 ID 信息拼接或加权,但常常导致两种信息融合不自然,要么太依赖文本,忽略协同关系,要么文本利用不足,丢失语义信息。

在这里插入图片描述

本文关注如何在序列推荐任务中,通过更智能的语义融合机制,把商品文本信息和用户行为序列的信息深度结合起来,让推荐系统既懂“内容”又懂“行为”。

本文提出 CCFRec 通过 sid(semantic id)作为桥梁,sid 有两个重要特征

  1. 可以理解为特殊 id,每个 id 有自己的可学习 embedding,可以像传统 id 那样建模协同语义。
  2. 每个 item 可以有多组 sid(每个 item 多个特征如:标题、品牌、类别,每个特征一组 sid,代码中搞了 5 套),能反应不同层次的内容语义,让相似内容的 item 自动贴近(同 RPG 文章中提到的,如果有几位相同的 sid 这两个 item 就比较相似)。

本两个创新目标

  1. 用 sid 指导模型,灵活地从文本信息中抽取对推荐有用的部分,不会死板地全部用文本。
  2. 让商品的最终表示既有内容信息,又有协同信息,让推荐系统更精确。

2. 方法

在这里插入图片描述

2.1 多视图 sid

这里思想特别简单(有点大力出奇迹的意思),就是将每个 item 的多种属性,论文代码中是 5 种(title,brand,features,categories,description),经过 embedding model 得到对应的 embedding,然后搞多套 sid

对比之前的方法都是将每个 item 的所有属性拼成一句话经过 embedding model,这样更细致了。最后将每个属性的 sid 拼在一起,组层一个大 sid 表。(每个属性 20 层 pq/rq 的 codebook,拼在一起 100 层)

每个商品有多个文本属性(如title、brand、features、categories、description):

  • Step 1:文本编码
    用预训练模型分别将每个属性编码为文本embedding向量:
    z i t = PLM ( a i ) , i ∈ { 1 , . . . , m } z_i^t = \text{PLM}(a_i), i \in \{1,...,m\} zit=PLM(ai),i{1,...,m}

  • Step 2:向量量化成sid
    对每个属性的文本embedding,用向量量化技术(PQ或RQ)转为多层语义码sid
    z i t → ( c 1 i , . . . , c k i ) z_i^t \rightarrow (c_1^i,...,c_k^i) zit(c1i,...,cki)
    比如用了5个属性,每个属性20个sid,则每个商品就有5×20=100个sid。

2.2 Code-Guided Semantic Fusion

在这里插入图片描述

核心创新:

这是其实比较新颖的一个点就是将经过 embedding model 得到的 embedding 作为 K/V 去增强 embedding 质量。

这个模块是本文最核心的创新

输入两类embedding:

  • 属性embedding Z t = [ z 1 t , . . . , z m t ] Z^t=[z_1^t,...,z_m^t] Zt=[z1t,...,zmt](内容信息)
  • 语义码embedding Z c = [ z 1 c , . . . , z n c c ] Z^c=[z_1^c,...,z_{n_c}^c] Zc=[z1c,...,zncc](协同信息)

这个模块由多层Transformer-like结构组成,每层包括:

  • Self-Attention层
    语义码之间相互融合:
    H ~ l = MHA ( H l − 1 , H l − 1 , H l − 1 ) \tilde{H}^l = \text{MHA}(H^{l-1},H^{l-1},H^{l-1}) H~l=MHA(Hl1,Hl1,Hl1)

  • Cross-Attention层
    以语义码embedding 为 query,以文本属性 embedding 为 key 和 value,主动抽取有用的文本信息:
    H l = FFN ( MHA ( H ~ l , Z t , Z t ) ) H^l = \text{FFN}\left(\text{MHA}\left(\tilde{H}^l,Z^t,Z^t\right)\right) Hl=FFN(MHA(H~l,Zt,Zt))

  • 最终得到商品融合表示:

    • 先池化获得整体表示: e = Pool ( H ) e=\text{Pool}(H) e=Pool(H)

    • 再加一个残差连接保留原始sid信息:
      e ~ = e + Pool ( Z c ) \tilde{e}=e+\text{Pool}(Z^c) e~=e+Pool(Zc)

通过上述模块,每个商品得到了高质量的语义融合向量 e ~ \tilde{e} e~

常规操作:

  • 将用户历史序列商品的融合embedding拼成序列,加位置编码,输入Transformer网络:
    h ^ i 0 = e ~ i + p i \hat{h}_i^0=\tilde{e}_i+p_i h^i0=e~i+pi

  • Transformer多层建模序列行为关系,得到最后一层隐藏状态:
    H ^ l = FFN ( MHA ( H ^ l − 1 , H ^ l − 1 , H ^ l − 1 ) ) \hat{H}^l=\text{FFN}\left(\text{MHA}\left(\hat{H}^{l-1},\hat{H}^{l-1},\hat{H}^{l-1}\right)\right) H^l=FFN(MHA(H^l1,H^l1,H^l1))

  • 最后一个位置的隐藏向量表示用户当前兴趣:
    r = H ^ L [ − 1 ] r=\hat{H}^L[-1] r=H^L[1]

损失

用户表示 r r r 与下一个点击商品embedding e ~ n + 1 \tilde{e}_{n+1} e~n+1 相似度最大,负样本相似度最小。 用Cross-Entropy损失:
L C E = − log ⁡ exp ⁡ ( g ( r , e ~ n + 1 ) / τ ) ∑ j ∈ B exp ⁡ ( g ( r , e ~ j ) / τ ) \mathcal{L}_{CE}=-\log\frac{\exp\left(g(r,\tilde{e}_{n+1})/\tau\right)}{\sum_{j\in\mathcal{B}}\exp\left(g(r,\tilde{e}_j)/\tau\right)} LCE=logjBexp(g(r,e~j)/τ)exp(g(r,e~n+1)/τ)

  • 其中, B \mathcal{B} B是正负样本集合, τ \tau τ是温度系数, g g g是余弦相似度。

2.3 Enhanced Representation Learning via Code Masking

作者提出通过额外的两个训练任务(基于掩码策略)增强模型的表示学习能力,分别是:

  • Masked Code Modeling (MCM, 掩码语义码建模)
  • Masked Sequence Alignment (MSA, 掩码序列对齐)

在这里插入图片描述

2.3.1 Masked Code Modeling (MCM)

  1. 核心思想

受自然语言处理中 BERT 模型的启发(通过掩码语言建模MLM学习文本表示),这里对语义码序列进行随机掩码,训练模型去恢复被掩盖的语义码,以促进语义码和文本信息更好地融合

  1. 具体做法
  • 每个商品拥有一个语义码序列:
    s c = ( c 1 , c 2 , . . . , c n c ) s^c = (c_1, c_2, ..., c_{n_c}) sc=(c1,c2,...,cnc)

  • 随机将一定比例 ρ \rho ρ 的语义码掩盖 (如 [ M A S K ] [MASK] [MASK] ),得到掩盖后的序列:
    s ^ c = ( c 1 , . . . , [ M A S K ] , . . . , c n c ) \hat{s}^c = (c_1, ..., [MASK], ..., c_{n_c}) s^c=(c1,...,[MASK],...,cnc)

  • 语义融合模块(SFM)接收到这个掩盖序列,要利用文本embedding和未掩盖的码,推测出被掩盖的码。

  1. 损失函数

预测的目标是让模型给掩盖位置预测正确的语义码:
L MCM = 1 ∣ M c ∣ ∑ x ∈ M c − log ⁡ exp ⁡ ( g ( h ^ x , z x c ) / τ ) ∑ j ∈ C exp ⁡ ( g ( h ^ x , z j c ) / τ ) \mathcal{L}_{\text{MCM}} = \frac{1}{|\mathcal{M}^c|}\sum_{x\in\mathcal{M}^c}-\log\frac{\exp(g(\hat{h}_x,z_x^c)/\tau)}{\sum_{j\in C}\exp(g(\hat{h}_x,z_j^c)/\tau)} LMCM=Mc1xMclogjCexp(g(h^x,zjc)/τ)exp(g(h^x,zxc)/τ)

  • 其中:
    • M c \mathcal{M}^c Mc 为掩盖位置的集合。
    • g ( h ^ x , z x c ) g(\hat{h}_x,z_x^c) g(h^x,zxc) 为预测表示(通过融合模块输出的隐藏向量 h ^ x \hat{h}_x h^x)和真实码embedding z x c z_x^c zxc 的余弦相似度。
    • 分母上的集合 C C C 表示所有语义码集合,作为分类的类别。
    • τ \tau τ 是温度系数,用于softmax平滑。
  1. 作用与优势
  • 增强语义码之间的关联性
  • 提高文本embedding与语义码之间的对齐能力。

2.3.2 Masked Sequence Alignment (MSA)

  1. 核心思想

这个任务用来增强推荐主干网络的序列建模能力,通过掩盖部分语义码产生数据增强(data augmentation),再进行对比学习(Contrastive Learning),提升模型对于序列建模的稳健性

  1. 具体做法
  • 同样对输入商品序列的语义码随机掩盖部分码,获得掩盖后的序列。
  • 掩盖序列经过语义融合模块(SFM)得到增强版的商品表示(augmented item representation)。
  • 将增强版的序列与原始序列分别输入到推荐主干网络,得到两种用户序列表示:
    • 原始表示 r r r(未掩盖序列)
    • 增强表示 r ^ \hat{r} r^(掩盖序列)
  • 希望相同序列的原始和增强版表示更相似,不同序列的表示更不同。
  1. 损失函数(公式7、8):

采用 InfoNCE 对比损失:
L MSA = 1 2 ( InfoNCE ( r ^ , r , B r ) + InfoNCE ( r , r ^ , B r ^ ) ) \mathcal{L}_{\text{MSA}} = \frac{1}{2}\bigl(\text{InfoNCE}(\hat{r}, r, \mathcal{B}_r) + \text{InfoNCE}(r, \hat{r}, \mathcal{B}_{\hat{r}})\bigr) LMSA=21(InfoNCE(r^,r,Br)+InfoNCE(r,r^,Br^))
其中 InfoNCE定义为:
InfoNCE ( x , y + , R y ) = − log ⁡ exp ⁡ ( g ( x , y + ) / τ ) ∑ y ∈ R y exp ⁡ ( g ( x , y ) / τ ) \text{InfoNCE}(x, y^+, \mathcal{R}_y) = -\log\frac{\exp(g(x,y^+)/\tau)}{\sum_{y\in\mathcal{R}_y}\exp(g(x,y)/\tau)} InfoNCE(x,y+,Ry)=logyRyexp(g(x,y)/τ)exp(g(x,y+)/τ)

  • ( x , y + ) (x,y^+) (x,y+) 表示一对正样本(即来自同一用户序列的原始表示与增强表示)。
  • 集合 R y \mathcal{R}_y Ry 包含了正样本和批次内其他序列(负样本)的表示。
  • 目的是拉近同序列表示(正样本),拉开不同序列表示(负样本)。
  1. 作用与优势:
  • 增加训练数据多样性,有效提升模型对用户序列的泛化能力和稳健性。

最后,综合起来三个优化目标(推荐预测损失、掩码语义码损失、掩码序列对齐损失),整体训练目标为:
L = L C E + α L M C M + β L M S A \mathcal{L} = \mathcal{L}_{CE} + \alpha\mathcal{L}_{MCM} + \beta\mathcal{L}_{MSA} L=LCE+αLMCM+βLMSA

  • L C E \mathcal{L}_{CE} LCE:推荐任务损失(预测下一个商品)。
  • L M C M \mathcal{L}_{MCM} LMCM:掩码语义码建模损失,优化SFM语义融合效果。
  • L M S A \mathcal{L}_{MSA} LMSA:掩码序列对齐损失,优化序列建模的稳健性。
  • α , β \alpha,\beta α,β 为超参数,调节不同任务的比重。

2.4 复杂度分析

2.4.1 训练阶段(Training)

CCFRec有两个关键模块:

  1. 语义融合模块(SFM, Semantic-Fusion Module)
  2. 序列推荐主干(SR, Sequential Recommendation backbone),比如SASRec那样的Transformer结构。
SFM部分
  • 在SFM中,主要有三种操作:自注意力层(Self-Attention)、跨融合层(Cross-Fusion)、前馈网络(Feed-Forward)。
  • 对于单个item,计算复杂度分别是:
    • 自注意力层:O(M²d)
    • 跨融合层:O(MKd)
    • 前馈网络:O(Md²)
  • 其中:
    • d 是模型的表示维度(embedding维度)
    • M 是语义code序列的长度
    • K 是属性序列的长度
  • **综合起来,得到一个item的SFM输出的总体复杂度:**O(M²d + MKd + Md²)
SR部分
  • 主干SR一般用的是SASRec那种Transformer结构,主要消耗在自注意力层和前馈层。
  • 假设用户行为序列长度为N,则总复杂度为:O(N²d + Nd²)
总体训练复杂度
  • 将SFM和SR加在一起,并考虑 batch(多个item同时训练),总训练复杂度为:O(N²d + Nd² + NM²d + NMKd + NMd²)
  • 这里N是用户序列的长度,M和K是item属性和code数量,d是embedding维度。
  • 重点:实际应用中,M 和 K 远小于 N(通常N>50,M、K一般不超过20),所以额外的开销是可以接受的

(代码中我看到 M=100,K=20,额。。。不过工业界数据上确实也是 K 会更大)

2.4.2 部署阶段(Deployment)

  • 部署时,为了提高效率,SFM模块可以被去掉,因为训练好的语义融合表示(item embedding)是固定的
  • 我们可以提前离线计算每个item的最终embedding(用SFM提前处理好,存下来),只用主干SR进行推理。
  • 这样,线上推理时的复杂度与SASRec等主流序列推荐模型完全一样,都是 O(N²d + Nd²)
  • 也就是说,部署阶段CCFRec的推理速度不会比常见的序列推荐模型慢。

这里倒是没问题。

3. 实验

3.1 主实验

在这里插入图片描述

3.2 消融实验

感觉这些消融有点没到点上,看不出来那些是本文最重要的组件。也没有整个去掉(1)(2)的,都是去掉很小的东西,然后微降效果

在这里插入图片描述

3.3 codebook 层数

层数增加效果提升,这里还是有点 scaling-law 的意义:

在这里插入图片描述

3.4 不同 sid

在这里插入图片描述

这里得到比较有趣的现象:

Random code是无用但无害:模型会“忽略”它,不依赖它。

SASRec code是冗余且有害:模型会“重复利用”协同信息,导致空间浪费,降低性能。

3.5 加 item id

论文采取了一种 参数高效(parameter-efficient) 的方式,简单来说就是在保持原有文本-语义表示的基础上,再加上一份独立的 item ID embedding,并且只训练这部分参数,步骤如下:

  1. 先用原始的 CCFRec 进行预训练,学习出每个物品的语义融合表示(只用文本+code)。
  2. 引入 item ID embedding lookup table:对每个物品,分配一个随机初始化的可训练 embedding(通常与语义表征等长,比如128维)。
  3. 冻结原有 CCFRec 所有参数,只训练 ID embedding,即其他部分参数都不动,只让 ID embedding 随训练迭代更新。
  4. 最终物品表示为
    • 最终表示 = 语义融合表示 + ID embedding
    • 两者直接相加后,作为输入传递给序列推荐器(如 Transformer/SASRec 等)。
  5. 继续用推荐损失(如交叉熵)finetune,直到收敛。

原本 CCFRec 只用文本和对应的 semantic code(语义码)来表达物品,不用传统的 item ID embedding。这样做的好处是更关注于文本的内容表达,便于泛化和冷启动,但有个明显的短板:无法表达“物品之间纯 collaborative(协同过滤)信息”,即没法捕捉到只有 ID 层面才有的微小区分。

在这里插入图片描述

4. 总结

主要是对 item embedding 与 text embedding 融合的工作,感觉设计的十分复杂(复现的时候训练相比于其他模型时间多太多),实验整体感觉差点意思,消融做的没看出哪些最关键组件,不过对于部署阶段的复杂度分析倒是感觉算是合理,相当于增加了训练阶段的算力以及存储,换准确度?


网站公告

今日签到

点亮在社区的每一天
去签到