说明:这个系列来自于DGL上面的A Blitz Introduction to DGL。如果看英文习惯的小伙伴还是建议直接看官网文档。
How Does DGL Represent A Graph?
本节结束您能够完成以下任务
- 通过DGL从头开始构造一个图
- 给节点和边指定特征
- 能够查询一个图的属性。类似于节点度和连通性
- 将一个图转化成另一个图
- 保存和加载图
构造一个图
先导入相关包
import dgl
import networkx as nx
import numpy as np
import torch
import matplotlib.pyplot as plt
DGL将所有图都表示为一个有向图,你可以通过多种方式进行定义一个图,例如。
g=dgl.graph(([0,0,0,0,0],[1,2,3,4,5]),num_nodes=6) #注意如果num_nodes如果多于前面列表指定的,可能会出现孤立节点
#下面两行是将图形简单的显示出来
nx.draw(g.to_networkx(),with_labels=True)
plt.show()
使用pytorch Longtensor类型也是可以的
g1=dgl.graph((torch.LongTensor([0,0,0,0,0]),torch.LongStorage([1,2,3,4,5])),num_nodes=8)
nx.draw(g1.to_networkx(),with_labels=True)
plt.show()
你也可以不指定确定的num_nodes,DGL会自动识别
g=dgl.graph(([0,0,0,0,0],[1,2,3,4,5]))
nx.draw(g.to_networkx(),with_labels=True,node_color='yellow',edge_color='green')
plt.show()
显示边:边的ID是从0开始自动编号的,并且和节点定义顺序一致
print(g.edges())
注意:前面已经提到,DGL定义的图都是有向图,如果你想定义一个无向图,其实就是两条平行的有向边,你可以使用DGL提供的方法进行添加一条相反边实现无向图
dgl.add_reverse_edges(g)
给节点和边指定特征(注意,DGL中边和节点都只接受tensor类的数值型特征)
g.ndata['x']=torch.randn(6,3)
g.edata['a']=torch.randn(5,4)
g.ndata['y']=torch.randn(6,5,4)
查询一个图的相关信息
print(g.num_nodes()) #查询一个图的节点个数
print(g.num_edges()) #查询一个图的边数
print(g.out_degrees(0)) #查询节点0的出度
print(g.in_degrees(0)) #查询节点0的入读
图的转换
按节点提取子图
sg1=g.subgraph([0,1,3]) #提取0,1,3节点组成的子图
按边序号提取子图
sg2=g.edge_subgraph([0,1,3]) #提取边序号为0,1,3组成的子图
你可以对你刚刚提取出来的子图进行查看是否准确
# sg1的节点序号
print(sg1.ndata[dgl.NID])
# sg1的边序号
print(sg1.edata[dgl.EID])
在提取子图的时候,对应的特征也会提取到子图中去
print(sg1.ndata['x'])
print(sg1.edata['a'])
print(sg2.ndata['x'])
print(sg2.edata['a'])
保存图和加载图(默认保存到当前目录’)
保存
dgl.save_graphs('graph.dgl',g)
dgl.save_graphs('graphs.dgl',[g,sg1,sg2]) #将多个图保存到一个文件中
加载
(g,),_=dgl.load_graphs('graph.dgl')
(g,sg1,sg2),_=dgl.load_graphs('graphs.dgl')
print(g)
print(sg1)
print(sg2)
nice~ 至此,你已经学会了用DGL定义简单图了,试着自己定义一些图吧。