1、創(chuàng)建圖
1.1镊折、同質(zhì)圖
1.1.1、圖表示
dgl創(chuàng)建圖的時(shí)候介衔,使用兩組節(jié)點(diǎn)列表表示邊恨胚,其中每組節(jié)點(diǎn)對(duì)應(yīng)位置的節(jié)點(diǎn)表示邊的兩個(gè)端點(diǎn),例如:
# 圖中有5個(gè)節(jié)點(diǎn)
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)
在沒有明確指定節(jié)點(diǎn)的情況下赃泡,dgl會(huì)根據(jù)邊的端點(diǎn),來自動(dòng)指定節(jié)點(diǎn)數(shù)量乘盼,一般是節(jié)點(diǎn)的數(shù)量=邊的最大端點(diǎn)編號(hào)+1
也可以明確指定邊的數(shù)量
g.add_nodes(6)
1.1.2升熊、創(chuàng)建同質(zhì)圖
<font color='red' style='font-weight:bond'>創(chuàng)建圖信息</font>
import dgl
import torch
edges = torch.tensor(1, 3, 4), torch.tensor(2, 4, 5)
g = dgl.graph(edges)
print(g) # 獲取節(jié)點(diǎn)圖的大致信息
"""
output:
Graph(num_nodes=6, num_edges=3,
ndata_schemes={}
edata_schemes={})
"""
[圖片上傳失敗...(image-5e8724-1699540452319)]
<font color='red' style='font-weight:bond'>為節(jié)點(diǎn)賦予特征</font>
dgl允許圖中的節(jié)點(diǎn)存在多個(gè)特征,但是需要指定特征的名稱绸栅,例如'feat'
# 批量賦予節(jié)點(diǎn)特征
g.ndata['feat'] = torch.randn(g.num_nodes(), 5) # 表示為為每個(gè)節(jié)點(diǎn)賦予一個(gè)符合正態(tài)分布的5-d特征
# 為每個(gè)節(jié)點(diǎn)分別賦予特征
# 可以使用g.ndata['<feature_name>'][<index>]的方式為節(jié)點(diǎn)賦值
# 但是需要注意级野,在為單個(gè)節(jié)點(diǎn)特征賦值之前,首先確保特征是存在的
g.ndata['x'] = torch.zeros(g.num_nodes(), 6) # 初始化特征粹胯,將節(jié)點(diǎn)特征x賦值為6-d
# 如果這里沒有初始化特征蓖柔,直接使用下面的賦值辰企,會(huì)導(dǎo)致keyErr
for i in range(g.num_nodes()):
g.ndata['x'][i] = torch.randn(6)
<font color='red' style='font-weight:bond'>為邊賦予特征</font>
與邊一樣,dgl同樣允許為邊創(chuàng)建多個(gè)特征
# 批量賦予邊節(jié)點(diǎn)特征
g.edata['feat'] = torch.randn(g.num_edges(), 2) # 為每個(gè)邊賦予一個(gè)符合正態(tài)分布的2-d特征
# 為每個(gè)節(jié)點(diǎn)分別賦予特征
# 為節(jié)點(diǎn)賦初值况鸣,同節(jié)點(diǎn)一樣牢贸,如果不賦初值,匯報(bào)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位的整數(shù)作為節(jié)點(diǎn)ID和邊ID镐捧。節(jié)點(diǎn)ID和邊ID的數(shù)據(jù)類型必須一致潜索,如果使用64位整數(shù),最多可以處理個(gè)節(jié)點(diǎn)或邊
不過愤估,如果節(jié)點(diǎn)或邊的數(shù)量少于個(gè)帮辟,最好使用32位整數(shù),這樣不僅能提升速度玩焰,還能減少內(nèi)存的使用
# 查看圖中節(jié)點(diǎn)/邊的id的位數(shù)
# 創(chuàng)建的graph默認(rèn)使用64位
print(g.idtype)
# 可以在創(chuàng)建圖的時(shí)候由驹,直接指定32位的數(shù)據(jù)
g32 = dgl.graph(edges, idtype=torch.int32)
print(g32.idtype)
# 已創(chuàng)建的圖,32位和64為相互轉(zhuǎn)換
g64 = g32.long() # 將int32轉(zhuǎn)換為int64
g32_2 = g64.int() # 將int64轉(zhuǎn)換為int32
1.1.3昔园、查詢圖信息
<font color='red' style='font-weight:bond'>查詢節(jié)點(diǎn)和邊的數(shù)量</font>
# 獲取節(jié)點(diǎn)數(shù)量
print(g.num_nodes())
# 獲取邊數(shù)量
print(g.num_edges())
<font color='red' style='font-weight:bond'>獲取節(jié)點(diǎn)蔓榄,邊特征</font>
"""
獲取節(jié)點(diǎn)特征
"""
# 獲取所有節(jié)點(diǎn)特征的feat特征
print(g.ndata['feat'])
# 獲取節(jié)點(diǎn)0的特征
print(g.ndata['feat'][0])
# 獲取多個(gè)節(jié)點(diǎn)的特征
print(g.ndata['feat'][torch.tensor([0, 1, 3])]) # 獲取節(jié)點(diǎn)0, 1默刚, 3的特征
# 獲取節(jié)點(diǎn)的所有特征
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'>創(chuàng)建異配圖</font>
dgl中的異配圖指的是同一個(gè)圖中荤西,存在多種類型的節(jié)點(diǎn)澜搅,以及多種邊類型。
import dgl
import torch
# 創(chuàng)建異配圖
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]))
})
例如上面的例子邪锌,創(chuàng)建的g擁有兩種節(jié)點(diǎn)勉躺,user
和movie
; 兩種邊觅丰,follow
和watch
這里需要特別注意饵溅,關(guān)于節(jié)點(diǎn)的ID,user
和movie
的ID是分別從0到1的妇萄,也就是說蜕企,既存在nodes['user'][0]
,也存在nodes['movie'][0]
<font color='red'>為節(jié)點(diǎn)和變添加屬性</font>
- 為節(jié)點(diǎn)添加屬性
# 添加節(jié)點(diǎn)特征
user_features = torch.randn(g.num_nodes('user'), 6) # 為user添加6-d的特征
movie_features = torch.randn(g.num_nodes('movie'), 7) # 為movie節(jié)點(diǎn)添加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'>獲取節(jié)點(diǎn)或者邊的數(shù)量</font>
# 獲取節(jié)點(diǎn)user的數(shù)量
print(g.num_nodes('user'))
# 獲取節(jié)點(diǎn)movie的數(shù)量
print(g.num_nodes('movie'))
# 獲取邊f(xié)ollow的數(shù)量
print(g.num_edges('follow'))
# 獲取邊watch的數(shù)量
print(g.num_edges('movie'))
<font color='red'>獲取節(jié)點(diǎn)或者邊的屬性</font>
- 獲取節(jié)點(diǎn)屬性
# 獲取節(jié)點(diǎn)中屬性feat的特征
print(g.nodes['user'].data['feat'])
# 獲取節(jié)點(diǎn)所有屬性特征
print(g.nodes['user'])
# 獲取節(jié)點(diǎn)user[0]的所有特征
print(g.nodes['user'][0])
# 獲取節(jié)點(diǎn)user[0]的feat特征
print(g.nodes['user'].data['feat'][0])
# 下面這種寫法是錯(cuò)誤的
# print(g.nodes['user'][0].data['feat'])
- 獲取邊屬性
# 獲取邊f(xié)ollow的feat特征
print(g.edges['follow'].data['feat'])
# 獲取邊f(xié)ollow的所有特征
print(g.edges['follow'])
# 獲取邊f(xié)ollow[0]的所有特征
print(g.edges['follow'][0])
# 獲取邊f(xié)ollow[0]的feat特征
print(g.edges['follow'].data['feat'][0])
- 從異質(zhì)圖中分離出子圖
# 從圖中分離出邊'follow'連接的子圖
subgraph = g.edge_type_subgraph(('follow', ))