【图神经网络】DGL实战:异构图神经网络在推荐系统中的应用

1. 从零开始:为什么推荐系统需要异构图?

如果你做过推荐系统,或者哪怕只是用过一些App,你肯定遇到过这样的场景:淘宝猜你喜欢、抖音的“下一个视频”、网易云音乐的每日推荐。这些系统是怎么知道你可能喜欢什么的?传统的方法,比如协同过滤,简单来说就是“喜欢A物品的人也喜欢B物品,所以推荐给你B”。这方法在早期很有效,但问题也很明显:它把用户和物品都当成了一个个孤立的ID,忽略了用户本身丰富的属性(年龄、性别、浏览历史)和物品复杂的特征(品类、价格、描述文本)。

这就好比给你介绍对象,媒人只告诉你“之前和TA相亲过的人都挺满意”,却完全不提对方的性格、爱好、职业。你心里肯定没底。推荐系统也一样,我们需要更丰富的“信息”来做判断。

这时候,图(Graph) 就登场了。我们可以把用户和物品都看作图上的“节点”,用户点击、购买、评分这些行为就是连接他们的“边”。这样一来,整个推荐系统的数据就构成了一张巨大的网络图。但问题又来了,用户节点和物品节点是两种完全不同的东西,它们的特征维度、含义天差地别。比如用户特征可能是[年龄=25, 城市=北京],而物品特征可能是[品类=手机, 价格=3999]。用传统的、只处理单一类型节点的同构图神经网络(GNN)来处理,就像让一个只会说中文的人去理解法文和德文混在一起的文档,非常别扭。

所以,我们需要异构图神经网络(Heterogeneous Graph Neural Network)。它就像个多语言专家,能同时理解“用户”和“商品”这两种不同的“语言”,并学习它们之间复杂的交互模式。DGL(Deep Graph Library)是目前最流行的图神经网络框架之一,它对异构图的原生支持做得非常好,让我们可以相对轻松地搭建和训练这类模型。

我刚开始接触异构图时,也觉得概念有点绕。但后来想明白了,其实它就是把现实世界中复杂的关系网络,用一种更贴近本质的方式建模。一旦用图把数据组织起来,很多问题就变得直观了。比如,要预测用户会不会买某个商品,本质上就是预测图上这两个节点之间会不会产生一条新的“购买”边,这就是典型的链接预测任务。而异构图神经网络,就是用来解决这类任务的利器。

2. 动手之前:用DGL构建你的第一张异构图

理论说再多,不如动手跑一行代码。在开始构建复杂的模型之前,我们得先把数据“图化”。DGL提供了非常直观的接口来创建和处理异构图,咱们一步步来。

首先,假设我们有一个简单的电影推荐场景,有三种节点:用户电影导演;有两种边:用户-评分->电影电影-由->导演。评分边可能还带有属性,比如分数(1-5分)。

2.1 创建异构图对象

在DGL里,创建异构图的核心是 dgl.heterograph 函数,它接受一个字典来定义不同类型的边。这是最关键的一步,我刚开始也在这里卡过。

import dgl
import torch

# 定义图结构数据
graph_data = {
    # 边类型: (源节点类型, 边类型, 目标节点类型)
    ('用户', '评分', '电影'): (torch.tensor([0, 0, 1, 2]), torch.tensor([0, 1, 1, 2])),  # 用户0评分了电影0和1,用户1评分了电影1,用户2评分了电影2
    ('电影', '由', '导演'): (torch.tensor([0, 1, 2]), torch.tensor([0, 1, 0])),  # 电影0由导演0执导,电影1由导演1执导,电影2由导演0执导
}

# 创建异构图
hetero_graph = dgl.heterograph(graph_data)
print(hetero_graph)

运行这段代码,你会看到类似这样的输出:

Graph(num_nodes={'用户': 3, '电影': 3, '导演': 2},
      num_edges={('用户', '评分', '电影'): 4, ('电影', '由', '导演'): 3},
      metagraph=[('用户', '电影', '评分'), ('电影', '导演', '由')])

这告诉我们,图里有3类节点,数量分别是3、3、2;有2类边,数量分别是4和3。metagraph 展示了图的元结构,清晰明了。

2.2 为节点和边添加特征

光有结构还不够,我们需要把丰富的特征信息附加上去。DGL允许我们为不同类型的节点和边分别设置特征。

# 为用户节点添加特征,假设每个用户有2个特征(例如:年龄、活跃度)
hetero_graph.nodes['用户'].data['feat'] = torch.randn(3, 2)
# 为电影节点添加特征,假设每个电影有3个特征(例如:类型编码、上映年份、预算)
hetero_graph.nodes['电影'].data['feat'] = torch.randn(3, 3)
# 为导演节点添加特征,假设每个导演有2个特征(例如:获奖次数、从业年限)
hetero_graph.nodes['导演'].data['feat'] = torch.randn(2, 2)

# 为‘评分’边添加特征,例如评分分数
hetero_graph.edges['评分'].data['rating'] = torch.tensor([5.0, 4.0, 3.0, 2.0])
print("用户特征:", hetero_graph.nodes['用户'].data['feat'])
print("评分边特征:", hetero_graph.edges['评分'].data['rating'])

这里我用了随机生成的张量来模拟特征,真实项目中,这些特征来自你的数据预处理,比如用户画像的向量、物品的嵌入向量或者文本特征的编码。为不同类型的节点分配不同维度的特征,这正是异构图灵活和强大的地方。你可以根据数据的实际情况自由设计,比如用BERT编码电影简介作为电影节点的初始特征。

2.3 异构图的基本操作

创建好图之后,我们经常需要查询和操作它。DGL的API设计得很人性化。

# 1. 获取特定类型的子图
user_movie_subgraph = hetero_graph['用户', '评分', '电影']
print(f"用户-电影子图的边数: {user_movie_subgraph.num_ed
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值