DGL教程【二】如何通过DGL表示一个Graph
通過本節(jié),將學(xué)到:
- 從頭開始用DGL構(gòu)建一個(gè)Graph
- 給Graph添加節(jié)點(diǎn)和邊的特征
- 獲取一些圖的信息,如節(jié)點(diǎn)的度或節(jié)點(diǎn)的其他屬性
- 將DGL graph 轉(zhuǎn)換到另一個(gè)graph
- 加載、保存DGL graph
從頭構(gòu)建Graph
DGL通過DGLGraph對(duì)象來創(chuàng)建一個(gè)有向圖,我們可以直接通過指定節(jié)點(diǎn),以及src節(jié)點(diǎn)和target節(jié)點(diǎn)來創(chuàng)建一個(gè)graph。節(jié)點(diǎn)的id從0開始。
例如下面一段代碼構(gòu)建了一個(gè)有向星型圖,共有6個(gè)節(jié)點(diǎn),中心節(jié)點(diǎn)的id是0,邊分別是從中心到葉子節(jié)點(diǎn)。
import dgl import numpy as np import torchg = dgl.graph(([0, 0, 0, 0, 0], [1, 2, 3, 4, 5]), num_nodes=6) # Equivalently, PyTorch LongTensors also work. g = dgl.graph((torch.LongTensor([0, 0, 0, 0, 0]), torch.LongTensor([1, 2, 3, 4, 5])), num_nodes=6)# You can omit the number of nodes argument if you can tell the number of nodes from the edge list alone. g = dgl.graph(([0, 0, 0, 0, 0], [1, 2, 3, 4, 5])) print(g.edges())輸出:
(tensor([0, 0, 0, 0, 0]), tensor([1, 2, 3, 4, 5]))注意DGLGraph默認(rèn)使用有向圖以方便計(jì)算,如果要?jiǎng)?chuàng)建無向圖,需要?jiǎng)?chuàng)建一個(gè)bidirectional graph。
指定節(jié)點(diǎn)和邊的特征
很多graph的節(jié)點(diǎn)和邊都包含屬性,雖然在現(xiàn)實(shí)中,節(jié)點(diǎn)和邊的屬性都是任意的,但是在DGLGraph中,只接受tensor(numerical contents)類型。因此,節(jié)點(diǎn)或邊的屬性必須擁有相同的shape,我們將節(jié)點(diǎn)或邊的屬性稱作features。
我們可以通過ndata和edata接口來分配或檢索節(jié)點(diǎn)和邊的features:
# Assign a 3-dimensional node feature vector for each node. g.ndata['x'] = torch.randn(6, 3) # Assign a 4-dimensional edge feature vector for each edge. g.edata['a'] = torch.randn(5, 4)# 可以給每個(gè)節(jié)點(diǎn)一個(gè)5*4維的特征矩陣 g.ndata['y'] = torch.randn(6, 5, 4) print(g.edata['a']) print(g.ndata)輸出結(jié)果如下:
tensor([[-0.0667, 0.4955, -0.7605, 1.0864],[ 1.3225, -0.0638, 0.4249, -0.9549],[ 1.5967, 0.6893, 0.0693, -0.2029],[ 0.9383, -0.9211, -0.3480, -1.2578],[-0.2237, -0.3213, 0.2844, -2.1222]]) {'x': tensor([[-1.5809, 0.5587, -0.2951],[-0.6097, -0.6469, 1.1301],[-0.2151, -0.4234, 0.1623],[ 0.0742, 1.0390, 0.4727],[-0.9907, 0.0712, -1.9446],[-0.8176, -1.3116, -0.0609]]), 'y': tensor([[[ 0.5657, 1.5601, -0.5912, -0.9166],[-2.1264, -1.0500, -1.5964, 0.8197],[-0.1032, 0.8735, 0.5557, 0.2568],[-0.2407, 0.5534, -0.4418, -0.8438],[-1.3463, -1.3163, 0.4165, 0.4069]],[[ 0.5147, 0.7456, 0.5775, -0.8002],[-0.7700, -0.9576, -0.4264, 0.5365],[-0.2953, -1.0986, -0.7701, 0.6752],[-0.8701, 0.0455, -0.0241, 1.4218],[ 0.8420, 1.5854, 0.2167, -0.3292]],[[-1.9216, -1.4101, -0.8027, -0.1626],[ 0.8344, 0.6824, -0.2703, -0.6369],[-0.8784, -1.3154, 2.5829, -0.6084],[ 1.0764, 0.6415, -0.0548, 2.0256],[-0.2596, 0.9234, -0.7495, 0.4572]],[[ 0.4695, 0.4599, 1.0253, -1.6217],[-0.9483, -1.1822, 0.6945, 0.2053],[-1.6246, -0.2697, 0.3077, -0.1492],[ 0.1044, 1.3403, -2.2207, 0.7767],[-1.0187, 0.9309, 1.3097, -0.8092]],[[ 0.3566, -0.9140, -0.0288, 0.8432],[ 1.4894, -1.0284, 1.1628, 1.6677],[ 0.9602, 0.8019, 0.2072, 0.9472],[-0.8926, 0.6656, 0.2531, 0.1492],[ 1.2601, 0.5075, 0.6341, -0.6500]],[[-0.3595, 0.8457, 0.0679, -0.2255],[ 0.0466, -0.5428, -1.8730, 1.7333],[-1.2157, 0.6068, -0.4385, -1.6794],[ 0.2981, 1.2320, -0.1630, 2.4952],[-1.3436, -2.1708, -0.3203, -0.9315]]])}目前有很多成熟的方法可以將屬性編碼成numerical features:
對(duì)于分類屬性(比如性別,職業(yè)),可以通過one-hot進(jìn)行編碼
對(duì)于字符串型的屬性(比如文章引用),可以考慮nlp模型
對(duì)于圖像的屬性,可以考慮CNN等視覺模型
獲取Graph的結(jié)構(gòu)信息
DGLGraph對(duì)象提供了很多方法來獲取Graph的結(jié)構(gòu)信息:
print(g.num_nodes()) # 6 print(g.num_edges()) # 5 # Out degrees of the center node print(g.out_degrees(0)) # 5 出度 圖中每個(gè)節(jié)點(diǎn)出度的最大值 # In degrees of the center node - note that the graph is directed so the in degree should be 0. print(g.in_degrees(0)) # 0 入度 圖中每個(gè)節(jié)點(diǎn)入度的最大值Graph 轉(zhuǎn)換
DGL提供了很多轉(zhuǎn)換的API,例如從一個(gè)圖中抽取一張子圖。
# 從原始圖中獲取節(jié)點(diǎn)0、節(jié)點(diǎn)1和節(jié)點(diǎn)3來成成一個(gè)子圖 sg1 = g.subgraph([0, 1, 3]) # 從原始圖中抽取邊0、邊1和邊3來成成一個(gè)子圖 sg2 = g.edge_subgraph([0, 1, 3])可以在子圖中通過dgl.NID或者dgl.EID來獲取父圖中節(jié)點(diǎn)和邊的映射。
# The original IDs of each node in sg1 print(sg1.ndata[dgl.NID]) # The original IDs of each edge in sg1 print(sg1.edata[dgl.EID]) # The original IDs of each node in sg2 print(sg2.ndata[dgl.NID]) # The original IDs of each edge in sg2 print(sg2.edata[dgl.EID])輸出:
tensor([0, 1, 3]) tensor([0, 2]) tensor([0, 1, 2, 4]) tensor([0, 1, 3])subgraph和edge_subgraph同樣會(huì)將父圖的屬性復(fù)制一份給子圖:
# sg1的每個(gè)原始節(jié)點(diǎn)的屬性 print(sg1.ndata['x']) # sg1的每個(gè)原始邊的屬性 print(sg1.edata['a']) # sg2中每個(gè)原始節(jié)點(diǎn)的屬性 print(sg2.ndata['x']) # sg2中每個(gè)原始邊的屬性 print(sg2.edata['a'])還有一種常用的轉(zhuǎn)換方式就是通過給原始graph添加反向邊dgl.add_reverse_edges
newg = dgl.add_reverse_edges(g) newg.edges()如果你有一個(gè)無向圖,可以通過這種方式來轉(zhuǎn)成bidirectional graph。這種方式會(huì)將原始圖中所有的邊都添加一個(gè)反向邊。
保存、加載Graph
我們可以通過dgl.save_graphs來保存一個(gè)Graph或者一個(gè)Graph列表,通過dgl.load_graphs來加載graph
# 保存graph dgl.save_graphs('graph.dgl', g) dgl.save_graphs('graphs.dgl', [g, sg1, sg2]) # 加載graph (g,), _ = dgl.load_graphs('graph.dgl') print(g) (g, sg1, sg2), _ = dgl.load_graphs('graphs.dgl') print(g) print(sg1) print(sg2)輸出:
Graph(num_nodes=6, num_edges=5,ndata_schemes={'y': Scheme(shape=(5, 4), dtype=torch.float32), 'x': Scheme(shape=(3,), dtype=torch.float32)}edata_schemes={'a': Scheme(shape=(4,), dtype=torch.float32)}) Graph(num_nodes=6, num_edges=5,ndata_schemes={'y': Scheme(shape=(5, 4), dtype=torch.float32), 'x': Scheme(shape=(3,), dtype=torch.float32)}edata_schemes={'a': Scheme(shape=(4,), dtype=torch.float32)}) Graph(num_nodes=3, num_edges=2,ndata_schemes={'_ID': Scheme(shape=(), dtype=torch.int64), 'x': Scheme(shape=(3,), dtype=torch.float32), 'y': Scheme(shape=(5, 4), dtype=torch.float32)}edata_schemes={'_ID': Scheme(shape=(), dtype=torch.int64), 'a': Scheme(shape=(4,), dtype=torch.float32)}) Graph(num_nodes=4, num_edges=3,ndata_schemes={'_ID': Scheme(shape=(), dtype=torch.int64), 'x': Scheme(shape=(3,), dtype=torch.float32), 'y': Scheme(shape=(5, 4), dtype=torch.float32)}edata_schemes={'_ID': Scheme(shape=(), dtype=torch.int64), 'a': Scheme(shape=(4,), dtype=torch.float32)})總結(jié)
以上是生活随笔為你收集整理的DGL教程【二】如何通过DGL表示一个Graph的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows常用高效快捷键11个,你都
- 下一篇: 如何设置路由器的主机和分机路由器的分机要