1、创建图
1.1、同质图
1.1.1、图表示
dgl创建图的时候,使用两组节点列表表示边,其中每组节点对应位置的节点表示边的两个端点,例如:
# 图中有5个节点
nodes = torch.tensor([1, 2, 3, 4, 5])
# 图中有三条边,分别是1-2, 3-4, 4-5
edges = torch.tensor(1, 3, 4), torch.tensor(2, 4, 5)
在没有明确指定节点的情况下,dgl会根据边的端点,来自动指定节点数量,一般是节点的数量=边的最大端点编号+1
也可以明确指定边的数量
g.add_nodes(6)
1.1.2、创建同质图
<font color='red' style='font-weight:bond'>创建图信息</font>
import dgl
import torch
edges = torch.tensor(1, 3, 4), torch.tensor(2, 4, 5)
g = dgl.graph(edges)
print(g) # 获取节点图的大致信息
"""
output:
Graph(num_nodes=6, num_edges=3,
ndata_schemes={}
edata_schemes={})
"""
[图片上传失败...(image-5e8724-1699540452319)]
<font color='red' style='font-weight:bond'>为节点赋予特征</font>
dgl允许图中的节点存在多个特征,但是需要指定特征的名称,例如'feat'
# 批量赋予节点特征
g.ndata['feat'] = torch.randn(g.num_nodes(), 5) # 表示为为每个节点赋予一个符合正态分布的5-d特征
# 为每个节点分别赋予特征
# 可以使用g.ndata['<feature_name>'][<index>]的方式为节点赋值
# 但是需要注意,在为单个节点特征赋值之前,首先确保特征是存在的
g.ndata['x'] = torch.zeros(g.num_nodes(), 6) # 初始化特征,将节点特征x赋值为6-d
# 如果这里没有初始化特征,直接使用下面的赋值,会导致keyErr
for i in range(g.num_nodes()):
g.ndata['x'][i] = torch.randn(6)
<font color='red' style='font-weight:bond'>为边赋予特征</font>
与边一样,dgl同样允许为边创建多个特征
# 批量赋予边节点特征
g.edata['feat'] = torch.randn(g.num_edges(), 2) # 为每个边赋予一个符合正态分布的2-d特征
# 为每个节点分别赋予特征
# 为节点赋初值,同节点一样,如果不赋初值,汇报KeyErr
g.edata['weigth'] = torch.zeros(g.num_edges(), 3)
for i in range(g.num_edges):
g.edata['weight'][i] = torch.randn(3)
<font color='red' style='font-weight:bond'>ID是32位or64位</font>
DGL支持使用32位和64位的整数作为节点ID和边ID。节点ID和边ID的数据类型必须一致,如果使用64位整数,最多可以处理个节点或边
不过,如果节点或边的数量少于个,最好使用32位整数,这样不仅能提升速度,还能减少内存的使用
# 查看图中节点/边的id的位数
# 创建的graph默认使用64位
print(g.idtype)
# 可以在创建图的时候,直接指定32位的数据
g32 = dgl.graph(edges, idtype=torch.int32)
print(g32.idtype)
# 已创建的图,32位和64为相互转换
g64 = g32.long() # 将int32转换为int64
g32_2 = g64.int() # 将int64转换为int32
1.1.3、查询图信息
<font color='red' style='font-weight:bond'>查询节点和边的数量</font>
# 获取节点数量
print(g.num_nodes())
# 获取边数量
print(g.num_edges())
<font color='red' style='font-weight:bond'>获取节点,边特征</font>
"""
获取节点特征
"""
# 获取所有节点特征的feat特征
print(g.ndata['feat'])
# 获取节点0的特征
print(g.ndata['feat'][0])
# 获取多个节点的特征
print(g.ndata['feat'][torch.tensor([0, 1, 3])]) # 获取节点0, 1, 3的特征
# 获取节点的所有特征
print(g.ndata)
"""
获取边的特征
"""
# 获取所有边的feat的特征
print(g.edata['feat'])
# 获取边0的特征
print(g.edata['feat'][0])
# 获取边1,2的特征
print(g.edata['feat'][torch.tensor([1, 2])])
# 获取边的所有特征
print(g.edata)
1.2、异配图
<font color='red'>创建异配图</font>
dgl中的异配图指的是同一个图中,存在多种类型的节点,以及多种边类型。
import dgl
import torch
# 创建异配图
g = dgl.heterograph({
('user', 'follow', 'user'): (torch.tensor([0, 1, 2]), torch.tensor([1, 2, 3])),
('user', 'watch', 'movie'): (torch.tensor([0, 1, 3]), torch.tensor([0, 1, 2]))
})
例如上面的例子,创建的g拥有两种节点,user
和movie
; 两种边,follow
和watch
这里需要特别注意,关于节点的ID,user
和movie
的ID是分别从0到1的,也就是说,既存在nodes['user'][0]
,也存在nodes['movie'][0]
<font color='red'>为节点和变添加属性</font>
- 为节点添加属性
# 添加节点特征
user_features = torch.randn(g.num_nodes('user'), 6) # 为user添加6-d的特征
movie_features = torch.randn(g.num_nodes('movie'), 7) # 为movie节点添加7-d特征
g.nodes['user'].data['feat'] = user_features
g.nodes['movie'].data['feat'] = movie_features
- 为边添加属性
follow_features = torch.randn(g.num_edges('follow'), 4) # 为follow边添加4-d名为features属性
follow_weight = torch.randn(g.num_edges('follow'), 5) # 为follow边添加5-d名为weight的属性
g.edges['follow'].data['feat'] = follow_features
g.edges['follow'].data['feat'] = follow_weight
<font color='red'>获取节点或者边的数量</font>
# 获取节点user的数量
print(g.num_nodes('user'))
# 获取节点movie的数量
print(g.num_nodes('movie'))
# 获取边follow的数量
print(g.num_edges('follow'))
# 获取边watch的数量
print(g.num_edges('movie'))
<font color='red'>获取节点或者边的属性</font>
- 获取节点属性
# 获取节点中属性feat的特征
print(g.nodes['user'].data['feat'])
# 获取节点所有属性特征
print(g.nodes['user'])
# 获取节点user[0]的所有特征
print(g.nodes['user'][0])
# 获取节点user[0]的feat特征
print(g.nodes['user'].data['feat'][0])
# 下面这种写法是错误的
# print(g.nodes['user'][0].data['feat'])
- 获取边属性
# 获取边follow的feat特征
print(g.edges['follow'].data['feat'])
# 获取边follow的所有特征
print(g.edges['follow'])
# 获取边follow[0]的所有特征
print(g.edges['follow'][0])
# 获取边follow[0]的feat特征
print(g.edges['follow'].data['feat'][0])
- 从异质图中分离出子图
# 从图中分离出边'follow'连接的子图
subgraph = g.edge_type_subgraph(('follow', ))
网友评论