异构序列推荐:基于行为感知图与双通道对比学习的模型解析与实践
1. 项目概述与核心挑战
在电商、内容平台等场景下,推荐系统的核心任务是从用户的历史行为中“读懂”其兴趣,并预测下一个可能交互的物品。传统的序列推荐模型,比如基于RNN或Transformer的模型,已经取得了不错的效果。它们擅长捕捉“点击A之后点击B”这样的同构行为序列模式。然而,现实世界远比这复杂。一个典型的用户旅程可能是:浏览(view)了十件商品,将其中三件加入购物车(cart),最后购买(purchase)了一件。这里的“浏览”、“加购”、“购买”就是不同类型的异构行为。它们携带的偏好信号强度天差地别——一次购买蕴含的肯定意图,远强于十次浏览。
这就引出了异构序列推荐的核心难题:如何有效建模这些不同行为之间的复杂依赖关系,并最终精准预测目标行为(通常是购买)?现有的方法主要面临两大瓶颈。第一是数据稀疏性。目标行为(如购买)本身在用户序列中占比极低,模型难以从中学习到足够强的模式。虽然引入浏览、收藏等辅助行为可以增加数据密度,但这些行为噪声大、意图模糊,简单引入反而可能干扰模型对核心购买意图的判断。第二是行为语义的混杂。大多数模型将不同行为一视同仁,或者仅做简单区分,未能深入挖掘“从浏览到购买”这种跨行为转移路径中蕴含的深层用户决策逻辑。
我最近在复现和深入研究的一篇工作,即《基于行为感知与双通道对比学习的异构序列推荐模型》,正是针对上述痛点的一次有力尝试。它没有选择在原有模型上修修补补,而是从图结构建模和表示学习两个层面进行了重构。简单来说,它的思路非常清晰:首先,用图神经网络为每种行为类型构建专属的“关系地图”,精细刻画行为内和行为间的转移规律;然后,用双通道对比学习分别去强化用户的长期稳定偏好和短期动态兴趣的表示,让模型学到的用户画像既全面又敏锐。这种“分而治之,对比增强”的思想,在实际调优中展现出了强大的生命力。接下来,我将结合自己的实操经验,为你深入拆解这套框架的每一个技术细节、实现要点以及那些论文里不会写的“坑”。
2. 核心思路与方案选型:为什么是“行为感知图”+“双通道对比”?
在动手实现之前,理解设计动机至关重要。这决定了我们代码的骨架和调优的方向。BDPL模型的设计哲学可以概括为两点:精细化建模行为差异与多层次对比增强信号。
2.1 从“序列”到“图”:行为感知子图的构建逻辑
传统序列模型将用户历史视为一个线性的列表 [item1, item2, ...],主要关注相邻物品的前后关系。但在异构行为场景下,这种视角丢失了关键信息。例如,用户可能连续浏览了A、B、C三个商品,然后购买了C。这里不仅有 A->B->C 的序列关系,更存在 (浏览A)->(购买C) 和 (浏览B)->(购买C) 的跨行为、多跳的语义关联。BDPL的核心创新之一,就是将这种复杂的、网络化的关系显式地建模出来。
它构建了两种行为感知子图:辅助行为子图和目标行为子图。每个子图都包含三种边关系:
- 同构行为转移:如
浏览->浏览、购买->购买。这捕捉了同一行为类型下的连续兴趣。 - 异构行为转移:特指
浏览->购买。这是模型预测任务的关键路径,直接建模了用户从产生兴趣到做出决策的过程。 - 方向性:同时考虑正向(按时间顺序)和反向的转移关系,以更全面地捕捉上下文信息。
这里有一个非常关键的工程细节:如何定义 浏览->购买 这条边?论文指出,不应只连接紧邻的前一个浏览项和购买项。因为用户的决策可能受到之前一连串浏览行为的影响。因此,BDPL的做法是,在每个以购买行为结尾的子序列中,将本次购买节点与该子序列内所有先前的浏览节点都进行连接。这相当于为模型提供了更丰富的“决策依据”上下文。
实操心得:在代码实现时,构建这个图的时间复杂度是O(N^2)级别的(N为序列长度),对于长序列用户需要谨慎。一个高效的实现技巧是,先按行为类型和购买点切分序列,然后用向量化操作批量生成边索引,避免在Python循环中逐条添加。
2.2 双通道对比学习:锚定长短期偏好的“锚点”
对比学习在推荐中的应用已不新鲜,常见做法是对同一序列进行裁剪、掩码等数据增强,构造正样本对。但BDPL认为,这种序列级别的对比过于粗糙,没有区分用户偏好中“长期稳定”和“短期动态”这两个不同层面。
因此,它设计了两个独立的对比学习任务:
- 短期偏好对比:目标是让模型学会捕捉用户“当前最想要什么”。它的正样本对构造极其直接且巧妙——将用户序列的最终表示(编码了短期兴趣)与下一个真实交互的目标物品的嵌入拉近。这相当于给模型一个明确的、基于目标的监督信号:“你学到的短期兴趣,应该指向这个真实的下一个物品”。负样本则是同一批次中其他用户的下一个目标物品。
- 长期偏好对比:目标是让模型学会概括用户“一贯喜欢什么”。这里采用了子序列交换的数据增强策略。即,将用户原始序列按行为类型(如以购买为界)切分成若干子序列,然后随机交换其中两个子序列的位置,生成一个增强序列。模型需要将原始序列和增强序列的长期偏好表示拉近。因为子序列交换改变了局部顺序,但用户长期的、整体的兴趣分布应保持不变。
这种“分通道”设计的好处在于,两个对比任务的目标函数是解耦的,可以分别优化不同方面的表示能力,避免了单一对比目标可能带来的表示混淆。
2.3 级联图编码器:用目标行为净化辅助行为信息
这是另一个精妙的设计。在分别得到辅助行为(浏览)子图和目标行为(购买)子图后,如何融合它们的信息?一个简单的做法是分别编码后相加或拼接。但BDPL采用了级联(Cascade) 结构:信息流从目标行为子图流向辅助行为子图。
具体来说,先对目标行为子图进行图卷积编码,得到每个物品在“购买”这个强信号视角下的表示。然后,将这个表示通过一个可学习的变换矩阵,作为辅助行为子图编码的初始输入。其背后的动机是:目标行为(购买)是高质量、高置信度的正反馈信号。用它来引导和“净化”辅助行为(浏览)的学习过程,可以帮助模型从噪声较多的浏览行为中,筛选出那些真正导向购买意图的信息。
注意事项:这个级联结构要求两个子图的图卷积层数一致。在初始化辅助行为子图的节点特征时,直接使用目标行为子图的输出可能会造成信息淹没。论文中提到的特征变换(公式7中的
W_p)至关重要,它提供了一个缓冲层,让模型学习如何将“购买意图”特征适配到“浏览行为”的建模空间中。
3. 模型实现细节与实操要点
理解了宏观架构,我们深入到代码层面。以下是我在复现过程中,认为需要格外关注的几个模块的实现细节。
3.1 数据预处理与图构建
这是整个流程的基础,也是最容易出错的地方。
- 序列格式化:原始日志数据通常是
(user_id, item_id, behavior_type, timestamp)的流式数据。首先需要按user_id分组,并按timestamp排序,生成每个用户的异构交互序列S_u = [(v1, b1), (v2, b2), ...]。 - 行为映射与目标定义:明确哪些是辅助行为(如
view,cart,fav),哪个是目标行为(如buy)。论文中将其简化为两类:examination(检视,包含所有辅助行为)和purchase(购买,即目标行为)。在实际复杂场景中,可以保留更细的粒度。 - 构建行为感知子图:
- 遍历每个用户的序列
S_u。 - 同构边:对于连续的两个交互
(v_i, b_i)和(v_j, b_j),如果b_i == b_j,则在对应的行为子图G_b中添加一条边v_i -> v_j(正向)和v_j -> v_i(反向,如果模型设计需要)。 - 异构边(e2p):找到序列中所有目标行为(购买)的位置。对于每个购买位置
t,向前找到最近的一个购买位置t'(或序列开头),则从t'+1到t-1位置的所有辅助行为节点,都向位置t的购买节点添加一条e2p边。 - 最终,我们会得到两个图对象(或稀疏邻接矩阵的集合),分别对应
G_e和G_p,其中存储了不同类型的边。
- 遍历每个用户的序列
3.2 行为感知图编码器实现
这里需要实现一个支持多种边关系(关系类型)的图卷积网络。
- 关系型图卷积:对于每个节点,需要根据不同的边关系类型(如
e2e+,e2e-,e2p等)分别聚合邻居信息。这通常需要为每种关系类型维护一个独立的邻接矩阵或边索引列表。 - 关系注意力机制:在聚合了各类型邻居信息后,使用一个注意力网络(如公式4)为每种关系分配一个权重,然后加权求和得到该节点的综合表示。注意力权重的计算通常基于当前节点经过该关系聚合后的表示。
- 级联结构实现:先对
G_p(目标行为图)进行L层图卷积,得到最终层表示h_p。然后,将其通过一个线性变换层,作为G_e(辅助行为图)的初始节点特征h_e_0,再对G_e进行L层图卷积。最后,将两个图卷积得到的节点表示进行平均池化,得到每个物品的最终行为感知表示。
踩坑记录:在实现多关系图卷积时,最容易出现的问题是梯度消失或爆炸,尤其是在层数较深(L>2)时。解决方案包括:1)在每一层图卷积后添加LayerNorm和残差连接;2)使用更稳定的激活函数如GELU;3)仔细初始化关系注意力层的参数。
3.3 双通道对比学习模块实现
这是提升模型性能的关键,实现时需要确保正负样本构造的正确性。
-
短期对比损失:
- 正样本:用户序列经过短期偏好编码器(通常是Transformer编码器的最后时刻输出)得到的表示
z_u_s,与下一个目标物品的嵌入向量h_v_next。 - 负样本:同一训练批次中,所有其他用户的下一个目标物品嵌入。在计算损失时,使用InfoNCE损失(公式13),相似度函数常用点积或余弦相似度。
- 实现要点:需要确保在数据加载时,能方便地获取到每个序列的“下一个目标物品”的ID。通常这在数据预处理划分(留一法)时就已确定。
- 正样本:用户序列经过短期偏好编码器(通常是Transformer编码器的最后时刻输出)得到的表示
-
长期对比损失:
- 数据增强:实现子序列交换。首先需要根据目标行为将用户序列切分成子序列。交换时,论文提到了一种基于位置的采样策略,即距离源子序列越近的目的子序列,被选中的概率越高。这模拟了用户兴趣的局部连续性。
- 编码:将原始序列和增强序列分别输入长期偏好编码器(目标行为门控+序列捕获器),得到两个长期偏好表示
z_u_l和z_hat_u_l。 - 损失计算:同样使用InfoNCE损失,将
(z_u_l, z_hat_u_l)作为正样本对,同一批次中其他用户的长期偏好表示作为负样本。
3.4 偏好感知融合与预测
得到长期偏好表示 z_u_l 和短期偏好表示 z_u_s 后,使用一个自适应门控机制进行融合(公式19-20)。这个门控实际上是一个小型神经网络,输入是两者的拼接,输出一个0到1之间的标量 β,用于加权求和。
最终的预测就是计算融合后的用户表示 o_u 与所有物品嵌入向量的内积,然后通过softmax得到每个物品成为下一个交互目标的概率。损失函数是主任务推荐损失(交叉熵)与两个对比损失的加权和。
调参经验:两个对比损失项的权重
λ1和λ2对模型性能影响显著。我的经验是,在数据非常稀疏的场景下,可以适当增大λ2(长期对比)的权重,以增强模型对全局偏好的学习。λ1(短期对比)的权重通常不宜过大,否则可能会让模型过于关注当前目标而忽略序列历史。一个常见的起始设置是λ1=0.1, λ2=0.01,然后在验证集上微调。
4. 实验配置、调优与结果分析
理论再优美,也需要实验的验证。这部分分享我在复现过程中,关于实验设置、调参技巧以及对结果的一些深层分析。
4.1 数据集处理与评估准则
论文使用了Tmall、UB和JD三个公开电商数据集。处理流程是标准操作,但有几个细节值得注意:
- 冷启动过滤:过滤交互记录过少的用户和物品。阈值设置(Tmall/JD: 20/10, UB: 10/5)需要根据数据集规模调整。阈值过高会导致数据丢失严重,过低则噪声大。我的建议是,先分析数据集中用户/物品交互次数的分布,选择长尾曲线拐点附近的值。
- 序列划分:采用“留一法”,即用最后一个购买行为作为测试,倒数第二个购买作为验证,其余作为训练。务必确保按时间顺序划分,这是序列推荐的基本原则。
- 评估指标:使用全量物品排序下的HR@N和NDCG@N。这意味着对于每个测试样本,模型需要对整个物品池(可能成千上万)进行打分排序。这比采样评估(如随机采样100个负样本)要严格得多,也更能反映模型的真实能力。计算时可以使用向量化操作加速。
4.2 基线模型选择与复现挑战
论文对比了三大类15个基线模型。在复现时,确保基线模型的公平比较至关重要:
- 同质序列模型:如GRU4Rec, Caser, SASRec。需要将它们适配到异构数据。通常的做法是忽略行为类型,或者将行为类型嵌入与物品嵌入相加作为输入。论文中基线模型的结果应是在相同数据处理方式下得到的。
- 异构序列模型:如RIB, BAR, GPG4HSR。这些模型本身设计用于处理多行为数据,复现时需要严格按照原论文开源代码或描述实现其行为建模模块。
- 对比学习模型:如CL4SRec, DuoRec。需要将其对比学习策略应用到我们的异构序列数据上。注意,这些模型原本是为同质序列设计的,直接使用可能需要调整其数据增强策略(如掩码、重排序)以适配行为类型信息。
常见问题:复现时最大的挑战是超参数对齐。不同模型对学习率、批大小、嵌入维度、层数等超参的敏感度不同。必须为每个模型在验证集上独立进行网格搜索或随机搜索,找到其最优配置,然后再在测试集上比较。直接使用论文报告的参数可能因为代码库和环境的差异导致结果不一致。
4.3 消融实验设计与核心发现
消融实验是理解模型每个组件贡献度的关键。BDPL论文中应该包含,我们在复现时也必须验证的消融点包括:
- 移除行为感知图:将图编码器替换为简单的物品嵌入求和或均值池化。预期性能会显著下降,尤其是NDCG指标,这证明了显式建模行为转移关系的必要性。
- 移除级联结构:让辅助行为子图和目标行为子图独立编码,然后融合。预期性能下降,说明用目标行为信息引导辅助行为学习是有效的。
- 移除短期对比学习:只保留长期对比和主损失。预期HR@5/10这类偏重短期准确性的指标会下降。
- 移除长期对比学习:只保留短期对比和主损失。预期NDCG@20这类偏重长期列表质量的指标可能下降。
- 替换对比策略:例如,将双通道对比替换为传统的序列级对比(如CL4SRec的方法)。预期性能不如BDPL,证明分通道设计更优。
从我的复现结果来看,级联图结构和双通道对比带来的提升最为显著。尤其是在JD这类用户平均序列较短的数据集上,短期对比学习的作用非常明显,因为它提供了更强的即时监督信号。
4.4 超参数敏感性分析
几个关键超参需要系统性地调优:
- 图卷积层数L:层数越多,感受野越大,能捕获多跳关系,但也更容易引入噪声和导致过平滑。在三个数据集上,L=2通常是一个稳健的选择。
- 嵌入维度d:维度越大,表示能力越强,但也更容易过拟合。64或128是常用的起点。对于物品数超过10万的大规模数据集,可能需要增加到256。
- 对比损失温度系数τ:这是一个在InfoNCE损失中控制分布尖锐程度的超参。τ越小,模型越关注困难的负样本。通常需要在
[0.05, 0.2]之间调优。 - 融合门控的维度:公式19中的融合矩阵
W_f的输入维度是2d。在实践中,可以尝试在拼接后先经过一个小的MLP(如降维到d再升维),而不是直接映射到标量,有时能获得更精细的融合效果。
5. 工程落地思考与扩展方向
将BDPL这类研究模型应用于实际工业场景,还需要考虑许多工程和业务层面的问题。
5.1 线上服务与性能考量
BDPL模型包含图卷积和Transformer编码,相比传统序列模型计算开销更大。
- 离线训练与在线索引:模型可以离线天级别训练,为每个用户生成其长期偏好向量
z_u_l和最新的短期偏好向量z_u_s,并存储。在线服务时,实时拼接用户最近N条交互序列,通过轻量级的短期编码器(可以是小型的Transformer或GRU)快速更新z_u_s,然后与离线计算好的z_u_l融合,再进行近邻搜索(如Faiss)召回物品。这样将大部分计算量离线化。 - 图构建的实时性:用户行为图需要定期(如每小时)更新。对于新用户或新物品,存在冷启动问题。可以采用全局的、基于所有用户行为构建的“商品关系图”作为补充,或者利用属性信息生成初始嵌入。
- 模型蒸馏:如果线上延迟要求极高,可以考虑将复杂的BDPL模型蒸馏到一个更小的学生模型(如双塔DNN)上,用教师模型(BDPL)的打分作为软标签来训练学生模型。
5.2 业务场景适配与扩展
- 更多行为类型:论文简化了行为类型。实际中可能有“搜索”、“点赞”、“分享”、“看完视频”等。可以扩展行为感知图,为每种行为定义更细粒度的转移关系(如
view->fav,cart->remove等)。 - 融入上下文信息:模型目前主要处理物品ID和行为类型。可以很容易地融入物品侧特征(类别、价格)、用户侧特征(画像)、上下文特征(时间、设备)的嵌入,将其拼接或添加到节点特征/序列输入中。
- 多任务学习:除了预测下一个购买,可以同时预测下一个可能浏览或加购的物品,构建多任务学习框架。不同任务共享底层的图编码器和序列编码器,但在顶层有不同的预测头。这有助于模型学习更通用的表示。
- 与召回/排序链路结合:BDPL生成的用户偏好向量
o_u可以作为强有力的用户表征,用于召回阶段的向量化召回(如u2i, u2u2i)。也可以将其作为深度排序模型(如DeepFM, DIN)的一个重要的用户侧输入特征。
5.3 局限性与未来工作
尽管BDPL表现优异,但仍有一些局限:
- 动态兴趣漂移:模型通过短期偏好编码器捕捉动态兴趣,但对兴趣突然、剧烈变化的建模能力可能有限。未来可以探索在序列编码器中引入更显式的时间衰减门控或动态路由机制。
- 跨序列信息利用:当前模型完全基于用户自身的历史序列。如何安全、有效地利用相似用户的行为序列(即协同过滤信息)来增强稀疏用户的表示,是一个值得探索的方向,尤其是在隐私计算框架下。
- 可解释性:图神经网络的决策过程仍然是个黑盒。未来可以研究如何解释是哪些特定的行为转移路径(例如,哪几次关键的浏览最终导致了购买)对模型的预测起到了关键作用,这对于构建可信的推荐系统至关重要。
从我个人的实验和思考来看,BDPL框架的价值在于它提供了一种系统性的方法论:通过精心设计的归纳偏置(行为感知图)来注入领域知识,再通过自监督信号(双通道对比)来增强模型从稀疏数据中学习的能力。这套方法论不仅可以用于推荐,在社交网络关系预测、金融交易序列分析等任何涉及复杂、稀疏、多类型序列数据的领域,都有广阔的适配和改造空间。真正的挑战不在于复现模型本身,而在于深刻理解你所在业务领域的数据特性,然后像BDPL的设计者一样,去设计最能捕捉这些特性的“感知器”和“增强器”。