图采样¶
图采样是管理大规模图数据的有效技术,在GraphSAGE框架为代表的编程范式中得到广泛应用。采样能减小数据规模,并通过数据对齐使基于张量的计算框架能够高效处理。
在采样之前,我们需要提供种子,这些种子可以是节点或边。相应地,GLE提供了图遍历操作符来为批量采样准备种子:
节点采样器
边采样器
那么,用户对采样的需求可以被抽象并归类为GLE中的以下几类操作:
邻域采样。
子图采样。
负采样。
邻域采样(Neighborhood Sampling)涉及根据输入顶点选择一跳或多跳相邻顶点,以构建GCN理论中的感知域。邻域采样的输入可以来自图遍历输出或其他外部数据源。
子图采样涉及一跳或多跳的顶点,以及所有源顶点和目标顶点已被采样的边,从而形成一个子图。随着GNN表达能力研究的进展,这种采样方法变得越来越重要。
负采样会选择与输入顶点不直接相连的顶点,这种方法通常用于无监督学习。
图遍历¶
在图神经网络(GNN)中,图遍历与传统图计算具有不同的语义。主流深度学习算法的训练模型通过批次进行迭代。为满足这一需求,数据必须能够按批次访问,我们将这种数据访问模式称为遍历。在GNN算法中,数据源是图结构,训练样本通常由图的顶点和边组成。图遍历指的是为算法提供按批次访问顶点、边或子图的能力。
目前GLE支持对顶点和边进行批量遍历。这种随机遍历可以是不回放或回放模式。在不回放遍历中,每当一个周期结束时都会触发gl.OutOfRangeError。被遍历的数据源是分区的,即当前工作节点(在分布式TF情况下)仅遍历与其对应的Server上的数据。
关于图遍历的使用方法和接口,请查看GLE的遍历部分获取更多详情。
邻域采样¶
每种采样操作都支持不同的实现策略,例如随机采样和基于边权重的采样。通过实际生产应用,我们已积累了10多种采样算子,并开放了算子编程接口,允许用户自定义以满足不断演进的图神经网络需求。
对于采样策略,GLE目前支持以下采样策略,对应生成NeighborSampler对象时的strategy参数。
策略 |
描述 |
|---|---|
edge_weight |
按边权重概率采样 |
随机 |
带替换的随机 |
topk |
Return the neighbors with edge weight topK, if there are not enough neighbors, refer to the padding rule. |
in_degree |
按顶点度进行概率采样。 |
full |
返回所有邻居节点,expand_factor参数不起作用,结果对象为SparseNodes或SparseEdges。 |
接下来是一个邻居采样的示例:
示例:
如下图所示,从类型为user的顶点出发,采样其2跳邻居,并将结果以层级形式返回,包含layer1和layer2。层级索引从1开始,即1跳邻居为layer1,2跳邻居为layer2。

s = g.neighbor_sampler(["buy", "i2i"], expand_factor=[2, 2])
l = s.get(ids) # input ids: shape=(batch_size)
# Nodes object
# shape=(batch_size, expand_factor[0])
l.layer_nodes(1).ids
l.layer_nodes(1).int_attrs
# Edges object
# shape=(batch_size * expand_factor[0], expand_factor[1])
l.layer_edges(2).weights
l.layer_edges(2).float_attrs
关于邻域采样的使用方法和接口,请查阅GLE的采样部分获取更多详情。
子图采样¶
与EgoGraph不同,SubGraph包含了图拓扑的edge_index,因此消息传递路径(前向计算路径)可以直接由edge_index确定,卷积层的实现可以直接通过edge_index和节点/边数据来完成。此外,SubGraph与PyG中的Data完全兼容,因此可以复用PyG的模型部分。
子图采样涉及一跳或多跳的顶点,以及所有源顶点和目标顶点已被采样的边,这些元素共同构成一个子图。
随着GNN表达能力研究的深入,这种采样方法变得越来越重要。
负采样¶
负采样指的是对与给定顶点无直接边关系的顶点进行采样。与邻居采样类似,负采样有不同的实现策略,例如随机采样、基于节点入度等。作为GNN的常见算子,负采样支持扩展和面向场景的定制。此外,GLE还提供了按指定属性条件进行负采样的能力。
GLE目前支持以下负采样策略,对应生成NegativeSampler对象时的strategy参数。
策略 |
描述 |
|---|---|
random |
随机负采样,不保证是真实负样本 |
in_degree |
基于顶点入度分布的负采样概率,确保真实负样本 |
node_weight |
基于顶点权重概率的负采样,真负样本 |
以下是一个负采样示例:
示例:
es = g.edge_sampler("buy", batch_size=3, strategy="random")
ns = g.negative_sampler("buy", 5, strategy="random")
for i in range(5):
edges = es.get()
neg_nodes = ns.get(edges.src_ids)
print(neg_nodes.ids) # shape is (3, 5)
print(neg_nodes.int_attrs) # shape is (3, 5, count(int_attrs))
print(neg_nodes.float_attrs) # shape as (3, 5, count(float_attrs))
关于负采样的使用方法和接口,请查阅GLE的负采样部分获取更多详情。
GSL¶
GLE将采样操作抽象为一组接口,称为GSL(图采样语言)。通常,图采样包含以下几种类别。
遍历类型(Traverse),用于从图中批量获取点或边的数据。
关系型(邻域、子图),用于获取点的N跳邻域或生成由点组成的子图以构建训练样本。
负采样(Negative),与关系型相对,通常用于无监督训练场景中生成负例样本。
例如,在“用户点击产品”的异构图场景中,“随机采样64个用户,并根据边权重为每个用户采样10个相关产品”。这可以通过GSL表示为
g.V("user").batch(64).outV("click").sample(10).by("edge_weight")
考虑到实际图数据的特性,GSL支持超大图、异构图和属性图,其语法设计接近Gremlin形式以便于理解。
更多详情,请查看GLE的GSL部分。