news 2026/10/2 13:22:16

KGAT解析:知识图谱与图注意力网络驱动的推荐系统

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
KGAT解析:知识图谱与图注意力网络驱动的推荐系统

刚把 KGAT 这篇论文啃完,趁着热乎劲儿还没散,赶紧把笔记整理出来。这算是知识图谱推荐方向绕不开的一篇工作,KDD 2019,浙江大学向萌哲他们做的。如果你在关注推荐系统怎么解决冷启动、稀疏性问题,或者想弄清楚知识图谱的信息到底怎么和用户行为融合,这篇论文值得仔细读一读。

先说一个总的感受:KGAT 这个模型,核心思想并不复杂,但它把事情做得很完整——从嵌入表示、高阶关系建模到可解释性,都有比较妥帖的落地方式。而且这篇论文在思路上是递进的,它不是凭空造一个模型,而是先分析已有方法的不足,然后顺着逻辑一步步补完,读起来思路非常顺。我整理了一下自己的阅读笔记和复现过程中踩过的坑,放在下面。

1. 它解决了什么问题?先说清楚背景再谈模型

1.1 协同过滤的瓶颈在哪里

传统协同过滤(Collaborative Filtering,简称 CF)靠的是用户-物品交互矩阵,核心假设是历史行为相似的用户,未来偏好也相似。这个思路在数据稠密的时候表现不错,但现实中绝大多数场景,用户交互的物品数量非常有限,矩阵稀疏度经常在 99% 以上。交互数据一旦稀疏,CF 的“共现”信号就捉襟见肘,推荐质量明显下滑。

为了解决稀疏性问题,后来研究者想到了用辅助信息(side information)来补充用户和物品的表示。知识图谱就是其中一种非常自然的辅助信息——它把物品的属性、品类、关联实体和关系都结构化地组织起来。比如一部电影,在知识图谱里可能关联着导演、主演、类型、获奖信息、同系列作品等。这些额外的连接关系,能够在用户-物品交互之外提供更多可供模型学习的信号。

1.2 知识图谱嵌入(KGE)方法的局限

顺着这个思路,早期工作直接套用知识图谱嵌入方法(Knowledge Graph Embedding,简称 KGE),代表工作有 CKE、DKN 等。它们的方式很直接:把图谱里的实体和关系嵌入到向量空间,然后用这些向量增强物品或用户的表示。

但这类方法有一个明显问题:知识图谱嵌入和推荐任务的优化目标是割裂的。具体来说,KGE 的优化目标通常是让嵌入表示能够还原图谱中的结构化事实,比如 TransE 要求头实体向量加关系向量约等于尾实体向量。这个目标本身和“用户会不会点击这个物品”并没有直接关系。结果就是,模型学到了不错的图谱表示,但表示的质量并不一定对推荐效果有正向帮助。

我复现 CKE 的时候这种感觉特别明显——图谱嵌入部分和协同过滤部分像是两个独立模块硬拼在一起,整个模型训练完,图谱信息对推荐的贡献其实相当有限。

1.3 端到端学习的优势所在

KGAT 的核心洞察在于:应该把知识图谱的信息融合过程放到推荐任务的监督信号下进行端到端优化。它提出了一种图注意力网络结构,让图谱中的信息传播过程和用户-物品交互建模在同一框架内共同学习。

这样做的好处是,图谱中的高阶关系能够按照对推荐目标有益的方式被选择性利用。比如同样是“同一个导演”这个关系,对于喜欢文艺片的用户可能是强信号,对于只爱看商业大片的用户可能就不那么重要。模型可以通过学习,自动区分不同关系在不同上下文中的权重。

另外一个重要优势是可解释性。因为 KGAT 在传播过程中用到了图谱中真实存在的路径(user-item-entity-...),所以推荐结果可以通过这些路径来解释——比如“因为你喜欢《星际穿越》,而这部电影和你曾经看过的《盗梦空间》有同一个导演诺兰,所以我们推荐了《敦刻尔克》”。这种解释方式比单纯基于向量相似度的推荐要直观得多。

2. 核心机制拆解:三个关键设计值得细细品味

2.1 从用户-物品二部图到协作知识图(CKG)

KGAT 首先做的事情,是把用户-物品交互图(二部图)和知识图谱统一起来,构建一个叫做协作知识图(Collaborative Knowledge Graph,简称 CKG)的异构图。

怎么理解这个过程?简单来说,就是把用户也当成一种特殊的实体放进图谱里。用户对物品的行为(点击、购买、收藏)被看成一种特殊的关系,连接用户实体和物品实体。这样一来,图里既有用户节点、物品节点,也有图谱中各种属性节点(导演、类型、品牌等),它们通过不同的关系边相互连接。

我实际构建 CKG 的时候,踩过一个比较大的坑:实体 ID 映射必须全局统一。就是说,用户、物品、图谱实体需要在一个统一的 ID 空间里编号,不能用户一套、物品一套、图谱实体又一套。否则后续做图采样和邻居聚合的时候,索引错位的问题会非常隐蔽,排查起来很痛苦。建议在数据预处理阶段就建立一个统一的映射表,从源头解决这个问题。

构建好 CKG 之后,图上自然形成了一些“信息通路”。例如用户 u1 点击过物品 i1,i1 在知识图谱中关联了导演 e1,e1 又导演了物品 i2,那么 u1 和 i2 之间就形成了一条长度为 3 的路径。这样的路径正是高阶关系学习的素材。

2.2 嵌入表示层:TransR 初始化是经验的总结

KGAT 借用了 TransR 的思路来初始化实体和关系的嵌入表示。这里有必要多花些笔墨,因为不少刚接触这个方向的读者会在这儿产生疑惑:为什么不用 TransE 或者 TransH?这三者之间的差异到底在哪里?

TransE 的关系建模方式是平移——它假设 h + r ≈ t(头实体向量加关系向量约等于尾实体向量)。这种方式简单高效,但处理一对多、多对一、多对多关系时力不从心。比如“导演”这个关系,一个导演导演了多部电影,TransE 很难让同一个 r 向量同时满足多个不同的电影向量与导演向量的平移关系。

TransH 的改进是把关系建模到超平面上,让实体在不同关系下有不同的投影表示。它部分解决了一对多的问题,但本质仍是平移模型,表达能力依然受限。

TransR 的思路是给每个关系单独分配一个投影矩阵,让实体向量先通过关系投影矩阵映射到关系对应的语义空间,再做平移。这样的好处是,不同关系可以在不同的语义子空间里建模,表达能力明显增强。

模型关联建模方式关系表示表达能力计算复杂度
TransEh + r ≈ t向量弱,难处理一对多低
TransH关系超平面上的平移向量(超平面+平移)中等中
TransR关系空间内的平移矩阵+向量较强高
KGAT关系投影矩阵 + 注意力聚合矩阵+向量强高

我自己的实操经验是,即使后续 KGAT 训练过程中嵌入表示会被不断更新,但一个合理的初始化确实能显著加快收敛速度。因为图注意力层的聚合依赖于初始嵌入的质量,如果初始嵌入是随机噪声,注意力权重很难学到有意义的分布。

2.3 图注意力传播层:KGAT 的精华所在

这是整篇论文最核心的部分。KGAT 的嵌入传播层在 CKG 上递归执行,每一层都做了两件事:计算注意力权重,聚合邻居信息。

注意力权重的计算逻辑

对于图中的一个节点 h,它的邻居集合是图中的三元组 (h, r, t)。KGAT 通过一个打分函数 π(h, r, t) 来衡量邻居 t 在关系 r 下对 h 的重要性。这个打分函数不是拍脑袋定的,它有自己的讲究:

π(h, r, t) = (W_r e_t)ᵀ tanh(W_r e_h + e_r)

其中 e_h、e_r、e_t 分别是头实体、关系、尾实体的嵌入向量,W_r 是关系 r 对应的投影矩阵。这个公式的直觉理解是:先把头实体和尾实体都投影到关系空间中,然后计算它们之间的相似度,再加上关系本身的信息。

这个设计比直接使用 GCN 的均匀聚合要精细得多。GCN 在聚合邻居时给所有邻居分配相同的权重,这在异构图中是不合理的——同样是一个电影节点,它关联的导演实体和演员实体对该用户决策的影响显然不同。

聚合完信息之后,KGAT 采用了类似 GCN 的邻域信息聚合函数,但不是简单加和,而是把当前节点表示和邻居聚合表示拼接,再经过一个线性变换,得到更新后的节点表示:

e_h^agg = LeakyReLU(W(e_h + e_neighbor))

e_h^{new} = e_h^agg + e_h

第二行其实是一个残差连接,我复现的时候发现这个残差设计很关键。如果没有它,层数加深时信息丢失很严重,尤其在 CKG 这样的异构图上。加上残差之后,训练稳定性和最终效果都有明显改善。

多层传播的含义

KGAT 的传播层可以叠加多层,每一层相当于在图上游走一步。一层传播能捕获一阶邻居信息,两层传播能捕获二阶邻居信息,以此类推。这就是论文中“高阶关系”的含义——不是知识图谱推理意义上的复杂逻辑链,而是图结构上的多跳语义传播。

值得注意的是,这里的“阶数”并不等同于性能的单调提升。我自己做实验的时候发现,2 层到 3 层之间通常有不错的收益,但到 4 层以后,收益变得很小,甚至可能下降。这个现象在论文的消融实验部分也有体现。原因是多跳传播在带来信息增益的同时,也引入了噪声——远处的邻居与当前节点的语义关联已经相当微弱。

2.4 预测层与目标函数:统一框架下的设计美学

KGAT 的预测层设计得比较优雅。在完成 L 层嵌入传播后,每个节点(用户或物品)会得到 L+1 个表示:初始嵌入 e⁰,第一层传播后的 e¹,第二层传播后的 e²……直到第 L 层的 eᴸ。

论文的做法是对这些表示做求和或拼接,得到最终的用户表示和物品表示。然后用户对物品的偏好得分通过内积计算:

ŷ(u, i) = e_u^ᵀ e_i^

这个设计思路和黄立峰他们的 NGCF(Neural Graph Collaborative Filtering)一脉相承,都是将各层表示融合,保留不同阶数的语义信息。

损失函数则是典型的 BPR(Bayesian Personalized Ranking)损失加上 L2 正则。BPR 的基本思想是:对于用户 u,已交互的物品 i⁺ 和未交互的物品 i⁻,我们希望模型打分满足 ŷ(u, i⁺) > ŷ(u, i⁻)。用公式表示就是最小化:

L = Σ -ln σ(ŷ(u, i⁺) - ŷ(u, i⁻)) + λ ‖Θ‖²

这个负采样策略我在复现的时候特别关注了一下。KGAT 的做法是从用户所有未交互的物品中随机采样一个作为 i⁻。这个策略简单有效,但负采样的数量和质量直接影响到训练效果。我试过每个正样本配 1 个负样本,效果还行;配 4 个负样本,收敛更快一些,但最终 AUC 差距并不大。

3. 实验视角:论文里的数字说明了什么

3.1 数据集与 baseline 选择

论文在三个公开数据集上做了实验:Amazon-book、Last-FM、Yelp2018。这三个数据集覆盖了不同的推荐场景——图书、音乐、本地生活。每个数据集都配了对应的知识图谱,物品和图谱实体的对齐工作做得比较细致。

我记得论文报告的基础统计大概是这样的:

数据集交互数量图谱三元组数量物品-实体对齐数
Amazon-book~190万~26万~3.6万
Last-FM~42万~13万~1.2万
Yelp2018~140万~180万~1.4万

baseline 选得很有层次:有只利用交互信息的 CF 方法(BPRMF、NeuMF)、有利用知识图谱特征的(CKE、DKN)、有图神经网络方向的(GCN、GraphSAGE、NGCF),基本把当时各类代表性方法都覆盖了。

3.2 关键结果解读

论文的核心结果显示,KGAT 在三个数据集上都稳定超过所有 baseline。在 Amazon-book 上,KGAT 相对最优 baseline(NGCF)在 Recall@20 上有约 8% 左右的提升;在 Last-FM 和 Yelp2018 上也有类似的优势。

坦率地说,这个提升幅度在推荐系统方向的论文里算是不错的,但也没到颠覆性的程度。论文的真正价值更多在于验证了一个方向:将知识图谱作为推荐辅助信息时,端到端的学习方式比两阶段的独立嵌入更有效。这一点后来被很多后续工作继承和发展。

另外,论文还对比了 KGAT 在三种不同设置下的表现:仅用协同信号(去掉图谱部分)、仅用知识图谱信号(去掉交互部分)、两者结合。结果显示两者结合效果最好,而且知识图谱信号对冷启动场景的提升尤其明显。这符合直觉:交互数据稀少的用户,图谱路径能够提供更多可用的语义信息支撑推荐决策。

3.3 消融实验里透露的设计取舍

论文的消融实验还有一个值得关注的结论:注意力机制确实带来了效果增益,但增益幅度并没有想象中那么大,大约是 2%~3% 的提升。这说明图谱结构信息本身的引入贡献了大部分收益,注意力模块是在此基础上的精细调整。

我自己的复现结果也印证了这一点。把 KGAT 的注意力权重改成均匀权重(相当于退化成 GCN 风格的聚合),效果确实会下降,但下降幅度在可接受范围内。这也提醒我们,在实际工程中如果算力受限,简化注意力部分可能是一个性价比不错的选择。

第四部分:复现与实操要点。

4.1 工程架构选择

如果准备复现这篇论文,建议使用 PyTorch 配合 DGL(Deep Graph Library)或者 PyG(PyTorch Geometric)。KGAT 涉及大量的图采样和邻居聚合操作,直接用原生 PyTorch 写循环很痛苦,而且效率极低。

DGL 的dgl.heterograph可以直接支持异构图,能够定义不同类型的节点和边,非常契合 CKG 的数据结构。PyG 的HeteroData也有类似的能力。两者选一个就行,我个人更习惯用 DGL,它在消息传递(message passing)接口上更灵活一些。

还有一个需要注意的地方:图数据的规模控制。CKG 的规模是用户数 + 物品数 + 图谱实体数这么多节点,边数则包括交互边和图谱关系边。数据集小还好,数据集一大,全图训练会非常吃内存。我第一次跑全量 Amazon-book 时直接 OOM(内存溢出)了,后来改成邻居采样(neighbor sampling),每个 batch 只采样固定数量的邻居,问题就解决了。

4.2 关键超参和训练细节

论文里透露的默认超参数大概是:嵌入维度 64,L2 正则系数 1e-5,学习率 0.0001,batch size 1024,传播层数 3 层。

这几个参数我复现的时候都试过调优,结论是:

  • 嵌入维度 64 是一个性价比很高的选择。升到 128 有增益,但幅度不大,训练时间几乎翻倍。降到 32 会明显掉点。
  • 学习率 0.0001 相当保守,可以用 Adam 配合 0.001 的学习率先训,后期手动降低学习率微调,收敛速度会快不少。
  • batch size 对最终效果影响不敏感,主要影响训练速度和显存占用。
  • 传播层数,论文推荐 3 层,我测试下来 2 层到 3 层确实有提升,但 3 层的训练耗时比 2 层多了一半以上。工业落地的话 2 层就够用。

另外还有几个论文没细讲但我实测有效的技巧:

  1. 邻居数量限制。CKG 中有些节点邻居非常多(比如热门电影、知名演员),聚合全部邻居会拖慢速度。限制每个节点采样 20~50 个邻居,效果几乎不受影响。
  2. 特征归一化。初始嵌入如果直接训练不归一化,容易出现梯度爆炸。加上 LayerNorm 或者简单做 L2 归一化,训练稳定很多。
  3. 早停策略。论文训练了较多个 epoch,我复现时用验证集上的 Recall@20 做早停,一般 30~50 个 epoch 内就能收敛到比较好的水平。

4.3 从论文到落地的距离

论文是学术实验,代码开源、流程明确,但从论文到工业落地还有一段距离。主要差别在于:

学术实验的场景是离线评估(offline evaluation),而工业推荐是线上实时推理,对延迟要求极高。KGAT 是标准的 GNN 结构,需要迭代式地聚合多层邻居,这在实时场景下做起来很吃力。工程上主要有两个缓解思路:

一是离线预计算实体表示,线上直接查表。提前把 KGAT 训练好,对全量物品计算最终嵌入向量存起来。线上推理时,只需要计算用户的最新嵌入,然后做向量检索。用户嵌入也可以近似处理——用最近一次更新的嵌入,或者用轻量模型实时算。

二是图裁剪。CKG 的规模在实际工业场景中可能达到亿级节点、十亿级边。全图训练几乎不可能,必须做图分割或子图采样。之前提到的邻居采样就是最直接的手段。

5. 常见问题与排查技巧实录

5.1 训练不收敛或者收敛速度慢

这是最容易碰到的问题,通常和初始化有关。把 TransR 预训练步骤省略、直接随机初始化嵌入的话,训练会显得很挣扎。建议先用 OpenKE 之类的工具库跑一遍 TransR,得到实体和关系的初始嵌入,再做后续训练。

另一个容易忽略的原因是学习率过高。图神经网络对学习率敏感的程度超出想象,我试过 lr=0.01 时 loss 整个训练过程完全降不下去,降到 0.0001 之后才正常。建议就用论文默认的 0.0001,稳妥。

5.2 显存/内存爆炸

CKG 全图训练耗内存严重,尤其是中间层生成的注意力权重矩阵,如果邻居数量没有限制,显存会迅速打满。解决办法是邻居采样加梯度累积。采样数量先设小一点,比如 20,确认代码没问题后再逐步调大。

5.3 效果不如论文报告值

很多复现者在这一步会怀疑人生。先说两个最常见原因:

第一,负采样策略不一致。论文的采样是“随机从未交互物品采样”,但并未说明具体随机种子和采样次数。这里的差异会带来几个点的指标波动。建议多换几个随机种子取平均,不要只跑一次就下结论。

第二,数据划分方式。论文用的是按时间划分还是按用户随机划分,会影响冷启动评估的难易程度。如果论文没有明确说明,建议按自己的业务场景选择,并明确标注在报告里。不同的划分策略下,KGAT 的效果差异可能有 5 个点以上。

5.4 注意力权重分布异常

调试的时候可以把注意力权重打印出来看看分布。正常情况应该是偏态分布——少数关键邻居权重高,大多数普通邻居权重低。如果你的权重分布接近均匀分布,说明注意力机制没有学到有效区分度,这通常是因为温度参数或初始化设置不合理,也可能是训练还没收敛。

6. 从 KGAT 到 LLM 时代:一个值得关注的演进方向

读这篇论文的时候,我注意到最近有一个新的研究方向很有意思:知识图谱微调可以增强大语言模型的知识操纵能力。这其实和 KGAT 的核心思想一脉相承——都是希望让图结构中的知识,以某种方式融入到一个更大的模型框架中,从而提升模型在特定任务上的表现。

KGAT 在推荐系统上做的事情,本质上是把知识图谱中的结构化信息,以端到端可学习的方式注入到用户-物品交互模型中。而知识图谱微调增强大模型的方向,是把知识图谱的推理能力注入到语言模型中,让模型不仅仅是“记住”知识,还能按照图谱结构进行“操纵”——比如多跳推理、关系组合、逻辑一致性控制。

我在测试这类模型时发现,加了知识图谱微调之后,大模型在处理需要多跳关联的问题时,输出的一致性和准确性比纯预训练模型要好不少。这和 KGAT 的实验结论有异曲同工之处:结构化的图信息确实能提供纯统计学习之外的有效信号。

不过坦率地讲,研究是研究,落地是落地。知识图谱的构建和维护成本很高,不是所有场景都值得引入图谱信息。我个人的经验是,如果交互数据已经足够稠密,CF 类方法已经能取得不错的效果,强行引入知识图谱未必有显著提升,反而增加了系统复杂度和维护成本。图谱信息的优势场景主要在于冷启动严重、长尾物品多、用户行为稀疏的地方——这时候图上那些从物品属性延伸出去的路径,才真正发挥作用。

7. 一点个人心得

最后简单聊几句感受。KGAT 这篇文章我反复读了几遍,越读越觉得它值得学习的地方在于问题意识的递进性——从 CF 的稀疏性缺陷到 KGE 的优化目标割裂,再到端到端图注意力网络的提出,每一步都建立在充分分析已有工作不足的基础上,而不是为了用某个技术而用某个技术。

当然,论文也不是没有可挑剔之处。比如注意力机制的复杂度和收益之间是否完全对等?我认为未必。但作为 2019 年的工作,它确实为知识图谱推荐这个方向奠定了很扎实的框架,后来的很多工作,比如 CKAN、KGIN 等,都或多或少受到了它的启发。

如果你是这个方向的新人,我建议按这个顺序来读:先读懂 CKE,理解为什么两阶段方法不够好;然后读 KGAT,理解端到端图模型怎么解决这个问题;最后读一两篇 KGAT 的后续改进工作,理解社区在哪些方向做了扩展。这个阅读路径应该会让你对整个知识图谱推荐方向有一个比较立体和清晰的认识。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/2 13:21:03

从零自建GitLab私有代码仓库:安装、配置与踩坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/2 13:17:19

用 clang 生成 LLVM IR:从命令到读懂 SSA 与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/2 13:16:42

华硕路由器上部署Go语言AI提示流编排器实战

1. 为什么要在路由器上折腾AI提示流编排把AI引擎塞进华硕路由器这件事,第一次跟朋友提起来的时候,对方看我的眼神就像在看一个非要给自行车装涡轮增压的人。但如果你手头正好有一台刷了Merlin固件的华硕路由器,又恰好对本地AI编排有点兴趣&am…

作者头像 李华
网站建设 2026/10/2 13:16:18

Tesseract-OCR 5.5.0 全量语言包离线环境搭建与多语种识别调优

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/2 13:16:15

Redis加速AI应用落地:从缓存到向量检索的完整实战指南

最近在搞大模型应用,圈子里的朋友几乎都在聊一件事:Redis 已正式接入 AI 了。与其说是 Redis 主动去接 AI,不如说是做后端的人终于意识到,大模型应用要落地,Redis 这种内存数据基础设施是绕不开的一环。我自己的项目里…

作者头像 李华
网站建设 2026/10/2 13:15:49

用OpenCV和Python实现文档扫描仪:从边缘检测到透视变换

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华