ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

KGAT模型拆解:知识图谱如何缓解推荐冷启动与稀疏交互难题

KGAT模型拆解:知识图谱如何缓解推荐冷启动与稀疏交互难题 做推荐系统这行最常被问的一个问题是用户交互数据太少模型怎么学冷启动、长尾物品、稀疏交互这几座大山压了很多年。传统协同过滤的思路是让相似用户和相似物品互相借力但数据一稀疏用户和物品的向量就学不准推荐质量也跟着崩。KGAT这篇论文给出的解法是把知识图谱作为外部信号和用户行为数据拼到同一张图里再用注意力机制自动挖掘其中的高阶关系。思路很直接但落地时有很多细节值得琢磨。这篇文章适合正在做推荐系统、尤其是接触过知识图谱但不知道如何跟推荐模型结合的同学也适合想复现KGAT实验结果的研究者。我会从模型设计的动机讲到每个模块的工作原理再补充我自己复现时踩过的坑和调参经验尽量让这篇文章不只是论文翻译而是一次能跟着动手的拆解。1. 为什么需要知识图谱协同过滤的瓶颈在哪1.1 协同过滤的冷启动与稀疏性问题先说一个几乎所有推荐团队都会遇到的场景一个用户只会跟系统里极少一部分物品发生交互。比如电商平台有1000万商品一个用户一年可能只买过20个这20个在1000万面前就是稀疏信号的极限。传统的协同过滤方法核心过程是学习用户和物品的初始嵌入向量然后通过交互矩阵去修正它们。但问题在于交互越稀疏能找到的“相似邻居”就越少向量更新时缺乏有效梯度信号最终学出来的表示往往不够有区分度。这还不算最严重的。更麻烦的是协同时存在的冷启动问题一个刚上架的新物品几乎没有任何用户交互记录协同过滤根本算不出它的嵌入向量只能随机初始化或者直接冷启动默认推荐。但对平台来说新物品往往是需要流量的这种情况就很难兼顾。我在实际项目中遇到过类似的情况新上架的商品在头几天曝光量很高点击率却低得离谱因为模型完全不知道它是什么。正是在这种背景下知识图谱被推到了前台。很多物品天然带有丰富的属性信息比如商品类目、品牌、材质、相关产品电影有导演、演员、类型、剧情标签论文有作者、领域、引用关系。这些关系如果只是当特征塞进模型往往只能解决皮毛问题起不到结构性作用。真正需要的是让模型在用户和物品之间找到“逻辑通路”跨越交互稀疏的限制。1.2 知识图谱带来的转机知识图谱本质上是一个有向异构图节点是实体边是关系。例如用户A看过电影《盗梦空间》而《盗梦空间》的导演是诺兰诺兰又执导了《星际穿越》。那么用户A和《星际穿越》之间虽然没有直接交互但通过“导演”这个关系可以建立起一条多跳的关联路径。这对于推荐来说简直是在稀疏的用户行为数据之外额外铺了一层“隐形的连带关系网”。KGAT这篇论文的核心就是抓住这种多跳关系。它不只是把知识图谱作为一个特征输入而是通过注意力机制在图上反复传播信息让用户和物品的表示能够吸收来自图谱邻居的信息。换句话说一个用户看了《盗梦空间》他的表示就会沿着图谱路径感知到诺兰、再感知到《星际穿越》从而在推荐时更有可能把《星际穿越》排到前面。这个过程不依赖用户直接看过《星际穿越》冷启动和稀疏问题就得到了缓解。当然把知识图谱引入推荐并不是KGAT首创。此前已经有CKE、CFKG这些方法尝试在同一空间里学习实体嵌入和用户嵌入也有RippleNet通过沿着知识图谱逐跳扩展用户兴趣来做推荐。这些方法各有亮点但都存在一个共性问题信息传播要么是均匀的、要么是预定义路径的无法自动区分图谱中哪些关系对当前用户更重要。KGAT要解决的恰恰就是这个“关系重要性学习”的问题。2. KGAT核心设计从协同知识图谱到注意力传播2.1 把用户和物品放进同一个图谱KGAT的第一步看起来简单却是整篇论文的基石——构建协同知识图谱Collaborative Knowledge GraphCKG。这一步做的事情是把原本分离的用户物品交互图谱和物品知识图谱拼接起来。用户物品交互图中节点是用户和物品边代表交互行为比如点击、购买、收藏。知识图谱中节点是物品和各类实体边代表语义关系比如“属于”“导演”“主演”。拼接的规则很直观因为物品同时出现在两个图中就可以作为桥梁节点将两个图连成一个统一的异构图。这样用户节点和物品节点经过若干跳就能触达知识实体比如下面这种路径就自然出现了用户A——点击——电影《盗梦空间》——导演——诺兰——执导——《星际穿越》在CKG里所有节点和关系都被映射到低维向量空间初始嵌入向量可以用随机初始化或者预训练的TransR来获得。这一步有个前人踩过的坑我留着后面在复现部分细说。重点是CKG把用户侧和知识侧打通之后后续所有信息传播才有了共同的“图底”。2.2 高阶关系是什么为什么要挖掘理解了CKG接下来就该回答一个问题为什么要挖掘高阶关系这里的高阶指的是超过一跳的路径。直接看一个例子用户A和物品B之间如果存在直接交互这算一阶信号如果用户A交互过物品B而B与物品C共享同一个实体那A和C之间就有了一条两阶路径。如果C又与用户D有交互再往下就能挖掘出更长的链式依赖。高阶关系的价值在于它能捕捉用户潜在兴趣的“传导”。还是用导演例子。用户没有直接看过《星际穿越》但他看过《盗梦空间》且两部电影共享诺兰这个导演那么“导演”这个高阶关系就能把用户的兴趣从一部电影传导到另一部。这种传导能力很大程度上就是推荐系统所谓的“泛化能力”。但如果只是把图中所有路径提取出来喂给模型计算量会爆炸。而且并非每条路径都有效有些路径甚至是噪声。KGAT的做法不是显式提取所有路径而是通过多层信息传播让每个节点在嵌入更新时逐步吸收邻域信息。理论上通过多层叠加信息可以从任意长度的路径上传播过来但受限于过平滑问题实际使用中两三层就足够了。2.3 注意力机制如何决定信息权重注意力机制是KGAT相对早期知识图谱推荐方法的显著改进。之前的RippleNet在传播用户兴趣时同一个用户的各跳邻域内实体权重是固定的并没有根据当前目标物品去动态调整。而KGAT在聚合邻居信息时会同时考虑当前节点和邻居的语义关系动态计算出这条边的重要性权重。具体来说给定节点h和它的一条出边关系r到目标节点t模型会先计算一个注意力分数score(h, r, t) LeakyReLU( W_r * (e_h ∥ e_r ∥ e_t) )其中e_h、e_r、e_t分别是头实体、关系、尾实体的嵌入向量W_r是关系对应的变换矩阵。然后把头实体所有出边的分数做softmax归一化得到每条边在信息聚合时的注意力权重。这样做的好处是模型可以自动学习“用户看过多部诺兰电影所以诺兰这个实体对他的影响应该更大”这类隐式规则而不是无差别地平均所有图谱关系。注意力计算完成之后每个节点会把邻居的信息按照权重加权聚合得到邻域表示。我和朋友讨论这篇论文时经常说这一步本质上给推荐系统装了一个“会挑重点的耳朵”图谱里的信息很多它听得到关键信息也不会忽略有用的全局信号。3. 模型训练与实现细节3.1 嵌入传播的递归流程KGAT的传播层是整个模型中最具实操细节的部分。每一层传播节点都要经历以下三个步骤计算邻域信息的加权表示利用上一节提到的注意力分数把节点h所有邻居节点t的嵌入向量按权重求和得到一个邻域聚合向量。将自身嵌入与邻域聚合向量融合这里有一个聚合器的选择问题。论文对比了三种聚合器——GCN聚合器直接相加、GraphSage聚合器拼接后经过线性变换、Bilinear聚合器双线性交互。实验结果表明GCN聚合器在多数场景下最稳定这也是复现时我优先推荐的选择。更新节点表示经过激活函数后作为下一层的输入。经过L层传播后模型会得到L个不同层的节点嵌入分别对应不同阶邻域的信息。最终表示并不是只取最后一层而是把每层嵌入做加权求和这样可以兼顾低阶和高阶信息避免过平滑导致所有节点趋于一致。这一部分的设计最能看出工程经验直接用最后一层往往会丢失局部特征而简单拼接又会放大噪声加权求和是性价比最高的折中方案。3.2 损失函数的设计KGAT的预测层用的是内积交互即用户u对物品v的预估分数就等于二者最终表示的点积。这个方案简单高效也方便线上部署时的向量检索。损失函数采用的是BPRBayesian Personalized Ranking损失搭配了一个带标签平滑的正则项。BPR的核心思想是对于每个正样本用户-物品对同时采样一个负样本物品希望正样本的打分高于负样本。比较有意思的是论文还加了一个基于知识图谱嵌入的正则项——让首尾实体通过关系变换后的距离尽可能小。这个设计有两个作用一是保持图谱结构的一致性二是约束嵌入空间防止传播过程中实体向量偏移太多而丢失图谱语义。我在复现时发现BPR损失在训练初期的下降速度很快但如果不加知识图谱正则项嵌入向量在100轮之后会出现一定程度的漂移具体表现是推荐列表里的相似物品变少、多样性下降。加了正则项之后虽然整体损失下降变缓但最终线上指标反而更稳定。这也是我常建议别人不要轻易删掉这一项的原因。3.3 关键超参数与实验设置论文的默认参数可以说是开箱即用的好配置这里列一份我复现时用的参数组合方便大家直接对照参数取值说明嵌入维度64过大会过拟合过小表达力不够传播层数L3太少信息不足太多过平滑Batch Size1024兼顾显存与收敛速度学习率1e-3属于常见范围通常不需要手动预热负采样数1BPR默认策略每个正样本采1个负样本L2正则系数1e-5防止嵌入向量过大知识图谱正则系数1e-4保持图谱结构一致性关于传播层数这里多说一句。很多同学会把层数当成免费午餐认为层数越多、高阶信息利用越充分。但实际上我试过4层之后推荐指标并没有继续上升反而在部分数据集上出现了下降。原因是过平滑随着层数加深所有节点的表示越来越相似难以区分。如果你的图谱本身很稀疏两层通常已经够用。4. 实验解读与效果分析4.1 数据集与对比方法KGAT在三个公开数据集上做了实验Amazon Book、LastFM和Yelp2018。这三个数据集覆盖了电商、音乐和本地生活三个场景而且稀疏程度不同能在一定程度上验证模型的泛化能力。对比方法选得也很有代表性。传统的基于协同过滤的方法如BPRMF、NeuMF代表的是“纯交互数据”基线CKE、SHINE、CFKG这些则是将知识图谱嵌入与协同过滤结合的方法RippleNet代表的是逐跳路径传播方法NFM这一类则是把知识图谱作为特征输送到深层模型的方法。把KGAT和这些方法放在一起对比能清楚看到它在不同技术路线上的相对优势。有一点容易被忽略论文还特意构造了一个“稀疏交互”的子集实验也就是只保留交互次数较少的用户和物品。在这个子集上KGAT的提升幅度比全量数据上更大这说明知识图谱的信号在数据稀疏时体现出的价值尤其明显。4.2 相比baseline的提升幅度在三个数据集上KGAT的整体表现都是最优的。这里挑一组我印象比较深的数据Amazon Book数据集上的Recall20从RippleNet的0.128提升到了0.165左右NDCG20从0.081提升到了0.097提升幅度大约在15%到30%之间。在LastFM和Yelp2018上也有相近比例的提高。这个幅度在推荐领域属于实打实的显著提升特别是在多个baseline已经调参到位的情况下。从相对变化来看KGAT比起CKE这类早期知识图谱推荐方法提升尤为明显。CKE虽然也用TransR来学实体嵌入但它没有显式考虑用户和实体之间的多跳传播知识图谱对推荐生成的贡献更多是作为物品的“附加特征”属于旁路信息。KGAT则把图谱信息真正引入了用户-物品交互传导链中两相对比差距是能和注意力机制的设计直接挂钩的。4.3 消融实验的启示论文的消融实验做得也很干净。作者对比了去掉注意力机制的KGAT变体即所有邻居权重相等之后各数据集上的指标都有所下降这说明注意力机制确实在甄别重要关系时发挥了关键作用。还对比了不同聚合器的效果GCN聚合器表现最佳GraphSage聚合器次之Bilinear聚合器相对较弱。这套消融实验给到我的启发是论文里每个组件都提供了真实性的贡献度检验。复现时我没必要一开始就把所有模块一次性堆上去可以先从最基础的传播层开始然后逐步加入注意力、聚合器、知识图谱正则把每一步对最终指标的影响记录在案。这种“增量式复现”的方法也方便定位自己在实现过程中哪里出了问题比起一把梭调试要高效得多。5. 踩坑实战复现KGAT的经验总结5.1 数据预处理容易出错的地方复现KGAT最大的坑往往不在模型代码里而在数据预处理阶段。构建CKG时用户、物品、实体、关系需要共享一套索引如果物品ID和实体ID没有对齐会导致图和交互表之间出现空洞训练时看起来在跑实际信息传播路径是断的。我在第一次复现时就因为在拼接两个图之前少做了ID映射导致运行结果和论文数据差距巨大排查了整整一天。另一个容易踩的坑是关系方向的处理。知识图谱中的关系是有向的但很多人构建邻接表时会把所有边当成无向边来处理。理论上KGAT的传播层支持双向传播但如果你的知识图谱自带方向语义比如“导演”和“执导”本身是互为反向的关系就不应该把它们合并成同一条边否则模型会丢失关系方向的信息。正确做法是原样保留每个三元组的方向并且在聚合邻居时既考虑出边邻居也考虑入边邻居。5.2 训练过程中的调参心得训练KGAT的过程中我踩过两个比较有代表性的坑。第一个是学习率选择。论文默认1e-3看起来没什么问题但如果数据集规模很大且Batch Size超过20481e-3会导致训练初期损失出现明显震荡。我最后的做法是采用学习率预热策略前5轮用较小的学习率比如1e-4做热身之后再切换到1e-3收敛速度和稳定性都有明显提升。第二个是嵌入维度的选择。很多人以为64维嵌入太低了想换成256维但实际上图模型的表达能力不仅取决于维度还取决于传播层融合的信息广度。在Amazon Book这种大规模数据集上64维加3层传播的效果已经接近256维加2层传播的效果而前者训练速度快了不止一倍。也就是说如果离线实验资源有限优先加深传播层数往往比加大嵌入维度更划算。5.3 对小数据集友好的改进建议如果手里的数据规模不大不建议直接套用论文的完整模型因为KGAT的注意力机制和深层传播在小规模数据上容易过拟合。一种可行的思路是减少传播层数到2层并把注意力权重的计算换成简单的点积形式减少参数量的同时也能保留主要性能。另一个思路是使用在知识图谱上预训练好的实体嵌入作为初始化再微调传播层的参数这能显著加快收敛速度。此外我还试过一个非常有效的小数据技巧把交互行为中的“点击”和“购买”等不同动作拆成不同的关系边。这样做虽然增加了图的复杂度但给模型提供了更多细粒度的信号来源在小数据集上效果提升比较明显。这个思路其实也符合KGAT的本意——把不同类型的语义关系都显式建模而不是统一当成普通交互。最后再分享一个小技巧。如果你打算把KGAT用到线上建议把用户和物品的最终表示导出成向量表用向量检索库做召回而不是在线上实时跑整个图传播。KGAT图传播部分虽然效果不错但毕竟涉及多层邻居聚合线上延迟不可控。离线预计算向量、线上近似最近邻检索是更工程化也更可落地的做法。我在实际项目中就是按这个思路做的既保留了KGAT的精度优势又保证了线上性能。
返回列表