本项目链接:https://aistudio.baidu.com/aistudio/projectdetail/5009827?contributionType=1 有疑问查看原项目
相关项目参考:
关于图计算&图学习的基础知识概览:前置知识点学习(PGL)[系列一] https://aistudio.baidu.com/aistudio/projectdetail/4982973?contributionType=1
图机器学习(GML)&图神经网络(GNN)原理和代码实现(前置学习系列二):https://aistudio.baidu.com/aistudio/projectdetail/4990947?contributionType=1
图学习【参考资料2】-知识补充与node2vec代码注解: https://aistudio.baidu.com/aistudio/projectdetail/5012408?forkThirdPart=1
图学习【参考资料1】词向量word2vec: [https://aistudio.baidu.com/aistudio/projectdetail/5009409?contributionType=1](https://aistudio.baidu.com/aistudio/projectdetail/5009409?contributionType=1
在图结构中有一个重要概念,同构图和异构图:
同构图:节点类型仅有一种的图
异构图:节点类型有多种的图,举例如下:
异质图介绍 在真实世界中,很多的图包含了多种类别节点和边,这类图我们称之为异质图。显然,同构图是异质图中的一个特例,边和节点的种类都是一。异质图比同构图的处理上更为复杂。 为了能够处理实际世界中的这大部分异质图,PGL进一步开发了图框架来对异质图模型的支持图神经网络的计算,新增了MetaPath采样支持异质图表示学习。
本节:
PGL中引入了异质图的支持,新增MetaPath采样支持异质图表示学习,新增异质图Message Passing机制支持基于消息传递的异质图算法,利用新增的异质图接口,能轻松搭建前沿的异质图学习算法。
真实世界中的大部分图都存在着多种类型的边和节点。其中,电子交易网络就是非常常见的异质图。这种类型的图通常包含两种以上类型的节点(商品和用户等),和两以上的边(购买和点击等)。 接下来就用图例介绍,图中有多种用户点击或者购买商品。这个图中有两种节点,分别是“用户”和“商品”。同时包含了两种类型的边,“购买”和“点击”。
以及学术论文
在异质图中,存在着多种边,我们需要对它们进行区分。使用PGL可以用一下形式来表示边:
'click': [(0, 4), (0, 7), (1, 6), (2, 5), (3, 6)],
'buy': [(0, 5), (1, 4), (1, 6), (2, 7), (3, 5)],
}
clicked = [(j, i) for i, j in edges['click']]
bought = [(j, i) for i, j in edges['buy']]
edges['clicked'] = clicked
edges['bought'] = bought
# 在异质图中,节点也有不同的类型。因此你需要对每一个节点的类别进行标记,节点的表示格式如下:
node_types = [(0, 'user'), (1, 'user'), (2, 'user'), (3, 'user'), (4, 'item'),
(5, 'item'),(6, 'item'), (7, 'item')]
# 由于边的类型不同,边的特征要根据不同类别来区分。
import numpy as np
import paddle
import paddle.nn as nn
import pgl
from pgl import graph # 导入 PGL 中的图模块
import paddle.fluid as fluid # 导入飞桨框架
seed = 0
np.random.seed(0)
paddle.seed(0)
num_nodes = len(node_types)
node_features = {'features': np.random.randn(num_nodes, 8).astype("float32")}
labels = np.array([0, 1, 0, 1, 0, 1, 1, 0])
# 在准备好节点和边后,可以利用PGL来构建异质图。
g = pgl.HeterGraph(edges=edges,
node_types=node_types,
node_feat=node_features)
#如果遇到报错显示没有pgl.HeterGraph,重启项目即可
# 在构建了异质图后,我们可以利用PGL很轻松的实现信息传递范式。在这个例子中,我们有两种类型的边,所以我们定义如下的信息传递函数:
class HeterMessagePassingLayer(nn.Layer):
def __init__(self, in_dim, out_dim, etypes):
super(HeterMessagePassingLayer, self).__init__()
self.in_dim = in_dim
self.out_dim = out_dim
self.etypes = etypes
self.weight = []
for i in range(len(self.etypes)):
self.weight.append(
self.create_parameter(shape=[self.in_dim, self.out_dim]))
def forward(self, graph, feat):
def send_func(src_feat, dst_feat, edge_feat):
return src_feat
def recv_func(msg):
return msg.reduce_mean(msg["h"])
feat_list = []
for idx, etype in enumerate(self.etypes):
h = paddle.matmul(feat, self.weight[idx])
msg = graph[etype].send(send_func, src_feat={"h": h})
h = graph[etype].recv(recv_func, msg)
feat_list.append(h)
h = paddle.stack(feat_list, axis=0)
h = paddle.sum(h, axis=0)
return h
# 通过堆叠两个 HeterMessagePassingLayer 创建一个简单的 GNN。
class HeterGNN(nn.Layer):
def __init__(self, in_dim, hidden_size, etypes, num_class):
super(HeterGNN, self).__init__()
self.in_dim = in_dim
self.hidden_size = hidden_size
self.etypes = etypes
self.num_class = num_class
self.layers = nn.LayerList()
self.layers.append(
HeterMessagePassingLayer(self.in_dim, self.hidden_size, self.etypes))
self.layers.append(
HeterMessagePassingLayer(self.hidden_size, self.hidden_size, self.etypes))
self.linear = nn.Linear(self.hidden_size, self.num_class)
def forward(self, graph, feat):
h = feat
for i in range(len(self.layers)):
h = self.layers[i](graph, h)
logits = self.linear(h)
return logits
#训练
model = HeterGNN(8, 8, g.edge_types, 2)
criterion = paddle.nn.loss.CrossEntropyLoss()
optim = paddle.optimizer.Adam(learning_rate=0.05,
parameters=model.parameters())
g.tensor()
labels = paddle.to_tensor(labels)
for epoch in range(10):
#print(g.node_feat["features"])
logits = model(g, g.node_feat["features"])
loss = criterion(logits, labels)
loss.backward()
optim.step()
optim.clear_grad()
print("epoch: %s | loss: %.4f" % (epoch, loss.numpy()[0]))
epoch: 1 | loss: 1.1593
epoch: 2 | loss: 0.9971
epoch: 3 | loss: 0.8670
epoch: 4 | loss: 0.7591
epoch: 5 | loss: 0.6629
epoch: 6 | loss: 0.5773
epoch: 7 | loss: 0.5130
epoch: 8 | loss: 0.4782
epoch: 9 | loss: 0.4551
上篇项目讲的deepwalk、node2vec两种方法都是在同构图中进行游走,如果在异构图中游走,会产生下面的问题:
因此在异构图中采用methpath2vec算法。
metapath2vec: Scalable Representation Learning for Heterogeneous Networks
论文网址 项目主页 发表时间: KDD 2017 论文作者: Yuxiao Dong, Nitesh V. Chawla, Ananthram Swami 作者单位: Microsoft Research
Metapath2vec是Yuxiao Dong等于2017年提出的一种用于异构信息网络(Heterogeneous Information Network, HIN)的顶点嵌入方法。metapath2vec使用基于meta-path的random walks来构建每个顶点的异构邻域,然后用Skip-Gram模型来完成顶点的嵌入。在metapath2vec的基础上,作者还提出了metapath2vec++来同时实现异构网络中的结构和语义关联的建模。
methpath2vec中有元路径(meta path)的概念,含义就是在图中选取的节点类型构成的组合路径,这个路径是有实际意义的,例如以上面的异构图为例,A-P-A代表同一篇论文的两个作者,A-P-C-P-A代表两个作者分别在同一个会议上发表了两篇论文。
针对网络嵌入的相关工作主要有两大部分构成,一部分是图嵌入,一部分是图神经网络。图嵌入方面的相关代表有Deepwalk、LINE、Node2vec以及NetMF,Deepwalk源于NLP(自然语言处理)方面的Word2vec,将Word2vec应用到社交网络体现出了良好的效果,LINE主要是针对大规模网络,Node2vec是在Deepwalk的随机游走上进行了改进,使得游走不再变得那么随机,使得其概率可控,具体就不做过多赘述。对于图神经网络,GCN通过卷积神经网络结合了邻居节点的特征表示融入到节点的表示中,GraphSAGE它就是一个典型的生成式模型,且它结合了节点的结构信息,而且,它不是直接为每个节点生成嵌入,而是生成一个可以表示节点嵌入的函数表示形式,这样的模型,也就是这种生成式模型,有助于它在训练期间对未观察到的节点进行归纳和判断。
Heterogeneity:表示节点/边的单类还是多类 Heterogeneous/Heterogeneous:表示节点是单类还是多类 为了区分,论文添加了
根据图结构(同构/异构)以及是否包含节点特征,作者将图分为如下六类(缩写):
论文归纳了以及每一种网络类型对应的经典的研究方法,如下表:
论文给出一个带节点属性的异构图的例子。在左侧原始的图中,用户包含了性别、年龄等属性,商品包含了价格、类目等属性。用户与商品之间包含了4种类型的边,分别对应点击、收藏、加入购物车以及购买行为。
传统的 graph embedding 算法比如 DeepWalk 的做法会忽略图中边的类型以及节点的特征,然后转换成一个 HON。 如果将边的类型考虑进去,那么就得到一个 MHEN,能够取得非常明显的效果。 此外,如果将节点的属性也同时考虑进去,那么就利用了原图的所有信息,可以得到最好的效果。
除了异构性和多样性外,处理 AMHEN 也面临着多重挑战:
信息网络(Information Network)是指一个有向图 G=(V,E), 同时还有一个object类型映射函数
,边类型映射函数
。每一个object
, 都有一个特定的object 类型
;每一条边
都有一个特定的relation
。 异质网络(Heterogeneous Network)指的是object的类型
或者relation的类型
。
网络模式(Network schema),定义为:
,是信息网络 G=(V, E)的一种 meta模板,这个信息网络有一个object类型映射函数
和 link 类型映射函数
。信息网络G是一个定义在object类型
上的有向图,并且边是
中的relation。
Meta Path 是2011年 Yizhou Sun etc. 在Mining Heterogeneous Information Networks: Principles and Methodologies提出的, 针对异质网络中的相似性搜索。Meta Path 是一条包含relation序列的路径,而这些 relation 定义在不同类型object之间。
元路径P是定义在网络模式TG = (A, R)上的,如
表示了从
到
的复杂的关系,
元路径P的长度即为关系R的个数.
确定元路径的意义在于我们会根据确定的元路径进行随机游走,如果元路径没有意义,会导致后续的训练过程中无法充分体现节点的意义,元路径通常需要人工进行筛选。
在基于元路径的游走过程中,只要首尾节点类型相同,就可以继续游走,直到达到最大游走长度或者找不到指定要求的节点。通常来说,元路径是对称的。
目前大部分的工作都集中在同构网络中,但真实场景下异构网络才是最常见的。针对同构网络设计的模型很多都没法应用于异构网络,比如说,对于一个学术网络而言:
解决诸如此类的挑战,有利于更好的在异构网络中应用多种网络挖掘任务:
问题定义Problem Definition
Definition 1: 异质网络(Heterogeneous Network):
,其中每个节点和边分别对应一个映射
和
。 其中
和
分别表示节点的类型集合以及关系的类型集合。且
。
Definition 2: 异质网络表示学习(Heterogeneous Network Representation Learning):
给定一个异构网络,学习一个维的潜在表征可以表征网络中顶点之间的结构信息和语义场景关系。异构网络表征学习的输出是一个低维的矩阵,其中行是一个维的向量,表示顶点的表征。这里需要注意的是,虽然顶点的类型不同,但是不同类型的顶点的表征向量映射到同一个维度空间。由于网络异构性的存在,传统的基于同构网络的顶点嵌入表征方法很难有效地直接应用在异构网络上。异质网络中的节点学习一个
维的表示
,
。节点的向量表示可以捕获节点间结构和语义关系。
在正式介绍metapath2vec方法之前,作者首先介绍了同构网络上的基于random walk的graph embedding算法的基本思想,如:Deepwalk和node2vec等。该类方法采用了类似word2vec的思想,即:使用skip-gram模型对每个顶点的局部领域顶点信息进行预测,进而学习到每个顶点的特征表示。通常,对于一个同构网络
,目标是从每个顶点的局部领域上最大化网络似然:
其中
表示顶点
的领域, 如1-hop以内的邻接页点, 2 -hop以内的邻接顶点。
表 示给定顶点
后, 顶点
的条件概率。下面正式给出基于异构网络的metapath2vec嵌入算法。 metapath2vec分为两个部分,分别是Meta-Path-Based Random Walks和Heterogeneous Skip-Gram
在metapath2vec中,作者使用Skip-Gram模型通过在顶点
的领域
上最大化 条件概率来学习异构网络
上的顶点表征。
其中
表示顶点
的类型为
的领域顶点集合。
通常定义为一个softmax函数, 即:
其中
是矩阵
的第
行矩阵, 表示页点
的嵌入向量。为了提升参数更新效率 metapath2vec采用了Negative Sampling进行参数迭代更新, 给定一个Negative Sampling的大 小
参数更新过程如下:
其中
, $P(u)是一个negative node
在M次采样中的预定义分布。 metapath2vec通过不考虑顶点的类型进行节点抽取来确定当前顶点的频率。
在同构网络中,DeepWalk和node2vec等算法通过随机游走的方式来构建Skip-Gram模型的上下文语料库,受此启发,作者提出了一种异构网络上的随机游走方式。在不考虑顶点类型和边类型的情况下,
表示从顶点
向其邻居顶点
的转移概率。然而Sun等已证明异构网络上的随机游走会偏向于某些高度可见的类型的顶点,这些顶点的路径在网络中具有一定的统治地位,而这些有一定比例的路径指向一小部分节点的集合。鉴于此,作者提出了一种基于meta-path的随机游走方式来生成Skip-Gram模型的邻域上下文。该随机游走方式可以同时捕获不同类型顶点之间语义关系和结构关系,促进了异构网络结构向metapath2vec的Skip-Gram模型的转换。 一个meta-path的scheme可以定义成如下形式:
其中
表示顶点
和顶点
之间的路径组合。例如下图中, "APA"表示一种固定语义的metapath, "APVPA"表示另外一种固定语义的meta-path。并且很多之前的研究成果都表明, meta-path在很多异构网络数据挖掘中很很大作用。因此,在本文中,作者给出了基于meta-path的随机游走方式。给定一个异构网络
和一个meta-path的scheme
:
那么在第
步的转移概率定义如下:
其中
表示页点
的
类型的领域顶点集合。换言之,
也 就是说随机游走是在预定义的meta-path scheme
条件下的有偏游走。初次之外, meta-path 通常是以一种对称的方式来使用, 也就是说在上述路径组合中,顶点
的类型和
的类型相同。即:
基于meta-path的随机游走保证不同类型顶点之间的语义关系可以适当的融入Skip-Gram模型中。
methpath2vec的变种:
metapath2vec在为每个顶点构建领域时,通过meta-path来指导随机游走过程向指定类型的顶点进行有偏游走。但是在softmax环节中,并没有顶点的类型,而是将所有的顶点认为是同一种类型的顶点。换言之,metapath2vec在Negative Sampling环节采样的negative 样本并没有考虑顶点的类型,也就是说metapath2vec支持任意类型顶点的Negative Sampling。于是作者在metapath2vec的基础上又提出了改进方案metapath2vec++。
在metapath2vec++中, softmax函数根据不同类型的顶点的上下文
进行归一化。也就是说
根据固定类型的页点进行调整。即:
其中
是网络中
类型顶点集合。在这种情况下, metapath2vec++为Skip-Gram模型的输出层中的每种类型的领域指定了一个多项式分布的集合。而在metapath2vec, DeepWalk和node2vec中, Skip-Gram输出多项式分布的维度等于蜂个网络中顶点的数目,然而对于metapath2vec++的Skip-Gram, 其针对特定类型的输出多项式的维度取决于网络中当前类型顶点的数目。如下图示。
最终我们可以得到如下的目标函数:
可以得出其梯度如下:
其中
是一个指示函数, 用来指示
在
时是否是顶点
的上下文。该 算法使用随机梯度下降进行参数优化。整个metapath2vec++算法如下。
因为会存在许多无法在一台机器上加载的巨大图,例如社交网络和引文网络。为了处理这样的图,PGL 开发了一个分布式图引擎框架来支持大规模图网络上的图采样,以进行分布式 GNN 训练。
下面将介绍执行分布式图引擎以进行图采样的步骤。
如何启动分布式图引擎服务的示例:
链接:https://ericdongyx.github.io/metapath2vec/m2v.html
将所有数据和代码下载到一个 zip 文件中—metapath2vec.zip 6.7 GB,包括以下 B、C、D、E 和 F 部分(DropBox |百度云)。
Bibtex:
@inproceedings{dong2017metapath2vec,
title={metapath2vec: 异构网络的可扩展表示学习},
author={Dong, Yuxiao and Chawla, Nitesh V and Swami, Ananthram},
booktitle={KDD '17},
pages={135- -144},
年份={2017},
组织={ACM}
}
引用: Yuxiao Dong、Nitesh V. Chawla 和 Ananthram Swami。2017. metapath2vec:异构网络的可扩展表示学习。在 KDD’17 中。135–144。
原始网络数据
Citation: Jie Tang, Jing Zhang, Limin Yao, Juanzi Li, Li Zhang, and Zhong Su. 2008. ArnetMiner: Extraction and Mining of Academic Social Networks. In KDD’08. 990–998. Œ
Citation: Yizhou Sun, Jiawei Han, Xifeng Yan, Philip S. Yu, and Tianyi Wu. 2011. Pathsim: Meta path-based top-k similarity search in heterogeneous information networks. In VLDB’11. 992–1003.
利用PGL来复现metapath2vec模型。和前面xxx2vec的方法类似,先做网络嵌入系数矩阵的训练,然后使用训练好的矩阵在做预测。
Dataset.py 包含了对图数据进行深度游走生成walks等接口
model.py 包含用于训练metapath2vec的skipgram模型定义
utils.py 包含了对配置文件config.yaml的读取接口 超参数
所有超参数都保存在config.yaml文件中,所以在训练之前,你可以打开config.yaml来修改你喜欢的超参数。
PGL 图形引擎启动
现在我们支持使用PGL Graph Engine分布式加载图数据。我们还开发了一个简单的教程来展示如何启动图形引擎
要启动分布式图服务,请按照以下步骤操作。
1)IP地址设置
第一步是为每个图形服务器设置 IP 列表。每个带有端口的 IP 地址代表一个服务器。在ip_list.txt文件中,我们为演示设置了 4 个 IP 地址如下:
127.0.0.1:8553
127.0.0.1:8554
127.0.0.1:8555
127.0.0.1:8556
2)通过 OpenMPI 启动图形引擎
在启动图形引擎之前,您应该在中设置以下超参数config.yaml:
etype2files: "p2a:./graph_data/paper2author_edges.txt,p2c:./graph_data/paper2conf_edges.txt"
ntype2files: "p:./graph_data/node_types.txt,a:./graph_data/node_types.txt,c:./graph_data/node_types.txt"
symmetry: True
shard_num: 100
然后,我们可以在 OpenMPI 的帮助下启动图形引擎。
mpirun -np 4 python -m pgl.distributed.launch --ip_config ./ip_list.txt --conf ./config.yaml --mode mpi --shard_num 100
手动启动图形引擎 如果您没有安装 OpenMPI,您可以手动启动图形引擎。
Fox 示例,如果我们要使用 4 个服务器,我们应该在 4 个终端上分别运行以下命令。
# terminal 3
python -m pgl.distributed.launch --ip_config ./ip_list.txt --conf ./config.yaml --shard_num 100 --server_id 3
# terminal 2
python -m pgl.distributed.launch --ip_config ./ip_list.txt --conf ./config.yaml --shard_num 100 --server_id 2
# terminal 1
python -m pgl.distributed.launch --ip_config ./ip_list.txt --conf ./config.yaml --shard_num 100 --server_id 1
# terminal 0
python -m pgl.distributed.launch --ip_config ./ip_list.txt --conf ./config.yaml --shard_num 100 --server_id 0
介绍了异质图,利用pgl对metapath2vec、metapath2vec 进行了实现,并给出了多个框架版本的demo满足个性化需求
metapath2vec是一种用于异构网络中表示学习的算法框架,其中包含多种类型的节点和链接。给定异构图,metapath2vec 算法首先生成基于元路径的随机游走,然后使用 skipgram 模型训练语言模型。基于 PGL重现了 metapath2vec 算法,用于可扩展的表示学习。
参考资料