pinterest在《TransAct: Transformer-based Realtime User Action Model for Recommendation at Pinterest》提出了它们的排序模型。

摘要

用于预测下一个动作的编码用户活动的序列模型,已成为构建大规模个性化推荐系统的一种流行设计选择。传统的序列推荐方法要么利用实时用户行为的端到端学习,要么以离线批处理生成的方式单独学习用户表示。本文:

  • (1)介绍了Pinterest的Homefeed排序架构,这是我们的个性化推荐产品和最大的参与度表面;
  • (2)提出了TransAct,一个从用户实时活动中提取短期偏好的序列模型
  • (3)描述了我们的混合排序方法,该方法结合了通过TransAct的端到端序列建模批生成的用户embedding

混合方法使我们能够结合直接在实时用户活动上学习的反应性优势和批用户表示的成本效益,这些用户表示是在更长时间内学习的。

我们描述了消融研究的结果,在产品化过程中面临的挑战,以及在线A/B实验的结果,这些验证了我们混合排序模型的有效性。我们进一步证明了TransAct在其他表面如上下文推荐和搜索方面的有效性。我们的模型已部署在Pinterest的Homefeed、相关Pin、通知和搜索中。

1 引言

近年来在线内容的激增为用户导航创造了压倒性的信息量。为了解决这个问题,推荐系统被用于各种行业,帮助用户从大量选择中找到相关item,包括产品、图片、视频和音乐。通过提供个性化推荐,企业和组织可以更好地服务用户,并保持他们对平台的参与。因此,推荐系统对企业至关重要,因为它们通过提高参与度(engagement)、销售和收入来推动增长。

作为最大的内容分享和社交媒体平台之一,Pinterest拥有数十亿个Pin,拥有丰富的上下文和视觉信息,为超过4亿用户提供灵感。

访问Pinterest时,用户会立即看到图1所示的Homefeed页面,这是主要的灵感来源,占平台总用户参与度的大部分。Homefeed页面由一个3阶段的推荐系统驱动,该系统根据用户兴趣和活动检索、排序和混合内容。在检索阶段,我们根据用户兴趣、关注的板块等多种因素,从Pinterest上创建的数十亿个Pin中筛选出数千个。然后我们使用pointwise排序模型通过预测它们对用户的个性化相关性来对候选Pin进行排序。最后,使用混合层调整排序结果以满足业务需求。

图片名称

图1 Pinterest Homefeed页

实时推荐至关重要,因为它为用户提供快速和最新的推荐,改善了他们的整体体验和满意度。集成实时数据,如最近的用户行为,可以更准确地推荐,并增加用户发现相关item的可能性[4, 21]。更长的用户行为序列可以改善用户表示,从而提高推荐性能。然而,使用长序列进行排序对基础设施提出了挑战,因为它们需要大量的计算资源,并可能导致延迟增加。为了解决这一挑战,

  • 一些方法已经利用哈希和最近邻搜索在长用户序列中[21]
  • 其他工作将用户过去的行为编码为用户嵌入[20],以表示长期用户兴趣。用户嵌入特征通常作为batch特征生成(例如,每天生成),在多个应用中以低延迟服务是成本效益的。

现有序列推荐的局限性在于:它们要么只使用实时用户行为,要么只使用从长期用户行为历史中学习的batch用户表示。

我们引入了一种新颖的实时-批量混合(realtime-batch hybrid)的排序方法,结合了实时用户行为信号和batch用户表示。为了捕捉用户的实时行为,我们提出了TransAct:

  • 一个基于transformer的新模块,旨在编码最近的用户行为序列并理解用户的即时偏好
  • 对于在较长时间内发生用户行为,我们将它们转换为批用户表示[20]

通过结合TransAct的表现力和批用户embedding,这种混合排序模型为用户提供了他们最近行为的实时反馈,同时也考虑了他们的长期兴趣。实时组件和batch组件互补推荐准确性。这导致Homefeed页面上用户体验的整体改善。

本文的主要贡献总结如下:

  • 我们描述了Pinnability,Pinterest的Homefeed生产排序系统的架构。Homefeed个性化推荐产品占Pinterest总用户参与度的大部分。
  • 我们提出了TransAct:一个基于transformer的实时用户行为序列模型,有效地从用户最近的行动中捕获用户的短期兴趣。我们证明了将TransAct与每天生成的用户表示[20]结合到混合模型中,在Pinnability中实现了最佳性能。这种设计选择通过全面的消融研究得到了证明。我们的代码实现是公开可用的1。
  • 我们描述了在Pinnability中实施的服务优化,使得在引入TransAct到Pinnability模型时,计算复杂度增加了65倍成为可能。具体来说,优化是为了使我们以前的基于CPU的模型能够在GPU上服务。
  • 我们描述了使用TransAct在现实世界推荐系统上的在线A/B实验。我们展示了在线环境中的一些实际问题,如推荐多样性下降和参与度衰减,并提出了解决这些问题的方案。

本文的其余部分组织如下:第2节回顾相关工作。第3节描述了TransAct的设计及其生产细节。实验结果在第4节报告。我们在第5节讨论了一些超出实验的发现。最后,我们在第6节总结我们的工作。

2 相关工作

2.1 推荐系统

协同过滤(CF)[12, 18, 24]基于这样的假设进行推荐:用户会偏好其他相似用户喜欢的物品。它使用用户行为历史来计算用户和物品之间的相似性,并基于相似性推荐物品。这种方法受到用户-物品矩阵稀疏性的困扰,并且无法处理从未与任何物品互动过的用户。另一方面,因子分解机[22, 23]能够处理稀疏矩阵。

最近,深度学习(DL)已被用于点击率(CTR)预测任务。例如:

  • 谷歌使用Wide & Deep [5]模型进行应用推荐。wide组件通过捕获特征之间的交互来实现记忆,而deep组件通过使用前馈网络学习分类特征的嵌入来帮助泛化。
  • DeepFM [7]通过自动学习低阶和高阶特征交互进行了改进。
  • DCN [34]及其升级版本DCN v2 [35]都旨在自动建模显式特征交叉。

上述推荐系统在捕捉用户的短期兴趣方面表现不佳,因为只利用了用户的静态特征。这些方法也倾向于忽略用户行为历史中的序列关系,导致用户偏好的表示不足。

2.2 序列推荐

为了解决这个问题,序列推荐在学术界和工业界都得到了广泛研究。序列推荐系统使用用户的行为历史作为输入,并应用推荐算法向用户推荐适当的物品。序列推荐模型能够在长时间内捕捉用户的长期偏好,类似于传统推荐方法。此外,它们还有一个额外的好处,即能够考虑到用户兴趣的演变,从而实现更高质量的推荐。

序列推荐通常被视为下一个物品预测任务,目标是基于用户过去的行为序列预测用户的下一个行动。我们在编码用户过去的行为到dense表示方面受到了先前序列推荐方法[4]的启发。一些早期的序列推荐系统使用机器学习技术,如马尔可夫链[8]和基于会话的K最近邻(KNN)[11]来模拟用户行为历史中交互的时间依赖性。这些模型因为仅通过组合不同会话的信息而无法完全捕捉用户的长期模式而受到批评。最近,深度学习技术,如循环神经网络(RNN)[25]在自然语言处理中取得了巨大成功,并在序列推荐中变得越来越流行。因此,许多基于DL的序列模型[6, 9, 30, 42]使用RNNs取得了出色的性能。卷积神经网络(CNNs)[40]广泛用于处理时间序列数据和图像数据。在序列推荐的背景下,基于CNN的模型可以有效地学习用户最近交互的一组物品内的依赖性,并相应地进行推荐[31, 32]。

注意力机制起源于神经机器翻译任务,该任务模拟输入句子的不同部分对输出词的重要性[2]。自注意力是一种已知的机制,用于衡量输入序列的不同部分的重要性[33]。已经有更多推荐系统使用注意力[43]和自注意力[4, 13, 16, 27, 39]。

许多先前的工作[13, 16, 27]仅使用公共数据集进行离线评估。然而,在线环境更具挑战性和不可预测性。由于问题表述的差异,我们的方法与这些工作不直接可比。我们的方法类似于点击率(CTR)预测任务。深度兴趣网络(DIN)使用注意力机制在CTR预测任务中模拟用户过去行为的依赖性。阿里巴巴的行为序列transformer(BST)[4]是DIN的改进版本,与我们的工作密切相关。他们提出使用transformer从用户行为中捕捉用户兴趣,强调行为顺序的重要性。然而,我们发现位置信息并没有增加太多价值。我们发现其他设计,如更好的早期融合和行为类型嵌入,在处理序列特征时是有效的。

3 方法论

在本节中,我们介绍了TransAct,我们的实时-batch混合排序模型。我们将从Pinterest Homefeed排序模型Pinnability的概述开始,然后描述如何使用TransAct在Pinnability中编码实时用户行为序列特征以进行排序任务。

3.1 预备知识:Homefeed排序模型

在Homefeed排序中,我们将推荐任务建模为pointwise多任务预测问题,可以定义如下:给定用户 $ u $ 和Pin $ p $,我们构建一个函数来预测用户 $ u $ 对候选Pin $ p $ 执行不同动作的概率。不同动作的集合包含正面和负面动作,例如点击、保存和隐藏。

我们构建了Pinnability,Pinterest的Homefeed排序模型,来解决上述问题。高层架构是Wide and Deep学习(WDL)模型[5]。Pinnability模型利用各种类型的输入信号,如用户信号、Pin信号和上下文信号。这些输入可以以不同的格式出现,包括类别型、数值型和嵌入型特征。

  • 我们使用嵌入层(embedding layer)将类别型特征投影到dense特征,并在数值型特征上执行batch归一化
  • 然后,我们应用一个全秩DCN V2[35]的特征交叉来显式建模特征交互
  • 最后,我们使用具有一组输出动作头 $ H = \lbrace h_1, h_2, …, h_k \rbrace $ 的全连接层来预测用户对候选Pin $ p $ 的动作。每个头对应一个动作

如图2所示,我们的模型是一个实时-batch混合模型,通过实时(TransAct)和batch(PinnerFormer)方法编码用户行为历史特征,并针对排序任务[37]进行优化。

图片名称

图2 Pinterest Homefeed ranking model (Pinnability)

每个训练样本是 (x, y),其中:

  • x 表示一组特征,
  • $ y \in \lbrace 0, 1 \rbrace^{ \mid H \mid} $,y中的每个条目对应于H中动作头的label。

Pinnability的loss函数是一个加权交叉熵损失,旨在优化多标签分类任务。我们将损失函数公式化为:

\[L = w_u \sum_{h \in H} \left\{ -w_h [y_h \log f(x)_h + (1 - y_h) (1 - \log f(x)_h)] \right\}\]

…(1)

其中:

  • $ f(x) \in (0, 1)^H $,$ f(x)_h $ 是头 $ h $ 的输出概率。
  • $ y_h \in \lbrace 0, 1\rbrace $ 是头 $ h $ 的真实标签。
  • 权重 $ w_h $ 应用于每个头的输出 $ f(x)_h $ 的交叉熵。
  • $ w_h $ 是根据真实标签 y 和标签权重矩阵 $ M \in \mathbb{R}^{\mid H \mid \times \mid H \mid} $ 计算的:
\[w_h = \sum_{a \in H} M_{h,a} \times y_a\]

标签权重矩阵 $ M $ 作为每个动作对每个头损失项贡献的控制因素。注意,如果 M 是对角矩阵,方程(1)简化为标准的多头二元交叉熵损失。但是选择根据经验确定的标签权重 M 可以显著提高性能

此外,每个训练样本都由用户依赖的权重 $ w_u $ 加权,这由用户属性决定,如用户状态、性别和位置。我们通过乘以用户状态权重、用户性别权重和用户位置权重来计算 $ w_u $:

\[w_u = w_{\text{state}} \times w_{\text{location}} \times w_{\text{gender}}\]

这些权重根据特定业务需求进行调整。

3.2 实时用户行为序列特征

用户过去的行为历史自然是一个可变长度特征——不同用户在平台上的过去行为数量不同。 尽管更长的用户行为序列通常意味着更准确的用户兴趣表示,但实际上,包含所有用户行为是不可行的。因为获取用户行为特征和执行排序模型推理所需的时间也可能大幅增长,这反过来又会影响用户体验和系统效率。考虑到基础设施成本和延迟要求,我们选择包含每个用户最近的100个行为序列。对于少于100个行为的用户,我们用0填充特征到100的长度。用户行为序列特征按时间戳降序排序,即第一个条目是最近的行为

用户行为序列中的所有行为都是Pin级别的行为。对于每个行为,我们使用三个主要特征:

  • 行为的时间戳
  • 行为类型
  • Pin的32维PinSage嵌入[38]:PinSage是一个紧凑的embedding,编码了Pin的内容信息

3.3 我们的方法:TransAct

与静态特征不同,实时用户行为序列特征 $ S(u) = [a_1, a_2, …, a_n] $ 是使用一个名为TransAct的专用子模块处理的。TransAct从用户的历史行为中提取序列模式,并预测 $ (u, p) $ 相关性分数。

3.3.1 特征编码

用户参与的Pin的相关性,可以通过用户行为历史中对它们采取的行动类型来确定。例如:

  • 通常认为用户保存到自己看板的Pin比仅查看的Pin更相关。
  • 如果Pin被用户隐藏,相关性应该非常低。

为了纳入这一重要信息,我们使用可训练的嵌入表将行动类型投影到低维向量。用户行为类型序列随后被投影到用户行为嵌入矩阵 $ W_{\text{actions}} \in \mathbb{R}^{\mid S \mid \times d_{\text{action}}} $,其中 $ d_{\text{action}} $ 是行动类型嵌入的维度。

如前所述,用户行为序列中的Pin内容由PinSage嵌入[38]表示。因此,用户行为序列中所有Pin的内容是一个矩阵 $ W_{\text{pins}} \in \mathbb{R}^{\mid S \mid \times d_{\text{PinSage}}} $。最终编码的用户行为序列特征是$CONCAT (W_{actions} \ , W_{pins}) \in \mathbb{R}^{\mid S \mid \times (d_{PinSage} + d_{action})} $。

3.3.2 早期融合(early fusion)

直接在排序模型中使用用户行为序列特征的一个独特优势是,我们可以显式地建模候选Pin和用户参与的Pin之间的交叉。早期融合(early fusion)在推荐任务中指的是在推荐模型的早期阶段合并用户和物品特征。通过实验,我们发现早期融合是提高排序性能的重要因素。评估了两种早期融合方法:

  • append:将候选Pin的PinSage embedding附加到用户行为序列作为序列的最后一项,类似于BST[4]。使用零向量作为候选Pin的虚拟动作类型
  • concat:对于用户行为序列中的每个动作,将候选Pin的PinSage embedding与用户行为特征连接起来。

我们根据离线实验结果选择concat作为我们的早期融合方法。早期融合的结果序列特征是:一个2维矩阵 $ U \in \mathbb{R}^{\mid S \mid \times d} $,其中 $ d = (d_{\ action} \ + 2d_{\ PinSage}) $。

3.3.3 序列聚合模型

准备好用户行为序列特征 $ U $ 后,下一个挑战是:有效地聚合用户行为序列中的所有信息以表示用户的短期偏好。工业中用于序列建模的一些流行模型架构包括CNN[40]、RNN[25]和最近的transformer[33]等。我们尝试了不同的序列聚合架构,并选择了基于transformer的架构。我们采用了标准transformer编码器,有2个编码器层和一个头。前馈网络的隐藏维度表示为 $ d_{\text{hidden}} $。这里不使用位置编码,因为我们的离线实验表明位置信息是无效的。

3.3.4 随机时间窗口掩码

在用户的所有最近行为上训练可能会导致兔子洞效应(rabbit hole effect),即模型推荐与用户最近参与内容相似的内容。这会损害用户Homefeed的多样性,对长期用户留存有害。为了解决这个问题,我们使用用户行为序列的时间戳构建transformer编码器的时间窗口掩码。该掩码在自注意力机制应用之前过滤掉输入序列中的某些位置。在每次前向传递中,从0到24小时均匀采样一个随机时间窗口 $ T $。在 $ (t_{\text{request}} - T, t_{\text{request}}) $ 内的所有行为都被掩码,其中 $ t_{\text{request}} $ 代表接收排序请求的时间戳。重要的是要注意,随机时间窗口掩码仅在训练期间应用,而在推理时不使用掩码。

3.3.5 transformer输出压缩

transformer编码器的输出是一个矩阵:$ O = (o_0 : o_{\mid S \mid -1}) \in \mathbb{R}^{\mid S \mid \times d} $。我们只取前K列($ o_0 : o_{K-1} $),将它们与最大池化向量 $ \text{MAXPOOL}(O) \in \mathbb{R}^d $ 连接起来,然后将其展平为一个向量 $ \mathbf{z} \in \mathbb{R}^{(K+1) \times d} $。前 $ K $ 列输出捕获了用户最近的兴趣,而 $ \text{MAXPOOL}(O) $ 表示用户对 $ S(u) $ 的长期偏好。由于输出足够紧凑,它可以很容易地使用DCN v2[35]特征交叉层集成到Pinnability框架中。

图片名称

图3 TransAct架构是一种可以插入到任何类似架构中的子模块,比如Pinnability。

3.4 模型产品化

3.4.1 模型重新训练

对于推荐系统来说,重新训练很重要,因为它允许系统不断适应用户行为和偏好随时间的变化。没有重新训练,推荐系统的性能会随着用户行为和偏好的变化而降低,导致推荐准确性下降[26]。当我们在排序中使用实时特征时,这一点尤其正确。模型对时间更敏感,需要频繁重新训练。否则,模型可能在几天内变得过时,导致预测准确性降低。我们每周从头开始重新训练Pinnability两次。我们发现这种重新训练频率对于确保一致的参与率和保持可管理的训练成本至关重要。我们将在第4.4.3节深入探讨重新训练的重要性。

3.4.2 GPU服务

带有TransAct的Pinnability在浮点运算方面比其前身复杂65倍。如果没有模型推理的突破,我们的模型服务成本和延迟将增加相同的规模。GPU模型推理允许我们以中性的延迟和服务成本提供带有TransAct的Pinnability。

在GPU上提供Pinnability的主要挑战是CUDA内核启动开销。在GPU上启动操作的CPU成本非常高,但它通常被延长的GPU计算时间所掩盖。然而,这对于Pinnability GPU模型服务有两个问题。首先,Pinnability和推荐模型通常处理数百个特征,这意味着有大量的CUDA内核。其次,在线服务期间的batch大小很小,因此每个CUDA内核需要的计算量很少。有了大量小CUDA内核,启动开销比实际计算更昂贵。我们通过以下优化解决了技术挑战:

  • 合并CUDA内核。一个有效的方法是尽可能合并操作。我们利用标准深度学习编译器,如nvFuser7,但通常发现需要人为干预许多剩余操作。一个例子是我们的嵌入表查找模块,它由两个计算步骤组成:原始ID到表索引查找和表索引到嵌入查找。由于特征数量众多,这个过程需要重复数百次。我们通过利用cuCollections8支持GPU上的原始ID哈希表,并实现自定义的合并嵌入查找模块,将多个特征的查找合并为一次查找,从而将与稀疏特征相关的数百个操作减少为一个。

  • 合并内存拷贝。每次推理时,数百个特征被作为单独的张量从CPU复制到GPU内存。调度数百个张量拷贝的开销成为瓶颈。为了减少张量拷贝操作的数量,我们在将它们从CPU传输到GPU之前,将多个张量合并为一个连续的缓冲区。这种方法减少了单独传输数百个张量的调度开销,改为传输一个张量。

  • 形成更大的批次。对于基于CPU的推理,更小的批次更受欢迎,以增加并行性和减少延迟。然而,对于基于GPU的推理,更大的批次更有效[29]。这导致我们重新评估我们的分布式系统设置。最初,我们使用scatter-gather架构将请求分割成小批次,并在多个叶节点上并行运行它们以获得更好的延迟。然而,这种设置与基于GPU的推理不兼容。相反,我们直接使用原始请求中的更大批次。为了补偿缓存容量的损失,我们实现了一个使用DRAM和SSD的混合缓存。

  • 利用CUDA图。我们依靠CUDA图9来完全消除剩余的小操作开销。CUDA图将模型推理过程捕获为操作的静态图,而不是单独调度的操作,允许计算作为一个单独的单元执行,没有任何内核启动开销。

3.4.3 实时特征处理

当用户采取行动时,基于Flink10的实时特征处理应用程序会消费前端事件生成的用户行为Kafka11流。它验证每个行动记录,检测并合并重复项,并管理多个数据源的任何时间差异。然后,应用程序将特征具体化并存储在Rockstore[3]中。在服务时间,每个Homefeed日志/服务请求触发处理器将序列特征转换为模型可以使用的格式。

4.实验

附录

https://arxiv.org/pdf/2306.00248

pinterest在《PinnerFormer: Sequence Modeling for User Representation at Pinterest》提出了它们的PinnerFormer方法:

摘要

近年来,序列模型在个性化推荐系统中变得越来越流行。这些传统的方法将用户在网站上的行为建模为一个序列,以预测用户的下一个行为。虽然理论上简单,但这些模型在生产环境中部署起来相当具有挑战性,通常需要流式基础设施来反映最新的用户活动,并可能管理可变数据以编码用户的隐藏状态。在这里,我们介绍了 PinnerFormer,这是一个训练用来预测用户未来长期参与度的用户表示,它基于用户近期行为的序列模型。与之前的方法不同,我们通过我们的新密集全动作损失(dense all-action loss)适应批量基础设施,模拟长期未来行为而不是下一个行为预测。我们展示了这样做可以显著缩小每天生成一次的批量用户嵌入和用户采取动作时生成的实时用户嵌入之间的差距。我们通过广泛的离线实验和消融研究来描述我们的设计理念,并在 A/B 实验中验证了我们方法的有效性,与我们之前用户表示相比,PinnerFormer 在 Pinterest 的用户留存和参与度方面显示出了显著的改进。PinnerFormer 自 2021 年秋季起已在生产环境中部署。

1 引言

每月有超过4亿用户使用Pinterest来从我们数十亿的Pins内容库中发现想法和灵感。一个Pin通常以一张图片开始,经常包括文本、一个网页链接和一个板子,将单个Pin连接到用户策划的Pins集合中。灵感是Pinterest的关键,主要通过我们的搜索和推荐系统实现,使用户能够通过:

  • (a) Homefeed,我们的个性化推荐产品,
  • (b) Related Pins,与查询Pin相关的推荐,
  • (c) Search,与用户文本查询相关的推荐来找到内容

用户通过保存Pins到板子(Repin)、点击底层链接、放大一个Pin(特写)、隐藏不相关内容等互动方式给出反馈。为了实现我们让每个人都能得到创造他们所爱生活灵感的使命,我们需要根据用户的兴趣和上下文个性化我们的内容,考虑到用户在Pinterest旅程中给出的反馈;即,我们需要对我们的用户有一个强大的表示。

学习user embedding(表示)已成为提高推荐质量的越来越流行的方法。这种嵌入已被采用以推动排名和候选生成在行业中,被用来在YouTube[6]、Google Play[26]、Airbnb搜索[8]、JD.com搜索[30]、Alibaba[12, 18]等多个平台上推动个性化推荐。除了学习个性化嵌入的工作外,还有一系列工作集中在直接使用序列信息构建排序模型[4, 18, 19, 31],使推荐基于用户最近的参与度进行个性化。

用户在网站上的行为往往是顺序性的;动作可以按照他们被采取的时间来排序,这自然导致了序列建模方法。已经有多种方法被提出来基于用户的历史互动序列预测未来的参与度[3, 9, 17, 20, 21]。更近的工作已经应用了各种深度学习模型,包括循环神经网络(RNN)和变换器(transformers)来进行这种序列推荐,并取得了有希望的结果[3, 7, 9, 10, 21, 25, 29]。序列模型传统上专注于实时设置,旨在从所有导致该点的动作中预测用户的下一个动作或参与度。

在实践中,将现有的序列建模方法部署到大型网络规模应用中存在两个关键挑战:

  • (a) 计算成本
  • (b) 基础设施复杂性

现有的序列建模方法大致分为两类:无状态模型有状态模型。无状态模型可能具有高计算成本,因为必须在用户采取的每个动作之后从头开始计算嵌入,而有状态模型需要健壮可靠的流式基础设施来处理给定用户模型状态中的潜在错误或数据损坏[18]。

在这里,我们介绍了PinnerFormer,这是一个在Pinterest生产环境中部署的端到端学习的用户表示。与先前关于序列用户建模的工作类似,PinnerFormer直接基于用户过去的Pin参与度学习表示。我们提出了一个密集全动作损失(dense all-action loss),这使我们的嵌入能够捕捉用户的长期兴趣,而不仅仅是预测下一个动作。这使我们的embedding可以在离线、批量设置中计算,并大大简化了基础设施

我们还解决了Pinterest中表现的基础设施复杂性挑战:有数十个排序模型可以从个性化中受益,但为每个模型开发定制解决方案是不可行的。我们选择不针对每个模型生产一个用户嵌入(这将增加复杂性),而是投资于开发一个可以用于多个下游任务的单一高质量用户嵌入。尽管在某些情况下可能会牺牲特定任务的性能,但对于大多数用例来说,复杂性权衡使得共享嵌入更受欢迎。

我们在离线和在线A/B实验中评估PinnerFormer。在离线实验中,我们展示了这种训练目标几乎将每日推断模型和实时推断模型之间的性能差距减半,并且比其他方法更好地反映了用户的长期兴趣。然后,我们展示了PinnerFormer作为特征的效用,证明当它作为多个不同领域排序模型中的特征使用时,它能够实现显著的在线收益。

2 设计选择

我们首先讨论PinnerFormer中的关键设计选择。

设计选择1:单个用户使用单个还是多个嵌入。 大多数生成用户表示的方法产生单个嵌入[3, 7, 9, 10, 21, 25, 29],但有些专注于学习固定或可变数量的用户嵌入[12, 13, 17, 24]。在我们之前用户表示PinnerSage中,我们决定允许一个可变的数量,可能是大量的嵌入,允许模型明确表示用户的多样化兴趣[17]。

尽管使用多个嵌入可以让模型更明确地捕捉用户兴趣,并且在检索中表现良好,但这在使用下游模型时可能会导致问题:在训练数据中存储20+个256维float16嵌入并不具有很好的扩展性,特别是当数据集可能包含数十亿行时,正如排序模型中的情况。此外,这也增加了模型训练和推理的成本;处理5000+个浮点数可能会引入非微不足道的延迟,特别是如果它们在聚合前被转换。在训练时,大型样本也可以增加加载数据所需的时间。为了避免这些问题,在使用PinnerSage进行排序模型时,我们通常会使用用户嵌入的加权聚合作为最终用户表示。因为我们希望PinnerFormer能够轻松用作特征,我们产生一个捕获用户兴趣的单个嵌入,允许在下游模型中无痛使用。在离线评估中,我们展示了我们的单个嵌入能够比PinnerSage更好地反映用户的长期兴趣,同时只需要一小部分存储空间。

设计选择2:实时与离线推理。 大多数关于序列用户建模的先前工作集中在实时或近实时操作的模型上。在实践中,这至少会导致以下之一:

  • 高计算成本: 对于用户采取的每一个动作,系统必须获取用户历史中的所有事件,并经常推断一个可能复杂的模型。
  • 高基础设施复杂性: 用户的隐藏状态或嵌入可以逐步更新,但这需要一个健壮的系统来恢复和预热模型的状态,以防任何数据损坏[18]。

在Pinterest,用户可能在一天内采取数十或数百个动作,因此一个每天最多更新一次用户嵌入的模型只需要同等规模实时模型计算资源的一小部分。在离线评估中,我们展示了我们的损失函数显著减少了实时和每日推断模型之间的差距,并且在A/B实验中,我们展示了PinnerFormer极大地提高了下游排序模型的性能。

3 我们的方法:PinnerFormer

在本节中,我们介绍了自2021年秋季以来在Pinterest生产环境中使用的PinnerFormer,描述了我们的模型(如图1所示)及其部署方式。

图片名称

图1 PinnerFormer架构的概览如下:特征通过带有因果掩蔽的transformer传递,并且在每个timestep返回embedding。需要注意的是,训练窗口(28天)超过了我们未来评估目标窗口(14天)

我们从:

  • 一个庞大的Pins语料库:$P = \lbrace 𝑃_1, 𝑃_2, \cdots, 𝑃_𝑁 \rbrace$,其中:𝑁非常大,大约有数十亿
  • 一组用户:$U = \lbrace 𝑈_1, 𝑈_2, \cdots \rbrace$,其中:$\mid U \mid > 500M$。
  • 对于语料库中的每个Pin,我们有一个PinSage embedding: $𝑝_𝑖 \in R^{256}$,这是Pin $𝑃_𝑖$的视觉、文本和参与度信息的聚合。
  • 对于每个用户,我们有一个用户在网站上采取的动作序列:$A_𝑈 = {𝐴_1, 𝐴_2, …, 𝐴_𝑆}$,按时间戳升序排列。

在这项工作中,我们将动作序列限制为用户对Pins的参与,包括过去一年中对Pin的保存、点击、反应和评论。基于这个假设,动作可以由PinSage嵌入表示,以及一些关于动作的元数据。实际上,对于给定的用户,𝑆可能非常大,对于某些用户来说可能是数千或数万,因此我们使用用户的M个最新动作来计算用户的嵌入。

给定这些定义,我们的目标是:学习一个用户表示$𝑓 : U → R^d$,与某些Pin表示$𝑔 : P → R^d$在余弦相似性下兼容。我们联合学习𝑓和𝑔,使用动作序列$A_𝑈$作为模型的唯一输入特征,并限制为仅最新的M个。

在一个用户的完整动作序列中,可能有许多类型的动作,其中一些是正向的(例如长时间点击),而另一些是中性的或负向的(例如隐藏或短时间点击)。在这项工作中,我们专注于学习预测正向参与的表示,我们将其定义为Pin保存(”Repin”)、持续超过10秒的Pin特写(”Closeup”)或对Pin下链接的长时间点击(>10s)(”Click”)。我们只将Homefeed上的参与视为正向的;在搜索或相关Pins等表面上,查询提供了大量上下文,而在Homefeed上,用户提供了主要的上下文。

我们的主要目标是:学习一个模型,能够预测用户在生成嵌入后的14天内的未来正向参与,而不是传统的序列建模任务,后者的嵌入只会预测下一个动作。换句话说,我们的目标是:学习嵌入$𝑢_𝑖$和$𝑝_𝑖$,使得如果$𝑑(𝑢_𝑘, 𝑝_𝑖) < 𝑑(𝑢_𝑘, 𝑝_𝑗)$,则$𝑝_𝑖$比$𝑝_𝑗$更有可能被$𝑢_𝑘$代表的用户在生成$𝑢_𝑘$后的14天内正向参与。我们选择14天的范围是为了可行性,并假设用户在两周内采取的动作足以代表用户的长期兴趣。图1展示了PinnerFormer架构,我们将在下面更详细地展开每个组件。

3.1 特征编码

对于用户序列中的每个动作,我们有一个PinSage嵌入(256维)[28]和元数据特征:动作类型(action type)、表面(surface)、时间戳(timestamp)和动作持续时间(action duration)。我们使用小型可学习的嵌入表来编码动作类型和表面,这两个分类特征,并丢弃这两个特征中任一的词汇表外术语的序列元素。我们用单个标量值$log(𝑑𝑢𝑟𝑎𝑡𝑖𝑜𝑛)$来编码动作持续时间。

为了表示动作发生的时间,我们使用2个衍生值以及原始的绝对时间戳:自用户采取的最新动作以来的时间,以及动作之间的时间间隔。对于这些时间特征,我们遵循使用不同周期的正弦和余弦变换编码时间的常见做法,类似于Time2vec[11],但使用固定的𝑃周期,而不是学习周期,以及对时间进行对数变换,而不是线性变换。这产生了2𝑃 + 1个特征(来自时间戳的周期变换的2𝑃)。

所有特征被连接成一个单独的向量,结果是一个维度为$𝐷_{in}$的输入向量。对应于动作𝐴𝑖的表示记为$𝑎_𝑖 \in R^{𝐷_{in}}$。

3.2 模型架构

在PinnerFormer中,我们使用transformer模型架构[22]来模拟用户动作序列。我们选择使用PreNorm残差连接,在每个块之前应用层归一化,因为这种方法已被证明可以提高训练的稳定性[16, 23]。我们首先构造输入矩阵$𝐴 = [𝑎_𝑇, …, 𝑎_{𝑇−𝑀+1}]^T \in R^{𝑀×𝐷_{in}}$,使用作为用户序列的导致动作$𝐴_{𝑇+1}$的𝑀个动作。然后,我们将这些投影到transformer的隐藏维度,添加一个完全可学习的位置编码,并应用一个标准transformer,由交替的前馈网络(FFN)和多头自注意力(MHSA)块组成。transformer在每个位置的输出通过一个小型MLP和L2归一化,结果得到一组嵌入$𝐸 = [𝑒_1, … , 𝑒_𝑀]^T \in R^{𝑆×𝐷}$,其中𝐷是最终嵌入维度。

为了表示Pins,我们学习一个MLP,它只接受PinSage作为输入,并L2归一化输出嵌入。我们发现使用L2归一化的嵌入来表示用户和Pins可以带来最稳定的训练,并且不会牺牲离线性能。

3.3 度量学习

为了训练我们的表示,我们需要由用户嵌入和目标Pin嵌入组成的配对${(𝑢1, 𝑝1), …, (𝑢𝐵, 𝑝𝐵)}$,其中用户和Pins可能被重复选择。我们选择不在这项工作中使用显式的负例(即我们没有为负参与,如隐藏,设置损失项)。在设计我们的模型时,有几个考虑因素:

  • (a) 我们如何选择这些配对?
  • (b) 对于给定的$(𝑢_𝑖, 𝑝_𝑖)$配对,我们如何选择负例?
  • (c) 给定一个$(𝑢_𝑖, 𝑝_𝑖)$配对和一组负例,我们如何计算损失?

我们首先描述(b)和(c),然后在3.4节详细讨论(a)。

3.3.1 负例选择。

我们考虑两个来源的负例:批内负例和随机负例。在选择给定用户的批内负例时,我们选择批内所有正例作为负例,遮蔽对该用户有正参与的Pins。这种方法高效简单,但如果天真地实施,可能会导致流行Pin的降级,因为参与度高的Pin比参与度低的Pin更可能出现为负例。批内负例的另一个缺点是负例的分布与用于检索的真实Pins底层分布不同,导致训练和服务之间的差异。第二个负例来源是我们可能展示给Homefeed的所有Pins语料库中均匀采样的负例,但单独使用这些可能导致模型崩溃,因为负例可能太容易。我们考虑的第三个选项是结合随机和批内负例,通过将批内和随机负例池合并为一个,包含批内和随机负例的组合,以利用两者的独特特征[26]。

在实践中,更大的负例池可以提高学习嵌入的质量,因此我们从训练中使用的所有的GPU中收集负例,选择可以舒适地适应GPU内存的最大可能池。

3.3.2 损失函数。

在选择负例来源后,我们可以为给定的用户和正嵌入配对$(𝑢_𝑖, 𝑝_𝑖)$产生一组负嵌入${𝑛_1, \cdots, 𝑛_𝑁}$。我们为每对计算损失,然后计算加权平均值,使得每个GPU上的批内每个用户都有相等的权重。

我们发现最好的损失函数是采样softmax带logQ修正[2, 27],我们根据给定负例在批中出现的概率对每个logit应用修正。我们还学习一个温度$\tau \in [0.01, \infty)$,限制稳定性的下界。如果我们让$𝑠(𝑢, 𝑝) = ⟨𝑢, 𝑝⟩/𝜏$,一个没有样本概率修正的采样softmax损失将被定义如下:

\[L (𝑢𝑖, 𝑝𝑖) = − \log \frac{𝑒^{𝑠(𝑢𝑖,𝑝𝑖)}}{𝑒^{𝑠(𝑢𝑖,𝑝𝑖)} + \sum_{𝑗=1}^{𝑁} 𝑒^{𝑠(𝑢𝑖,𝑛𝑗)}}\]

…(1)

当负例不是均匀分布时,应应用一个修正项𝑄𝑖(𝑣) = 𝑃 (Pin 𝑣在批中 用户𝑈𝑖在批中)来纠正采样偏差,其中𝑣可能是正例或负例。对于单个配对的带样本概率修正的softmax损失然后被定义如下:
\[L (𝑢𝑖, 𝑝𝑖) = − \log \frac{𝑒^{𝑠(𝑢𝑖,𝑢𝑖)−\log(𝑄𝑖(𝑝𝑖))}}{𝑒^{𝑠(𝑢𝑖,𝑢𝑖)−\log(𝑄𝑖(𝑝𝑖))} + \sum_{𝑗=1}^{𝑁} 𝑒^{𝑠(𝑢𝑖,𝑛𝑗)−\log(𝑄𝑖(𝑛𝑗))}}\]

…(2)

为了简化,我们使用计数-最小草图[5]来近似𝑄。

3.4 训练目标

给定我们的损失函数,我们解决如何选择配对$(𝑢_𝑖, 𝑝_𝑖)$的问题。我们的模型应该能够预测三种形式的正向参与:Repins、Closeups和Clicks。这些动作都有价值,而不是像多任务学习文献[1, 14]中常见的那样学习任务特定的头,我们选择以多任务的方式训练单个嵌入,直接学习一个可以有效检索不同类型的正向参与的嵌入。我们不在损失计算函数中显式地对不同参与进行不同的加权。我们考虑的四个训练目标如下描述,并在图2中描绘。

图片名称

图2

3.4.1 下一个动作预测。

序列建模任务的朴素目标是下一个动作预测,我们给定用户序列$\lbrace 𝐴_𝑇, 𝐴_{𝑇−1}, …, 𝐴_{𝑇−𝑀+1} \rbrace$预测$𝐴_{𝑇+1}$(如果$𝐴_{𝑇+1}$是正向参与)。这个目标对于实时序列模型来说很直观,因为在在线设置中,$𝐴_𝑇$总是用户采取的最新动作。SASRec[10]通过在模型的每一步预测下一个动作,而不仅仅是预测最近的正向参与来扩展这个简单的训练目标。我们在实验中稍微修改这一点,只允许正向参与对模型的损失做出贡献。

与这些传统目标不同,我们的目标不是预测用户的下一个即时动作;相反,我们每天推断用户嵌入,并旨在捕捉用户的长期兴趣。为此,我们引入了两个替代训练目标。

3.4.2 所有动作预测。

基于我们不仅希望预测用户将采取的下一个动作的观察,我们构建了一个朴素的训练目标,使用最终用户嵌入𝑒1预测用户在接下来的𝐾天内将采取的所有动作。假设用户在𝑇+3、𝑇+8和𝑇+12的动作中有正向参与,所有这些都落在𝑇的𝐾天窗口内,我们的目标是从用户序列{𝑎𝑇, 𝑎𝑇−1, …, 𝑎𝑇−𝑆+1}预测所有3个动作:𝐴𝑇+3、𝐴𝑇+8、𝐴𝑇+12。这个目标迫使模型学习长期兴趣,而不仅仅关注用户将采取的下一个动作,这应该减少来自每天离线推断的陈旧性效应。为了计算可行性,我们在这个𝐾天时间窗口中为每个用户随机采样多达32个动作。

3.4.3 密集所有动作预测。

为了进一步提高每批提供的信号,我们从SASRec[10]中汲取灵感,修改所有动作预测目标。我们不是使用只有𝑒1的最新用户嵌入在𝐾天窗口内预测动作,而是选择一组随机索引{𝑠𝑖},并对每个𝑒𝑠𝑖,旨在从接下来𝐾天内所有正向参与的集合中预测一个随机选择的正向参与。为确保这种方法从数据的顺序中学习,我们对transformer的自注意力块应用因果掩蔽,以便每个动作只能关注过去或现在的动作,而不能关注未来的动作。我们观察到这种掩蔽在这项任务上显著提高了模型的性能。为了减少内存使用,我们不旨在预测所有正向参与动作,而只是为每个𝑒𝑠𝑖预测一个正向参与动作。

3.5 数据集设计(续)

我们利用压缩格式来存储训练序列。我们观察到,给定单个用户的时间线,可以构建许多独立的用户序列和正例。给定一个完整的用户序列 ( A_U = {Y_1, \ldots, Y_S} ) 和某个最大序列长度 ( M ),我们可以构建多达 ( S - M - 1 ) 个长度恰好等于 ( M ) 的训练样本(假设所有动作都是正向的)。例如,序列 ({Y_5, \ldots, Y_{5+M-1}}) 以及正参与 ({Y_{5+M}, Y_{7+M}}) 可以从完整的时间线 ( A_U ) 中提取出来。存储这些数据的一种潜在方式是提前具体化所有长度为 ( M )(或更短)的相关序列,以及每个序列对应的未来正参与集合。这在尝试不同的采样策略时会遇到问题,因为调整参数将需要重新生成训练数据——这是一个缓慢的过程。为了提高生产力,我们改为将每个用户的序列存储为数据集中的单行,并在训练期间即时采样示例。这明显的好处是允许在训练期间进行定制采样,但代价是减少了训练数据的混洗。

具体来说,我们使用这种策略调整了几个参数,这些参数都显著影响模型的整体性能:

  • 最大序列长度
  • 从用户时间线中采样的可能用户序列的比例
  • 每个用户采样的最大序列数
  • 每个序列作为标签采样的最大正例数

3.6 模型服务

由于我们专注于PinnerFormer的离线、批量设置中的推理,我们在一个每日增量的工作流程中推断模型,如图3所示。

图片名称

图3

这个工作流程为过去一天与任何Pin互动的用户生成新的嵌入,将它们与前一天的嵌入合并,然后上传到键值特征存储中,以便在线服务。因为我们只为最近一天有互动的用户生成新的嵌入,并且在没有延迟限制的情况下离线运行推理,我们能够使用比否则可能的更大的模型,这增加了我们的嵌入可以捕获的信息量。如果输入特征有任何损坏(例如,由于日志记录错误),我们可以轻松地为自损坏以来更新了嵌入的所有用户运行推理,假设上游数据已经修复,第二天的数据将是正确的。

Pin嵌入的计算成本很低,只需要对现有特征进行小型MLP转换,因此我们每天从头开始生成它们,然后编译一个HNSW[15]图,该图可以使用保存在特征存储中用户嵌入在线查询。

4.

附录

https://arxiv.org/pdf/2205.04507

weixin在《Scenario-Adaptive Feature Interaction for Click-Through Rate Prediction》提出了一种在特征交叉建模中考虑场景信息的方法:SATrans。

一、摘要

传统的点击率(CTR)预测模型通常在单一场景下进行训练和部署。然而,大规模的商业平台通常包含多个推荐场景,其流量特征可能非常不同。最近的研究证明,学习一个统一的模型来服务于多个场景可以有效地提高整体性能。然而,大多数现有方法都各自存在各种限制,例如:区分度建模不足、随着场景增加效率低下、以及缺乏可解释性。更重要的是,据我们所知,现有的多场景建模方法在建模场景差异时没有考虑显式的特征交互(explicit feature interaction),这限制了网络的表现力,从而影响效果。在本文中,我们提出了一个名为SATrans的新型场景自适应特征交互框架(Scenario-Adaptive Feature Interaction framework),将场景差异(scenario discrepancy)建模成特征相关性(feature correlations)模式的差异。具体而言,SATrans建立在Transformer架构上,以学习高阶特征交互,并在自注意力建模中涉及场景信息,以捕捉场景之间的分布变化。我们提供了各种实现我们的框架来提高性能,并在公共和工业数据集上进行实验,结果表明SATrans:

  • 1)显著优于现有的最先进方法进行预测
  • 2)参数效率高,随着场景增加而空间复杂度略微增加
  • 3)在实例级别和场景级别都具有良好的可解释性

我们已经将该模型部署在微信公众号平台上,在三个主要场景中平均在线CTR增加了2.84%。

一、介绍

近年来,多场景点击率(MS-CTR:Multi-Scenario Click-Through Rate)预测[8, 19, 20, 28, 29]已成为在线推荐领域广泛研究的热点,它主要关注于预测在多个场景中的用户-物品对的CTR。在像腾讯和阿里巴巴这样的大型商业公司中,通常存在许多业务场景(例如主页信息流、横幅信息流)[30]。此外,从服务平台收集的日志数据可以根据一些代表性特征(例如性别、国家)分成多个子集。这些子集具有不同的CTR分布,可以被视为场景[29]。不同的场景间可以共享共性(例如重叠的用户或物品、一般性偏好),可以使所有场景的预测受益。同时,用户行为和曝光分布在不同场景下可能会有很大的差异[32]。因此,在估计CTR时建模场景之间的共性和差异非常重要。此外,特征交叉(feature interaction)学习在CTR预测任务中起着至关重要的作用。有效地模拟特征的高阶组合可以提高网络的表达能力,从而有助于提高预测性能[4, 10, 21]。

通常有三种典型的MS-CTR预测方法:

  • (1)利用传统的CTR预测模型[4, 5, 10, 13, 24, 27]和启发式训练策略,例如:为每个场景训练单独的模型、或使用所有场景实例训练共享模型,然后进行微调。这类方法可以自然地继承传统CTR预测模型的所有优点(例如显式特征交互),但它们在知识转移和场景建模方面的能力有限。
  • (2)基于多任务学习(MTL)构建统一框架,将每个场景视为一个任务[2, 8, 20]。这种策略需要为每个场景建立单独的网络模块(例如门控网络、专家或输出塔),随着场景的增加,会消耗过多的参数。更糟糕的是,MTL模型通常将骨干网络或专家网络视为广义深度神经网络(DNN)[11, 17, 22],以位逻辑和隐式方式学习高阶特征交互,受到离散特征交互的梯度不敏感问题的困扰,无法适应POLY函数[14]或简单的点积[16]。尽管可以用因子分解机(FM)[15]或DCN [24]等显式交互模型替换DNN,但特征交互和场景建模的过程是分离的,这限制了模型的可解释性,并可能导致次优的性能。
  • (3)利用辅助编码器(auxiliary encoder)使用场景相关特征作为输入,生成场景自适应单元(SAU),以影响网络[28-30]。这些方法比MTL方法更灵活、参数更有效,可以处理大量场景和多个场景特征字段。然而,这一类现有方法并没有直接、明确地考虑场景特性对特征交互的影响,因此跨场景的特征相关性和组合的差异仍不清楚。

从特征交互的角度来看,来自不同场景的样本可能具有不同的模式。以电子商务推荐为例,性别、位置和品牌可能是三个重要的特征,它们的组合可能会显著影响CTR得分。然而,同一特征组合的重要性在不同场景中是不同的。考虑二阶特征组合,<品牌,位置> 可能对食品推荐场景更有意义,因为用户的食品偏好受地理因素的影响很大,而 <品牌,性别> 在服装推荐中可能更相关,因为这个场景中有特定的性别区分。据我们所知,现有的MS-CTR方法都不能明确地捕捉到这种特征交互的差异,这限制了网络的表达能力,并导致模型的可解释性不足。

为了解决这些限制,本文提出了一种名为Scenario-Adaptive Transformer(SATrans)的MS-CTR预测的显式特征交叉模型,将场景信息纳入特征的相关建模中,以学习每个场景的独特和自适应的高阶特征交互。具体而言,我们利用Transformer [23]作为骨干架构,对输入特征进行高阶交叉和组合建模,该方法已被AutoInt [21]和InterHAt [9]证明是有效的。Transformer中的多头自注意机制允许每个特征字段与所有其他特征交叉,并自动识别相关特征以形成有意义的高阶特征。为了将场景特性纳入特征交叉中,我们:

  • 首先设计了一个场景编码器,将场景相关特征转换为固定长度的场景embedding。
  • 然后利用场景自适应交叉层来测量相关性,使用特征对的embedding和场景embedding作为输入,其中注意力分数通过一个精心设计的场景自适应相关函数计算。

提出的场景自适应自注意机制赋予SATrans许多优点:

  • (1)共性建模:每个交叉层中的共享特征转换矩阵和嵌入层自然地捕捉到共同知识;
  • (2)差异建模:自适应注意力分数编码了场景之间的分布偏移;
  • (3)高可扩展性:网络参数的规模几乎不依赖于场景的数量,使SATrans能够高效地处理数千甚至数百万个场景;
  • (4)良好的可解释性:注意力分数可以衡量特征之间的相关性,提供实例级和场景级的可解释性。

总之,在本文中,我们做出了以下贡献:

  • 我们是第一个从特征交互的角度对MS-CTR预测问题进行建模,并提出了一种新颖的SATrans,它在输入特征上明确地进行场景自适应高阶交叉
  • 我们分别为SATrans设计了三种场景编码器和场景自适应交互模块的实现,相比于基本的自注意力机制,显著提高了特征交互的质量
  • 我们在公共和工业数据集上进行了广泛的实验。在多场景CTR预测任务上的实验结果表明,我们提出的方法不仅在预测方面显著优于现有的最先进方法,而且具有良好的可扩展性和模型可解释性
  • 考虑到MS-CTR预测中开源代码的稀缺性,我们发布了我们模型的实现以及比较基准3,以促进未来的研究

三、问题公式化

点击率(CTR)预测数据集可以表示为:

\[D = \lbrace (𝑥_𝑗,𝑦_𝑗) \rbrace_{j=1}^{|D|}\]

其中:

  • $𝑥_𝑗$和$𝑦_𝑗 \in \lbrace 0,1 \rbrace$:表示第j个样本的特征集和点击label

在现实世界的推荐中,通常存在多个业务场景,这意味着数据集D可以分为多个特定场景的子集 $D^s$(例如:$D = U_s D^s$),其中场景𝑠的子集$D^s= \lbrace(𝑥_𝑖^s,𝑥_i^a,𝑦_𝑖)\rbrace_{𝑖=1}^{\mid D^s \mid}$根据$𝑥_i^s$获得。这里将整个特征集$𝑥_𝑖$分为:

  • 场景相关(scenario-specific)的特征集:$𝑥_𝑖^s$
  • 场景无关(scenario-agnosti)的特征集:$𝑥_𝑖^a$

$𝑥_𝑖^s$中的场景相关特征可以是:业务ID或展示位置ID等上下文特征,也可以扩展为用户配置文件特征(例如,性别,年龄组)或item特征(例如,类别,品牌),这可能会导致不同的行为或曝光分布。将每个场景子集$D^𝑠$拆分为:训练集$D_{train}^s$和测试集 $D_{test}^s$,我们有:$D_{train} = U_s D_{train}^s$和$D_{test} = U_s D_{test}^s$。MS-CTR预测的目标是:基于$D_{train}$构建一个统一的CTR模型,可以为$D_{test}$中的所有场景子集提供准确的CTR预测。

4.方法

4.1 架构总览

为了建模多个场景下特征交互的特殊性,对于MS-CTR预测问题,我们提出了SATrans。

图片名称

图1 SATrans的总体框架。左侧是场景编码器,使用场景相关特征作为输入生成固定大小的嵌入。右侧是由多个SAI层组成的骨干网络。场景编码器和SAI层的实现细节分别在第4.2节和第4.3节中详细说明。

如图1所示,SATrans将基于自注意力的交叉层堆叠作为backbone,并由两个场景相关组件(scenario-specific components):

  • (1) 场景编码器(Scenario Encoder):将特定场景特征转换为固定长度的embedding向量
  • (2) 场景自适应交叉层(Scenario-Adaptive Interaction: SAI layers):通过场景自适应自注意机制进行高阶特征交叉。

给定输入特征集${𝑥_𝑖^s,𝑥_𝑖^a}$,我们首先将其转换为稀疏特征向量:

\[x = [x^s; x^𝑎] = [x_1^s; \cdots; x_𝑀^s; x_1^a; \cdots; x_{𝑁-𝑀}^a]\]

… (1)

其中:

  • 𝑀是场景相关特征(scenario-specific features)的数量
  • 𝑁是所有特征的数量

之后,我们首先将场景相关特征$x^s$输入到场景编码器(scenario encoder)中以获取场景embedding s,然后使用embedding layer将所有特征x投影到相同的低维空间,并获得dense embedding $e = [e_1; \cdots; e_𝑁]$,接着进行多个场景自适应交叉层(scenario-adaptive interacting layers),其中在场景embedding的指导下,通过自注意机制将高阶特征组合在一起。通过堆叠𝑙个交叉层,可以建模多达(𝑙+1)阶的场景自适应特征交叉。最终交叉层的输出被连接,然后经过线性层和sigmoid函数来估计CTR。SATrans的关键在于如何设计有效的场景编码器和场景自适应交互模块。在接下来的部分中,我们将介绍我们提出的方法的详细信息。

图片名称

图2 三种类型的Scenario Encoder

4.2 Scenario Feature Encoder

给定场景相关特征$x^s=[x_1^s;\cdots;x_𝑀^s]$,我们使用一个场景自适应编码器(scenarioadaptive encoder)将场景特征编码为固定长度的场景embedding $s \in R^L$,以指导在每个SAI层中的特征交互,其中维度𝐿取决于SAI层的具体实现。为了提高场景embedding的质量,我们考虑三个信息来源:

  • 1)场景专有信息,区分不同的场景;
  • 2)共享知识,编码场景之间的共性;
  • 3)结构位置,表示场景嵌入在自注意网络中涉及的位置(position)(例如,当前层的深度,查询或键嵌入)。

我们针对不同的信息来源提出了三种实现方式。

  • 独立嵌入(IE: Independent Embedding):该方法首先将场景特征拼接一起稀疏向量$x^𝑠$转换为一个one-hot稀疏特征$x^𝑜$,然后使用嵌入矩阵将其投影到低维向量s中。这种做法将所有场景特征字段的每种可能组合视为一个场景,并使用独立embedding来表示每个场景,这意味着场景之间没有共享知识。更糟糕的是,当特征组合数增加时,嵌入矩阵可能会很大,这将导致参数效率低下和不灵活。

  • 编码网络(EN: Encoding Network):为了更灵活地编码场景特征并涉及共享知识,我们考虑利用共享编码网络来转换场景特征。对于每个场景特征字段,首先使用嵌入矩阵$E_𝑖^s$将稀疏特征向量$x_𝑖^s$投影为低维向量$e_𝑖^s$。我们将每个字段的embedding向量连接起来,得到:$e^𝑠=[e_1^s; e_2^s; \cdots; e_𝑀^s]$,然后通过非线性激活层(例如ReLU [1])将其feed到一个共享的编码网络$𝑓_𝑒(·)$中,以获取最终的场景embedding s。在我们的实验中,我们发现一个简单的矩阵变换已经足够,即:$s=W_𝑠 ReLU(e^𝑠)$。

  • 带有结构位置ID的编码网络(ENP):由于场景embedding在不同的交叉层和backbone自注意力网络中的不同位置(例如,查询或键)上操作,因此生成位置感知的场景嵌入(position-aware scenario embeddings)以提高网络的表达能力是合理的。为此,除了场景特征外,我们还将位置ID作为额外特征馈送到网络中,以为SAI层中的每个结构位置生成唯一的场景embedding。具体而言,我们有:

\[s_{𝑙,ℎ} = W_𝑠 ReLU(Concat(e^𝑠, p_{𝑙,ℎ}))\]

…(2)

其中:

  • $p_{𝑙,ℎ}$是position embedding
  • 𝑙是层深度(layer depth) ID
  • $ℎ \in \lbrace 𝑄,𝐾 \rbrace$

在EN和ENP方案中,每个场景(或场景特征)的单独网络参数只是低维度(在我们的实验中为32)的embedding向量,与每个场景具有独立门控网络、特定专家网络或输出塔的MTL方法相比,这是非常参数有效的,使得SATrans可用于大量场景。我们在实验中比较参数复杂度。在接下来的部分中,我们省略下标𝑙,并使用$s_Q$和$s_K$分别表示查询和键表示的场景嵌入,以简化表示。请注意,对于IE和EN策略,$s_Q=s_K$。

4.3 Scenario-Adaptive Interacting Layer

一旦我们在相同的低维空间中拥有特征embedding: $e=[e1;…;e𝑁]$,和每个交互层中每个位置的场景embedding: $s_{𝑖,𝑗}$,我们就开始建模场景自适应高阶组合特征。假设第𝑖个特征的输入表示为$h_𝑖$,并且在第一个交互层中$h_𝑖=e_𝑖$。

我们首先引入多头自注意机制来确定每个特征组合的重要性。以第𝑖个特征为例,首先,在特定的注意力头ℎ下,第𝑖个特征与第𝑗个特征($𝑖,𝑗 \in \lbrace 1,…,𝑁 \rbrace$)之间的相关性定义为:

\[𝛼_{𝑖,𝑗}^{(ℎ)}=\frac{exp(𝜙(ℎ)(h_𝑖,h_𝑗))}{\sum_𝑘^N exp(𝜙(ℎ)(h_𝑖,h_𝑘))}\]

…(3)

\[𝜙(ℎ)(h_𝑖,h_𝑗)=⟨W_Q^{(ℎ)} h_𝑖, W_K^{(ℎ)} h_𝑗⟩\]

…(4)

其中:

  • $𝜙(ℎ)(·,·)$:是一个attention函数,它定义了在head h下第𝑖个特征和第𝑗个特征之间的未归一化相关性。它可以是一个神经网络或者简单的内积,即⟨·,·⟩。
  • $W_Q^{(h)}, W_K^{(h)} \in R^{𝑑′\times 𝑑}$:是变换矩阵,将原始的embedding空间$R^𝑑$投影到一个新的空间$R^{𝑑′}$。其中$𝑑′=𝑑/𝐻$,𝐻是注意力头的数量。

然后,通过系数$𝛼_{𝑖,𝑗}$聚合其他特征,第𝑖个特征在子空间ℎ中的representation被更新为:

\[\widehat{h}_𝑖^{(ℎ)} = \sum\limits_l^M 𝛼_{𝑖,𝑗}^{(ℎ)} (W_V^{(ℎ)} h_𝑙)\]

…(5)

其中:

  • $W_V^{(ℎ)} \in R^{𝑑′×𝑑}$
  • $\widehat{h}_𝑖^{(ℎ)}$:是在head h下第𝑖个特征及其相关特征的组合。

等式(4)中的相关函数将所有场景的实例视为相同,忽略了不同场景之间的分布差异。为了建模场景之间的分布转移,我们在特征之间的相关系数计算中引入了场景embedding。我们首先将$s_Q、s_K$的场景embedding分成𝐻个部分,即:

\[s_Q=[s_Q^{(1)}, \cdots, s_Q^{(𝐻)}],\\ s_K=[s_K^{(1)}, \cdots, s_K^{(𝐻)}]\]

其中:

  • $s_K^{(h)},s_Q^{(h)} \in R^{𝐿/𝐻}$

然后在head h下改进场景自适应注意力函数,如下所示:

\[𝜙_{𝑠𝑎}^{(ℎ)}(h_𝑖,h_𝑗,s_Q^{(ℎ)},s_K^{(ℎ)})\]

… (6)

现在的问题是:如何设计场景自适应注意力函数$𝜙_{𝑠𝑎}^{(ℎ)}(·,·,·,·)$,它会明显影响交叉质量。基于计算复杂度从低到高的顺序,我们考虑了三种方法,如图3所示。

图片名称

图3 计算scenario-adaptive self-attention的三种策略

SA-Gate(Bit-wise)

SA-Gate是一种直接使用按位转换(bitwise transform)来引入场景embedding的策略是门控机制。具体而言,我们基于场景嵌入生成门控模块,以过滤特征嵌入:

\[𝜙_{𝑠𝑎}^{(ℎ)}(h_𝑖,h_𝑗,s_Q^{(ℎ)}, s_K^{(h)})=⟨\sigma(s_Q^{(h)}) \circ (W_Q^{(h)} h_𝑖), \sigma(s_K^{(h)}) \circ (W_K^{(h)} h_𝑗)⟩\]

…(7)

其中:

  • $\sigma(𝑥)=1/(1+e^{(−𝑥)})$:表示Sigmoid函数
  • $\circ$:表示element-wise乘积

SA-Bilinear(双线性: Bilinear)

这种方法对特征embedding进行双线性变换,由场景感知矩阵S参数化。注意力分数计算为:

\[𝜙_{𝑠𝑎}^{(ℎ)}(h_𝑖,h_𝑗,s_Q^{(ℎ)},s_K^{(ℎ)})=(W_Q^{(ℎ)} h_𝑗)^⊤ S(W_K^{(ℎ)} h_𝑖)\]

…(8)

其中:

  • $S=Reshape(s_Q^{(ℎ)}) \in R^{𝑑×𝑑}$:场景感知矩阵

…(9)

注意:在这种策略中,每层中的$s_Q^{(ℎ)}$和$s_K^{(ℎ)}$是相同的。

SA-MetaNet(非线性)

前两种策略采用按位和双线性变换来引入场景特征,其表达能力有限,可能无法建模场景信息与交互特征之间的复杂关系。为此,我们考虑通过MetaNet机制进行非线性变换,类似于动态权重单元[30]。

以$s_Q^{(ℎ)}$为例,首先将其分成𝑃个slots:$[s_{Q,1}^{(ℎ)};\cdots;s_{Q,𝑃}^{(ℎ)}]$,

生成一个𝑃层Meta Network $𝑓_{s_Q^{(ℎ)}}^m(·)$的投影参数:

\[𝑓_{s_Q^{(ℎ)}}^m=W_1 \sigma(W_2 \sigma(\cdots \sigma(W_𝑃 x)\cdots))\]

其中:

  • $W_𝑝=Reshape(s_{Q,p}^{(ℎ)}),W_𝑝 \in R^{𝑑_{𝑝−1}×𝑑_𝑝}$
  • $𝑑_𝑝$:是第𝑝+1层的输入维度
  • $\sigma$:是非线性激活函数(例如ReLU)

我们使用相同的过程构建$𝑓_{s_K^{(ℎ)}}^m(·)$来处理场景嵌入$s_K^{(ℎ)}$。生成的MetaNet用于在pair-wise交叉前对input特征embedding进行转换。直观地说,$s_Q$和$s_K$的不同slots以及激活函数,可以被视为从低层到高层的场景感知滤波器,对特征嵌入进行处理,赋予网络捕捉场景之间隐含差异的能力。现在,场景自适应注意力得分(scenario-adaptive attention score)计算如下:

\[𝜙_𝑠𝑎^{(ℎ)}(h_𝑖,h_𝑗,s_Q^{(ℎ)},s_K^{(ℎ)})=⟨LN_Q^{(ℎ)}(𝑓_{s_Q^{(ℎ)}}^m (W_Q^{(ℎ)} h_𝑖)), LN_K^{(ℎ)} (𝑓_{s_K^{(ℎ)}}^m (W_K^{(ℎ)} h_𝑗))⟩\]

…(10)

其中:

  • $LN_Q^{(ℎ)}(·)$和$LN_K^{(ℎ)}(·)$:是层归一化层,用于归一化嵌入分布,具有独立的层参数。

我们发现归一化层是必不可少的,因为经过多层非线性变换后,embedding的方差会显著放大,这会严重影响收敛。在实践中,我们将MetaNet与LN层一起移动到多头分区之前,这允许跨不同头部进行信息交互,并在经验上实现了更好的性能。因此,注意力头ℎ下的注意力得分表示为:

\[𝜙_{𝑠𝑎}^{(h)}(h_𝑖,h_𝑗,s_Q,s_K)=⟨[LN_Q(𝑓_{s_Q}^{m}(W_Q h_𝑖))]^h, [LN_K(𝑓_{s_K}^m (W_K h_𝑗))]^ℎ⟩\]

…(11)

其中:

  • $W_Q$和$W_K \in R^{𝑑×𝑑}$:是变换矩阵
  • $[\cdot]^h$:表示分区操作和选择第ℎ个子空间

根据公式5,我们会更新在attention head h下的第𝑖个特征的representation为$\widehat{h}_𝑖^h$,然后将不同子空间的特征聚合如下:

\[\widehat{h}_𝑖 = \widehat{h}_i^1 \oplus \widehat{h}_2^h \cdots \oplus \widehat{h}_𝐻^h\]

… (12)

其中:

  • $\oplus$是concatenation运算符。

接下来,我们使用投影矩阵$W_Agg$将学习到的特征进行转换,并添加标准的残差连接(residual connections)以保留以前学习到的组合特征(combinatorial features),包括原始的个体特征(即一阶特征),接着是一个层归一化层。形式上,第𝑖个特征的输出表示为:

\[h_𝑖^O=LN(W_A \widehat{h}_𝑖 + h_𝑖)\]

…(13)

通过这样一个interacting layer,每个特征表示会被更新到一个新的特征空间中,具有在场景信息的指导下来自其他字段的信息聚合。我们可以堆叠多个这样的层来模拟任意阶的组合特征。我们将最后一层的输出embedding串联起来以获得$h^{Out}=h_1^{Out} \oplus h_2^{Out} … \oplus h_𝑁^{Out}$,并使用带有Sigmoid函数𝜎的线性层来获得最终预测:

\[pCTR=\sigma(W_O h^{Out} +b_O)\]

…(14)

其中:

  • $W_O \in R^{1×𝑁_𝑑}$ 和 $b_O \in R$。

整个网络通过交叉熵损失进行优化。空间和时间复杂度的分析详见附录A。

https://dl.acm.org/doi/pdf/10.1145/3580305.3599936

Vaclav Kosar在《Cross-Attention in Transformer Architecture》这篇文章里提出了一种cross attention方法。其实在很多地方有在用。

介绍

交叉注意力(Cross attention)是:

  • 一种在Transformer架构中的attention机制,可以将两种不同embedding序列进行混合
  • 这两个序列必须具有相同的维度
  • 这两个序列可以是不同的模态(例如文本、图像、声音)
  • 其中一个序列作为Query输入,定义了输出长度。另一个序列则产生Key和Value输入,用于attention计算

交叉注意力机制使得模型能够关注来自两个序列的相关信息,这在图像字幕或多模式机器翻译等任务中非常有用。

Cross-attention应用

Cross-attention vs Self-attention

除了输入之外,cross attention的计算方式与self-attention相同。cross attention以不对称的方式组合了两个相同维度的独立embedding序列,而self-attention的输入是单个embedding序列。其中一个序列作为query输入,而另一个序列作为key和value输入。在SelfDoc中的一种cross attention可选方式是:使用来自一个序列的query和value,而key则来自另一个序列。

前馈层(feed forward layer)与cross-attention相关,不同之处是:前馈层会使用softmax,并且其中一个输入序列是静态的。《[Augmenting Self-attention with Persistent Memory paper]{https://vaclavkosar.com/ml/Feed-Forward-Self-Attendion-Key-Value-Memory}》一文表明,前馈层的计算方式与self-attention相同。

图片名称

图1

Cross-attention算法

  • 假设我们有两个embeddings(token)序列S1和S2
  • 从序列S1中计算键(Key)和值(Value)
  • 从序列S2中计算查询(Queries)
  • 使用Key和Query来计算注意力矩阵(Attention Matrix)
  • 将queries应用于注意力矩阵
  • 输出序列具有与序列S2相同的维度和长度

在一个等式中:

\[softmax((W_Q S_2)(W_K S_1)^T)W_V S_1\]

Cross-attention可选方式

Feature-wise Linear Modulation Layer是一个更简单的可选方式,它不要求:输入必须是个序列,并且是线性计算复杂度的。这可以使用稳定扩散(Stable Diffusion)生成图像。在这种情况下,交叉注意力用于使用文本提示为图像生成器中的UNet层中的变压器进行条件编码。构造函数显示了我们如何使用不同的维度,并且如果您使用调试器逐步执行代码,还可以看到两种模态之间的不同序列长度。

Cross-attention实现

在Diffusers library中的cross attention实现可以使用Stable Diffusion生成图像。在这个case中,cross-attention被用于【使用文本prompt为图像生成器中的UNet层中的condition transformers】。构造函数显示了我们如何使用不同的维度,并且如果您使用调试器逐步执行代码,还可以看到两种模态之间的不同序列长度。

class CrossAttention(nn.Module):
    r"""
    A cross attention layer.

    Parameters:
        query_dim (`int`): The number of channels in the query.
        cross_attention_dim (`int`, *optional*):
            The number of channels in the encoder_hidden_states. If not given, defaults to `query_dim`.
        heads (`int`,  *optional*, defaults to 8): The number of heads to use for multi-head attention.
        dim_head (`int`,  *optional*, defaults to 64): The number of channels in each head.
        dropout (`float`, *optional*, defaults to 0.0): The dropout probability to use.
        bias (`bool`, *optional*, defaults to False):
            Set to `True` for the query, key, and value linear layers to contain a bias parameter.
    """

特别是在这部分中,您可以看到查询(query)、键(key)和值(value)是如何相互作用的。这是编码器-解码器架构,因此query是从encoder的hidden states中创建得到的。

        query = attn.to_q(hidden_states)
        query = attn.head_to_batch_dim(query)

        encoder_hidden_states = encoder_hidden_states if encoder_hidden_states is not None else hidden_states
        key = attn.to_k(encoder_hidden_states)
        value = attn.to_v(encoder_hidden_states)
        key = attn.head_to_batch_dim(key)
        value = attn.head_to_batch_dim(value)

        attention_probs = attn.get_attention_scores(query, key, attention_mask)
        hidden_states = torch.bmm(attention_probs, value)

流行结构中的cross-attention

Transformer Decoder中的cross-attention

图片名称

Stable Diffusion中的cross-attenion

图片名称

Perceiver IO中的Cross-Attention

图片名称

SelfDoc中的Cross-Attention

图片名称

kuaishou在《TWIN: TWo-stage Interest Network for Lifelong User Behavior Modeling in CTR Prediction at Kuaishou》中提出了TWIN的长序列建模方法。

摘要

终身用户行为建模(Life-long user behavior modeling),即从数月甚至数年的丰富历史行为中提取用户的隐藏兴趣,在现代CTR预测系统中起着核心作用。传统算法大多遵循两个级联阶段:一个简单的通用搜索单元(GSU),用于快速和粗略地搜索数万个长期行为,以及一个精确搜索单元(ESU),用于对GSU的少数最终选手进行有效的目标关注(TA)。尽管高效,现有算法大多存在一个关键限制:GSU和ESU之间的目标-行为相关度度量不一致。因此,它们的GSU通常会错过高度相关的行为,但会检索被ESU认为不相关的行为。在这种情况下,ESU中的TA,无论如何分配注意力,都会偏离真实的用户兴趣,从而降低整体CTR预测精度。为解决这种不一致性,我们提出了TWo-stage Interest Network(TWIN),其中我们的Consistency-Preserved GSU(CP-GSU)采用与ESU中TA相同的目标-行为相关度量,使两个阶段成为孪生。具体而言,为了打破TA的计算瓶颈并将其从ESU扩展到GSU,即从行为长度102扩展到长度104-105,我们通过行为特征分割构建了一种新的注意机制。

  • 对于行为的视频固有特征,我们通过高效的预计算和缓存策略计算它们的线性投影。
  • 对于用户-物品交叉特征,我们将每个特征压缩为注意力分数计算中的一维偏置项,以节省计算成本。

两个阶段之间的一致性,加上CP-GSU中有效的TA-based相关度量,为CTR预测的显著性能提升做出了贡献。在快手的460亿规模的真实生产数据集上进行的离线实验和在线A / B测试表明,TWIN优于所有比较的SOTA算法。通过优化在线基础设施,我们将计算瓶颈降低了99.3%,这有助于TWIN在快手上的成功部署,每天为数亿活跃用户提供主要流量服务。

1.介绍

作为中国最受欢迎的短视频分享应用之一,快手强烈依赖于其强大的推荐系统(RS)。每天,RS帮助数亿活跃用户过滤掉数百万个不感兴趣的视频,找到他们感兴趣的内容,留下数十亿的点击日志。这些巨大的数据不仅为RS的训练提供了数据支持,而且推动了技术革命,不断提升了这个平台的用户体验和业务效果。

在现代RS中,一个基本任务是点击率(CTR)预测,旨在预测用户点击一个item/视频的概率[2,10,32]。准确的CTR预测可以指导RS为每个用户提供其喜欢的内容,并将每个视频传递给其感兴趣的受众。为了实现这一目标,CTR模型应该高度个性化,并充分利用稀缺的用户信息。因此,终身用户行为建模,即从丰富的长期历史行为中提取用户的隐藏兴趣,通常作为CTR模型的关键组成部分[7,16,34-36]。

工业终身行为建模算法大多遵循两个级联阶段[19]:(1)通用搜索单元(GSU),对数万个长期行为进行快速粗略搜索,并输出最相关的少数目标行为;(2)精确搜索单元(ESU),对来自GSU的最终候选进行有效的目标关注(TA:Target Attention)。这种两阶段设计的原因有两个原因:

  • 一方面,为了准确捕捉用户的兴趣,TA是强调目标相关行为和抑制目标不相关行为的合适选择
  • 另一方面,TA的高昂计算成本限制了其适用的序列长度最多只有几百个。为此,一个简单快速的GSU作为预过滤器对于截断在短短几个月内就可以轻松达到$10^4-10^5$的工业规模行为序列至关重要。

近年来,出现了许多关于两阶段终身行为建模的新兴研究,它们的主要区别在于GSU策略,即如何粗略选择目标相关行为。例如:

  • SIM Hard [19]:仅从与target item相同的类别中选择行为
  • SIM Soft [19]:通过内积计算预训练item embedding的目标-行为相关度分数,并选择相关度最高的行为
  • ETA:使用局部敏感哈希(LSH)和汉明距离来近似计算相关度分数[3]
  • SDIM:通过多轮哈希碰撞从具有相同哈希签名的行为中采样目标行为,等等。

尽管已经广泛研究,现有的两阶段终身行为建模算法仍然存在一个关键限制:GSU和ESU之间的不一致性(如图11所示)。具体而言,GSU使用的目标-行为相关度量既粗略又与ESU中的TA不一致。因此,GSU可能会错过相关的行为,但会检索被ESU认为不相关的行为,浪费ESU宝贵的计算资源。在这种情况下,ESU中的TA,无论如何分配注意力,都会偏离真实的用户兴趣,从而降低整体CTR预测精度。

为了解决这种不一致性,我们提出了TWIN:TWo-stage Interest Network,用于终身用户行为建模,其中Consistency-Preserved GSU(CP-GSU)采用与ESU中TA相同的目标-行为相关度量,使两个阶段成为孪生。为了将昂贵的TA扩展到CP-GSU中,TWIN通过有效的行为特征分割、简化的TA架构和高度优化的在线基础设施打破了TA的关键计算瓶颈,即所有行为的线性投影。具体而言,对于行为的视频固有特征(例如视频ID、作者、持续时间、主题),这些特征在用户/行为序列之间共享,我们通过高效的预计算和缓存策略加速它们的投影。对于行为的用户-视频交叉特征(例如用户的点击时间戳、播放时间、评分),其中缓存不适用,我们通过将它们的投影压缩为偏置项来简化TA架构。通过优化在线基础设施,我们成功将TA的适用序列长度从ESU中的$10^2$扩展到CP-GSU中的$10^4 ~ 10^5$。两个阶段之间的一致性,加上CP-GSU中有效的基于TA的相关度量,为CTR预测的显著性能提升做出了贡献。

主要贡献:

  • 在我们提出的TWIN中,CP-GSU精确而一致地检索不仅与目标相关,而且ESU认为重要的行为,最大化行为建模的检索效果。据我们所知,我们是第一个成功解决两阶段终身行为建模问题不一致性的团队。
  • 我们通过在快手的460亿规模的工业数据集上进行大量离线实验和在线A/B测试来验证TWIN的有效性。我们通过消融研究验证了我们的有效性,并展示了TWIN带来的显著在线收益。
  • 我们构建了高效的工业基础设施,将TWIN应用于实际在线RS。我们提出了有效的预计算和缓存策略,将TWIN的计算瓶颈,即CP-GSU中行为的线性投影,降低了99.3%,并满足了在线服务系统的低延迟要求。TWIN现已部署在快手的RS上,每天为3.46亿活跃用户的主要流量提供服务。

2.相关工作

我们的工作与两个活跃的研究领域密切相关:CTR预测和长期用户行为建模。

2.1 点击率预测

CTR预测旨在预测用户的个性化兴趣,对于现代RS至关重要。早期的CTR模型是浅层的,主要关注于利用特征交互,例如因子分解机(FM)[22]和场感知因子分解机(FFM)[12]。随着深度学习的成功,深度CTR模型得到广泛研究并成为主流选择。例如,陈等人[2]和张等人[33]首次将深度模型应用于CTR任务。Wide&Deep [5]结合了宽线性模型和深度模型,充分利用特征交互的记忆和深度架构的泛化优势。DeepFM [10]和DCN [26,27]改进了Wide&Deep的宽部分,以增加特征交互能力。xDeepFM [15]和AFM [29]进一步利用类卷积层和注意机制来改进深度部分并提高模型性能。

随着CTR模型变得越来越个性化,用户行为建模,即从历史行为的总结中捕捉用户的隐藏兴趣,成为一个关键模块。由于计算资源的限制,早期的算法大多采用目标无关的方式,因此可以在离线情况下高效地预计算[8,23,31]。为了更好地提取用户对特定item的兴趣,采用了各种TA机制。DIN [36]通过历史行为上的TA表示用户兴趣,强调目标相关行为。DIEN [35]进一步使用ARGRU(经典GRU的基于注意力的变体)引入行为之间的时间关系。DSIN [9]将行为分为多个会话,并在每个会话内进行自注意力计算,以强调会话内关系。MIND [14]和DMIN [30]通过多个向量表示用户兴趣。BST [4]、SASRec [13]和BERT4Rec [24]也使用变压器来提高模型的性能和并行性。

2.2 Long-Term User Behavior Modeling

随着TA和兴趣建模在现代工业RS中的有效性得到确认,研究人员开始对越来越长的行为进行建模。Liu和Zamanian [16]将长期和短期兴趣结合在CTR预测中。MIMN [18]将用户行为存储为用户兴趣中心(UIC)的记忆矩阵,并在新的用户行为到来时更新记忆。然而,MIMN难以扩展到长度超过$10^3$的序列,并为不同的候选项生成相同的记忆矩阵,携带无用的噪声并损害TA。

最近,SIM [19]和UBR4CTR [20,21]引入了两阶段级联框架来解决这些挑战,并在CTR预测中实现了SOTA性能。传统的两阶段算法通常由以下两部分组成:

  • 1)一个简单快速的GSU,从数千个用户行为中检索与目标项最“相关”的item
  • 2)一个注意力ESU,对GSU的最终候选item执行TA

UBR4CTR在其第一阶段中使用BM25作为相关度量。而在原始的SIM中,有两个具有不同GSU设计的实例。SIM Hard的GSU从与目标项相同的类别中选择相关项,而SIM Soft的GSU使用预训练item embedding的内积作为相关度量。尽管两阶段设计迈出了重要一步,但原始的GSU仍面临着高计算负担,并且与ESU具有不同的检索度量,导致两个阶段之间的不一致性。

最近,ETA [3]使用局部敏感哈希(LSH)对由ESU训练的item embedding进行编码,并通过汉明距离(HD)从长期行为中检索相关项。SDIM [1]通过多轮哈希碰撞从具有相同哈希签名的行为项中采样target item,并通过线性聚合这些采样的行为项来获取用户兴趣。ETA和SDIM采用End2End训练是积极的。换句话说,它们的两个阶段共享相同的embedding。然而,在检索策略方面仍存在不一致性,具体而言是网络结构和参数。

在本文中,我们提出将TA结构扩展到GSU,并将embedding和attention参数从ESU同步到GSU,保持端到端训练。结果,在网络结构和模型参数方面实现了一致性,相比于ETA和SDIM,获得了显著的性能提升。我们在表1中详细说明了我们的模型与其他模型的差异。请注意,我们的工作与旨在加速变压器(例如LISA [28])的索引算法不同。它们通过将行为映射到码本并查找距离来近似相关度量计算。而我们的工作以及许多其他两阶段算法使用精确的距离计算,但使用GSU作为预过滤器来减少行为数量。

3 TWIN在快手CTR预测中的应用

首先,在第3.1节中,我们回顾了CTR预测问题的一般基础知识。然后,在第3.2节中,我们描述了快手CTR预测系统的模型架构。接着,在第3.3节中,我们进一步深入探讨了我们提出的保持一致性的终身用户行为建模模块——两阶段兴趣网络(TWIN)。最后,在第3.4节中,我们介绍了必要的加速策略,以确保TWIN成功部署在快手的主流量上。

所使用的符号总结在表2中。

3.1 基础知识

CTR预测的目的是:在给定特定上下文的情况下预测用户点击一个item的概率。准确的CTR预测不仅通过提供首选内容提升用户体验,而且通过吸引感兴趣的受众,有益于内容生产者和平台的业务效益。因此,CTR预测已成为各种工业RS的核心组成部分,特别是像快手这样的短视频推荐平台。

CTR预测通常被公式化为一个二元分类问题,目标是学习一个预测函数 $𝑓: R_d \rightarrow R$,给定:

  • $D=\lbrace (x_1,𝑦_1), \cdots,(x_{\mid D\mid}, 𝑦_{\mid D \mid})\rbrace$: 一个训练数据集。
  • $x_i \in R_d$:是第i个训练样本的特征向量(即用户、item和上下文特征的串联)
  • $𝑦_i \in \lbrace 0,1 \rbrace$:是表示用户是否点击(1)该项或未点击(0)的label

预测的CTR计算公式如下:

\[𝑦^i =\sigma(𝑓(x_𝑖))\]

…(1)

其中:

  • $𝜎(\cdot)$是将𝑓的预测缩放到(0,1)的sigmoid函数

模型的训练通过最小化负对数似然来完成:

\(l(D)=-\frac{1}{|D|} \sum_{𝑖=1}^{|D|} 𝑦_i log(\hat{𝑦}_i)+(1−𝑦_i)log(1−\hat{𝑦}_i)\) … (2)

为简洁起见,当不会引起混淆时,在以下各节中省略训练样本索引𝑖。

3.2 CTR预测的架构

我们现在介绍快手CTR预测系统的架构,详细信息如图2所示。

3.2.1 embedding layer

在底部,我们的模型从一个feature embedding layer开始,它会将训练样本的原始特征转换为embedding向量。

不失一般性,我们假设所有特征在必要的预处理后都是类别型。对于具有词汇表大小为$𝑣_𝐴$的特征𝐴,我们首先将分类信息编码为一个one-hot/multi-hot编码$xA,hot \in {0,1}^{𝑣_𝐴}$。例如:

\[WeekDay=Mon => x_{WeekDay,hot} = [1, 0, 0, 0, 0, 0, 0]^T, \\ Topic={Funny, Pet} => x_{Topic, hot} = [\cdots, 0, 1, 0, \cdots, 0, 1, 0...]^T\]

请注意,在大多数工业系统中,词汇表大小(特别是用户/作者/视频ID的大小)可以轻松扩展到数亿。因此,一种常见的策略是将极高维度的one-hot编码转换为低维度的嵌入向量,

\(x_{A,emb} = 𝐸_𝐴 x_{A,hot}\) …(3)

其中:

  • $𝐸_𝐴 \in R^{𝑑𝐴 \times 𝑣_𝐴}$是特征𝐴的embedding字典
  • $𝑑_𝐴$是embedding维度

在我们的系统中:

  • 对于具有大词汇表的id特征,我们将embedding维度设置为64,
  • 对于其他特征,如视频主题、视频播放时间戳,我们将embedding维度设置为8。

在所有上层中,我们将embedding向量作为输入,因此为简洁起见省略了“emb”下标。

3.2.2 深度网络

我们的CTR预测的总体架构如图2所示。

图2 快手CTR预测系统中的TWIN。与传统的两阶段行为建模算法不同,TWIN在CP-GSU和ESU中采用相同的目标-行为相关度度量,包括相同的网络架构(如左图所示)和相同的参数值(如中下部分所示)。这是具有挑战性的,因为MHTA的计算成本很高,因此只适用于ESU(具有100个行为),而不适用于CP-GSU(具有104个行为)。 我们通过提出以下方法来解决这个挑战:1)高效的特征拆分和投影策略,以不同的方式处理项的固有特征和用户-项交叉特征(如右下图所示);2)简化的目标注意力架构,通过将交叉特征压缩为偏置项来加速目标注意力的效率(如左图所示)。

上层模块由堆叠的神经网络和ReLU组成,作为一个混合器,学习三个中间模块的输出之间的交互作用:

  • TWIN,提出的保持一致性的终身用户行为建模模块,通过两个级联的行为建模子模块提取用户兴趣:
    • 1)保持一致性的一般搜索单元(CP-GSU):从成千上万的长期历史行为中进行粗略搜索,找到100个最相关的行为;
    • 2)精确搜索单元(ESU):对CP-GSU的100个最终选手采用attention机制,捕捉精确的用户兴趣。与通常由“轻量级”GSU和“重量级”ESU组成的传统算法不同,我们提出的CP-GSU采用与ESU相同的相关性评估指标,使得这两个级联阶段成为TWIN。因此,CP-GSU始终检索ESU认为重要的item,最大化了行为建模的效果。
  • 短期行为建模(Short-term behavior modeling):从最近的50个行为中提取用户兴趣。该模块关注用户对最近几天的短期兴趣,是TWIN的强有力补充。
  • 其他任务建模。除了行为建模,我们还将各种其他任务建模的输出连接起来,包括用户的性别、年龄、职业、位置,视频的持续时间、主题、受欢迎程度、质量,以及播放日期、时间戳、页面位置等上下文特征。

3.3 TWIN: 两阶段兴趣网络

我们将提出的算法命名为TWIN,以突出CP-GSU遵循与ESU相同的相关性评估指标。请注意,这种一致性并不是微不足道的,因为:

  • 有效的行为建模算法通常基于多头目标注意力(MHTA)[25],通过强调目标相关行为来精确捕捉用户兴趣。不幸的是,由于计算复杂度高,MHTA适用的行为序列长度大多限制在几百个之内。
  • 为了全面捕捉用户的长期兴趣,CP-GSU应该涵盖最近几个月的用户行为,这可能很容易达到数万个。考虑到在线系统的严格低延迟要求,这个序列长度远远超出了传统MHTA的能力范围。

本节的目的是回答这个关键问题:如何提高MHTA的效率,以便将其从ESU扩展到CP-GSU,或者说从数百个序列长度扩展到至少数万个序列长度?

3.3.1 行为特征分割和线性投影

遵循MHTA [25]的标准符号,我们将长度为𝐿的行为序列$[𝑠_1,𝑠_2,\cdots,𝑠_𝐿]$的特征定义为矩阵𝐾,其中每一行表示一个行为的特征。在实践中,MHTA中注意力得分计算中𝐾的线性投影是阻碍其在极长的用户行为序列上应用的关键计算瓶颈。因此,我们提出以下措施以降低其复杂度。

我们首先将行为特征矩阵𝐾分成两部分:

\(𝐾 ≜ [𝐾_ℎ 𝐾_𝑐] \in R^{𝐿 × (𝐻+𝐶)}\) …(4)

我们将:

  • $𝐾_ℎ \in R^{𝐿×𝐻}$:定义为行为items的固有特征(例如视频id、作者、主题、持续时间),它们独立于特定的用户/行为序列
  • $𝐾_𝑐 \in R^{𝐿×𝐶}$:定义为user-item交叉特征(例如用户点击时间戳、用户播放时间、点击页面位置、用户-视频交互)。这种分割允许高效计算以下线性投影$𝐾_ℎ 𝑊^ℎ$ $和$𝐾_𝑐 𝑊^𝑐$ 。

对于固有特征$𝐾_ℎ$,虽然维度𝐻很大(每个id特征为64),但线性投影实际上并不昂贵。特定项的固有特征在用户/行为序列之间是共享的。通过必要的缓存策略,𝐾ℎ𝑊 ℎ 可以通过查找和聚集过程高效地“计算”。在线部署的详细信息将在第3.4节介绍。 对于用户-项交叉特征𝐾𝑐,缓存策略不适用,因为:1)交叉特征描述了用户和视频之间的交互细节,因此不在用户行为序列之间共享;2)每个用户最多只观看一次视频。也就是说,在投影交叉特征时没有重复计算。因此,我们通过简化线性投影权重来降低计算成本。

对于用户-项交叉特征$𝐾_𝑐$,缓存策略不适用,因为:

  • 1)交叉特征描述了用户和视频之间的交互细节,因此不在用户行为序列之间共享;
  • 2)每个用户最多只观看一次视频。也就是说,在投影交叉特征时没有重复计算。

因此,我们通过简化线性投影权重来降低计算成本。

给定𝐽个交叉特征,每个特征的嵌入维度为8(因为没有具有巨大词汇表大小的id特征)。我们将线性投影简化如下:

\(𝐾_𝑐 𝑊^𝑐 ≜ [𝐾_{𝑐,1} w_1^c, \cdots, 𝐾_{𝑐,𝐽} w_𝐽^c]\) … (5)

其中:

  • $𝐾_{𝑐,𝑗} \in R^{𝐿×8}$: 是𝐾𝑐的第𝑗个交叉特征的按列切片
  • $w_𝑗^c \in R^8$:是其线性投影权重

使用这个简化的投影,我们将每个交叉特征压缩到一个维度,即$𝐾_𝑐 𝑊^𝑐 \in R^{𝐿×𝐽} $ 。请注意,这个简化的投影等价于将$𝑊 _𝑐$ 限制为一个对角块矩阵。

3.3.2 复杂度分析

在传统的MHTA中,线性投影的时间复杂度,即从维度$𝐿×(𝐻+𝐶)$到$𝐿×{d_out}$输出维度的复杂度为𝑂(𝐿×(𝐻+𝐶)×输出维度)。

而在我们的TWIN中的MHTA中,item的固有特征$𝐾_ℎ 𝑊^ℎ$已经预先计算并以𝑂(𝐿)的效率聚合,与维度𝐻无关。而user-item交叉特征$𝐾_𝑐𝑊^𝑐$则被降低为$𝑂(𝐿×𝐶)$的低维计算。 由于𝐶 ≪ 𝐻,且𝐶 ≪ 输出维度,正是这种理论上的加速,使得MHTA在CPGSU和ESU中都能一致地实现。

3.3.3 TWIN中的目标注意力

基于行为的线性投影𝐾ℎ𝑊 ℎ和𝐾𝑐𝑊 𝑐,我们现在定义了目标-行为相关度度量,该度量在CP-GSU和ESU中均匀使用。不失一般性,我们假设用户和目标项之间没有交互,并将目标项的固有特征表示为$q \in R_𝐻$。通过适当的线性投影$𝑊_𝑞$,计算目标项与历史行为之间的相关度分数: $𝜶 ∈ R 𝐿: 𝜶 = (𝐾ℎ𝑊 ℎ ) (q ⊤𝑊 𝑞 ) ⊤ √ 𝑑𝑘

(𝐾𝑐𝑊 𝑐 )𝜷$, (6)

其中$𝑑_𝑘$是查询和键的投影维度。这个相关度分数是通过查询(即目标的固有特征)和键(即行为的固有特征)之间的内积计算的。此外,由于交叉特征被压缩为1维,因此作为偏置项。我们使用𝜷 ∈ R 𝐽作为交叉特征的相对重要性的可学习参数。 在CP-GSU中,这个相关度分数𝜶用于将𝐿 = 104的长期历史行为截断为100个最相关的行为。而在ESU中,我们对最终的100个候选项执行加权平均池化: Attention(q ⊤𝑊 𝑞 , 𝐾ℎ𝑊 ℎ , 𝐾𝑐𝑊 𝑐 , 𝐾𝑊 𝑣 ) = Softmax(𝜶) ⊤𝐾𝑊 𝑣 , (7) 其中𝑊 𝑣是一个投影矩阵。我们稍微滥用了符号,将𝐿 = 100。这个投影𝐾𝑊 𝑣仅在100个行为上执行,因此可以在线高效地进行。我们不需要像计算104个行为的𝜶时那样分割𝐾。 为了共同关注来自不同表示子空间的信息,我们在MHTA中采用了4个头。因此,TWIN的最终输出定义为 TWIN = Concat(head1, …, head4)𝑊 𝑜 , head𝑎 = Attention(q ⊤𝑊 𝑞 𝑎 , 𝐾ℎ𝑊 ℎ 𝑎 , 𝐾𝑐𝑊 𝑐 𝑎 , 𝐾𝑊 𝑣 𝑎 ), 𝑎 ∈ {1, …, 4}, (8) 𝑊 𝑜是一个投影,学习头之间的相对重要性。