• homogeneous graph : 一种节点,一种边
  • heterogeneous graph: 多种节点,多种边
  • bipartite graph : 两种节点,一种边

image-20220730204438968

1、DGLgraph结构

1.1 同构图

Cora论文关系图–同构图(homogeneous)

(1)节点:2708篇论文,节点特征表示每个论文有是否出现1433个关键词中信息;节点标签表示每个论文所述的7个类别之一。

(2)边:10556个论文引用论文的关系,此外没有边的特征信息

1
2
3
from dgl.data import CoraGraphDataset
dataset = CoraGraphDataset()
g = dataset[0]
  • 节点信息
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 节点类型
g.ntypes
# 节点数
g.number_of_nodes()
# 节点的meta信息
g.ndata.keys()
# 节点具体一种meta信息(特征)的维度
g.ndata['feat'].shape
# 节点具体一种meta信息(标签)的频数
Counter(g.ndata['label'].numpy())
  • 边的信息
1
2
3
4
5
6
7
8
# 边的类型
g.etypes
# 边的数目
g.number_of_edges()
# 边的两端节点ID:sourece → target,以及边的ID
g.edges(form="all")
# 边的meta信息
g.edata.keys()
  • 从头创建一个同构图
1
2
3
4
5
6
7
g = dgl.graph(([0, 0, 0, 0, 0], [1, 2, 3, 4, 5]),    #edge的sourece与target
			  num_nodes=6)                           #node number
# 如不指定节点数,则取决于最大的节点id-1
g.ndata['x'] = torch.randn(6, 3)
g.ndata['y'] = torch.tensor(np.random.randn(6,5))

g.edata['w'] = torch.tensor([0.1, 0.6, 0.9, 0.7, 1.0])

1.2 异构图

假设存在药物,蛋白两种节点的异构图,其中有药物-蛋白、药物-药物、蛋白-蛋白3种边

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import dgl
import numpy as np
import torch
g = dgl.heterograph({
   ('drug', 'interacts', 'drug'): (torch.tensor([0, 1]), torch.tensor([1, 2])),
   ('drug', 'targets', 'gene'): (torch.tensor([0, 1]), torch.tensor([2, 3])),
   ('gene', 'coexpress', 'gene'): (torch.tensor([1]), torch.tensor([2]))
})
g.nodes['drug'].data['x'] = torch.ones(3, 1)
g.nodes['gene'].data['x'] = torch.ones(4, 2)

g.edges['interacts'].data['w'] = torch.ones(2, 1)
  • 节点信息
1
2
3
4
5
6
# 节点类型
g.ntypes
# 具体某一种节点类型的节点数(节点数取决于最大的节点id-1)
g.num_nodes('drug')
# 具体某一种节点类型的meta
g.nodes['drug'].data.keys()
  • 边的类型
1
2
3
4
5
6
7
8
9
# 边的类型
g.etypes
g.canonical_etypes
# 具体某一种边的数目
g.num_edges("interacts")
# 具体某一种边的ID信息
g.edges(etype="interacts", form='all')
# 具体某一种边的meta信息
g.edges['interacts'].data.keys()

1.3 其它操作

  • 单向→双向
1
2
g0 = dgl.add_reverse_edges(g)
g0.edges()
  • 自己与自己
1
2
g0 = dgl.add_self_loop(g)
g0.edges()
  • 保存与加载图
1
2
dgl.save_graphs('my.dgl', g)
(g,), _ = dgl.load_graphs('my.dgl')
  • 更多

(1)图信息查询 https://docs.dgl.ai/api/python/dgl.DGLGraph.html#apigraph-querying-graph-structure

(2)图信息修改 https://docs.dgl.ai/api/python/dgl.html#api-subgraph-extraction

2、从文件读入DGL

1
2
3
import dgl
ds = dgl.data.CSVDataset('/path/to/dataset')
g = ds[0]

根据同构图与异构图,文件夹需要准备不同的文件

2.1 同构图

需要包含以下3个文件

  • meta.yaml:指定边文件与节点文件
1
2
3
4
5
dataset_name: example_hoto_dataset
edge_data:
- file_name: edges.csv
node_data:
- file_name: nodes.csv
  • nodes.csv:节点csv文件
1
2
3
4
node_id,label,train_mask,val_mask,test_mask,feat
0,1,False,True,True,"0.07816474278491703, 0.9137336384979067, 0.4654086994009452"
1,1,True,True,True,"0.05354099924658973, 0.8753101998792645, 0.33929432608774135"
2,1,True,False,True,"0.33234211884156384, 0.9370522452510665, 0.6694943496824788"
  • edges.csv:边csv文件
1
2
3
4
src_id,dst_id,label,train_mask,val_mask,test_mask,feat
4,0,2,False,True,True,"0.5477868606453535, 0.4470617033458436, 0.936706701616337"
4,0,0,False,False,True,"0.9794634290792008, 0.23682038840665198, 0.049629338970987646"
0,3,1,True,True,True,"0.8586722047523594, 0.5746912787380253, 0.6462162561249654"

2.2 异构图

假设2种节点、2种边,需要包含以下2种文件

  • meta.yaml:指定边文件与节点文件
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
dataset_name: example_hete_dataset
edge_data:
- file_name: edges_0.csv
  etype: [user, follow, user]
- file_name: edges_1.csv
  etype: [user, like, item]
node_data:
- file_name: nodes_0.csv
  ntype: user
- file_name: nodes_1.csv
  ntype: item
  • 边csv文件:edges_0.csv or edges_1.csv
1
2
3
4
5
src_id,dst_id,label,feat
4,4,1,"0.736833152378035,0.10522806046048205,0.9418796835016118"
3,4,2,"0.5749339182767451,0.20181320245665535,0.490938012147181"
1,4,2,"0.7697294432580938,0.49397782380750765,0.10864079337442234"
0,4,0,"0.1364240150959487,0.1393107840629273,0.7901988878812207"
  • 节点csv文件:nodes_0.csv or nodes_1.csv
1
2
3
4
node_id,label,feat
0,2,"0.5400687466285844,0.7588441197954202,0.4268254673041745"
1,1,"0.08680051341900807,0.11446843700743892,0.7196969604886617"
2,2,"0.8964389655603473,0.23368113896545695,0.8813472954005022"

3、GNN模型

3.1 GNN层结构

  • GNN的核心是根据邻居信息更新节点特征,更新算法有GCN、Graphsage、GAT…
  • 根据预测目的,GNN可分为节点分类、回归,边的分类、回归,边是否存在的预测
    • 关于边相关预测,本质上是使用两端节点信息作为边的特征信息
  • 关于多层GNN的结构,大体如下:
    • 1层的GNN:考虑邻居节点的信息
    • 2层的GNN:考虑邻居以及邻居的邻居信息
image-20220730214831525

3.2 sampler与batch模式

默认情况下,一轮epoch,GNN会考虑所有节点的所有邻居信息。

  • sampler模式:在具体的某一层GNN中,只考虑节点的有限个邻居
  • batch模式:将训练集样本划分为多个小样本集,每个小样本集单独训练。

在设置sampler与batch模式下,每个小样本集的每一层GNN称之为block

image-20220730215044893