端到端生成式推荐 —— OneRec 精读笔记

文章链接:https://arxiv.org/pdf/2502.18965

机构:快手

发布时间:2025.02

Copyright (c) Wang-Luning. All Rights Reserved.

OneRec系列继承了Tiger使用SID直接预测下一个物品的范式,并通过RL等优化手段使得其生成效果更好,能够更接近端到端的目标效果。

传统的级联式推荐系统中,下游模块(例如ranking)的效果上限完全取决于上游模块(例如召回)给出的结果,这就限制了整个系统的能力上限:

image-20260211141202752

OneRec致力于使用端到端的模型取代传统的级联推荐系统,而不仅仅满足于TIGER那种仅用于召回阶段的生成式模型。OneRec模型是Encoder-Decoder的架构,为了scale模型参数在decoder中使用了MoE,其输入用户历史行为序列并逐步解码出用户还可能感兴趣的新视频。为了避免逐个生成下一个视频导致还需要手工设计规则来重排组合这些生成结果,其抛弃了传统的单点的next-item prediction,使用session-wise list generation来生成一个list的高质量视频,让模型自己学习最优的session结构,从而端到端地模拟整个召回-精排-重排的过程,可以直接将生成的session推送给用户。另外,还引入了DPO来进一步增强生成结果的质量,使得模型能以更高概率生成用户偏好的session。

 

Prelim —— RQ-KMeans

RQ-KMeans本质上和TIGER中对于RQ-VAE的codebook的KMeans初始化过程类似。但RQ-VAE依赖于模型训练,其优化目标包括重建与量化损失,实践中还是容易导致码本坍塌问题(hourglass phenomenon,大部分SID集中于少量codes,其他codes几乎不会被用到)。

因此,OneRec等工作采用RQ-KMeans来构造SID,其同样采用逐层残差结构。只不过每层的codebook是直接通过训练数据做聚类得到的,而不是通过学习得出来的。

设某个输入视频i的多模态表征向量eiRd,初始化残差为ri1=ei,然后在每一层的codebook中选取最近的code作为该层给出的id sil,然后求该层输入和选中的code之间的新残差作为下一层输入,然后再在下一层codebook中选取和这个新残差最接近的code......直到通过所有L层后,将每层选取的code的id都收集并组合起来,即为该视频的SID:

si1=argmink||ri1ck1||22,  ri2=ri1csi11si2=argmink||ri2ck2||22,  ri3=ri2csi22siL=argmink||riLckL||22SIDi=(si1,si2,,siL)

在构建codebook时,对于第l层,使用Balanced K-means构造其codebook:

将上述过程迭代直到收敛,最终得到的那K个聚类中心就构成了第l层的codebook:

Cl={c1l,,cKl}

image-20260115151914586

RQ-KMeans构造出的SID通常分布更均匀,具有较强的区分性,码本坍塌问题更少,整体上更适合自回归生成任务。但不同物品的SID碰撞问题相对更多。

 

SID的构造:

对于用户侧特征,OneRec将正样本用户历史行为序列Hu={v1h,,vnh}作为输入,其中每个v都是用户有效观看或进行正向回应的视频,n为行为序列长度。模型输出是一个session的视频列表S={v1,,vm},其中m为一个session的视频数量。在实践中,OneRec中取n=256个历史行为作为历史行为序列,取m=5作为一个session的视频数量。

对于每个视频vi来说,通过多模态embedding eiRd来描述它。由于RQ-VAE存在码本不平衡问题,因此采用Balanced RQ-KMeans来将embedding转化为SID:(si1,,siL)。在实践中,每层的codebook含有8192个cluster,共有L=3层,可见code空间总共有81923550B种组合

 

Session-wise List Generation:

一个session的定义是用户一次请求后返回的一批视频,通常是m=510个。一个session中的视频考虑了用户兴趣、连贯性、多样性等综合的因素,在传统级联系统中即为重排后的结果。一个高质量的session应满足如下条件:一个session中用户观看了的视频应至少5个、用户在该session中的总观看时长超过某个阈值、用户对于其中的视频进行了点赞等正向互动。

session-wise list generation的模型M的目标可以写成:

S=M(Hu)

其中,Hu表示输入历史序列中n个视频{v1h,,vnh}的SID表示:

Hu={(s11,,s1L),,(sn1,,snL)}

S为输出的一个session中的m个视频的SID表示:

S={(s11,,s1L),,(sm1,,smL)}

image-20260211143238100

模型本身是Encoder-Decoder结构,其中Encoder输入历史序列Hu,通过多头自注意力+FFN来建模用户历史交互信息。经过encoder处理后的输入历史序列表征为H

H=Encoder(Hu)

Decoder用于自回归地输出target session的SID。为了扩展模型参数,其中的FFN换成了MoE结构。实验中设置每层有NMoE=24个experts,激活数量为KMoE=2

在训练时,训练数据中用于学习预测的ground truth高质量session被输入decoder中,且每个视频的SID之前都添加一个特殊的s[BOS] token来进行标识,得到训练时decoder的输入:

S¯={s[BOS],s11,,s1L,s[BOS],s21,,s2L,,s[BOS],sm1,,smL}

训练的loss即为在这个输入序列上做NTP Loss,也即预测生成这个session。

推理时Encoder的输入是已知的用户历史序列,Decoder的输入是一个BOS token,来自回归地生成下一个session中的一系列视频的SID。

线上实验使用的是OneRec-1B模型

 

DPO偏好调整:

为了进一步加强模型生成高质量session的能力,在上一步预训练模型的基础上进一步使用DPO。

在NLP中,可以使用人类标注的偏好数据。然而在推荐系统中稀疏的用户与物品交互数据带来了挑战,没办法获得那么多直接由人类交互得到的偏好数据。因此首先需要训练一个奖励模型来预测用户对于一个session的偏好程度,从而代替DPO中通过人类标注来构造偏好数据的过程,自动化地构造大量的偏好数据用于DPO训练

也即,这里训练的奖励模型的作用只是代替人类标注生成偏好数据,然后进一步拿这些偏好数据去做DPO,并不是直接作为RL的训练目标。DPO的目标是直接微调模型使得其以更大概率生成偏好的样本,而不是以生成能拿到更高奖励的样本作为直接目标(虽然最终优化结构也在某种程度上间接地达成了这个目标)。

考虑4种指标来反映用户对于一个session的偏好程度(奖励分数):

奖励模型的训练目标就是能够在给定用户和某个session时能够精准预测上述指标。奖励模型本质上类似于传统推荐中的精排模型——给定用户和候选session,输出该候选session的得分(类比于CTR等指标,只不过这里换成一些短视频相关的指标)。

R(u,S)表示一个奖励模型,它返回的奖励分数r代表了用户u(通常使用用户历史行为序列来代表)对于session S={v1,,vm}的偏好程度。为了得到target-aware的候选session的表征,类似使用target attention机制的精排模型,对于候选session中的每个视频vi,首先使用它的embedding和用户历史序列中各个item的embedding做一个target-aware的操作(例如对于用户行为做target attention):

ei=viu

这样就可以得到候选session中各个视频的target-aware表征h={e1,,em}

然后,通过一个自回归层来在session内部的各个视频间进行交互:

hf=SelfAttention(hWsQ,hWsK,hWsV)

最后,将session中各个视频处理后的表征相加得到这个session的总表征向量Sum(hf),然后将其分别送入4个MLP任务塔Tower()=Sigmoid(MLP()),分别预测上述4个指标分数:

r^swt=Towerswt(Sum(hf))r^vtr=Towervtr(Sum(hf))r^wtr=Towerwtr(Sum(hf))r^ltr=Towerltr(Sum(hf))

训练数据中的session是已知上述4个指标的ground truth真实label值的,因此可以使用BCELoss作为目标来使得奖励模型的预测结果和真实结果尽可能接近:

LRM=xtr=swt,vtr,wtr,ltr(yxtrlog(r^xtr)+(1yxtr)log(1r^xtr))

得到训好的奖励模型R(u,S)后,下一步即可基于预训练模型Mt(类比NLP DPO流程中SFT后的LLM)生成大量数据并打分得到有标注的偏好数据。具体而言,使用预训练模型Mt为每个用户u(context为历史交互序列Hu)通过beam search生成N个session,然后使用奖励模型给这些session进行打分,并把其中得分最高的session Suw和得分最低的session Sul作为正样本和负样本构成一个样本对:Dtpair=(Suw,Sul,Hu)。然后即可将其用于模型的DPO优化:

LDPO(Suw,Sul|Hu)=logσ(βlogMt+1(Suw|Hu)Mt(Suw|Hu)βlogMt+1(Sul|Hu)Mt(Sul|Hu))

实际的训练过程采用了Iterative Preference Alignment(IPA),把NTP预训练和DPO过程穿插进行,逐步迭代多版模型(类似于PPO那种多轮迭代)。具体而言,首先单独进行NTP预训练并在t时刻得到收敛的预训练模型Mt,然后进一步实行若干步的DPO优化迭代,得到一系列模型Mt+1,Mt+2,,MT。每一步迭代时使用上一步的旧模型(相当于PPO里的πold)生成偏好样本。