【DGL学习3】自己构造和使用简单图

使用DGL构造和使用简单图。
参考:https://docs.dgl.ai/guide_cn/graph-graphs-nodes-edges.html

import dgl
import torch
import numpy as np
Using backend: pytorch

使用DGL建简单图

创建一个 DGLGraph 对象的一种方法是使用 dgl.graph() 函数。它接受一个边的集合作为输入。
DGL推荐使用Tensor作为DGL API的输入。不过大部分的DGL API也支持Python的可迭代类型(比如列表)或numpy.ndarray类型作为API的输入,方便用户快速进行开发验证。

g = dgl.graph((torch.tensor([0, 0, 0, 0, 0]), torch.tensor([1, 2, 3, 4, 5])))
print(g)
Graph(num_nodes=6, num_edges=5,
      ndata_schemes={}
      edata_schemes={})

DGL支持使用 32 位或 64 位的整数作为节点ID和边ID。节点和边ID的数据类型必须一致。如果使用 64 位整数, DGL可以处理最多 2 63 2^{63} 263−1 个节点或边。不过,如果图里的节点或者边的数量小于 2 63 2^{63} 263−1 ,用户最好使用 32 位整数。 这样不仅能提升速度,还能减少内存的使用。

print(g.idtype)  # DGL默认使用int64
g = g.int()
print(g.idtype)  # 转换成int32
torch.int32
torch.int32

获取图的属性信息

print(g)
print(g.nodes())  # 图中节点的数量是DGL通过给定的图的边列表中最大的点ID推断所得出的
print(g.edges())
# 获取边的对应端点和边ID
print(g.edges(form='all'))
Graph(num_nodes=6, num_edges=5,
      ndata_schemes={}
      edata_schemes={})
tensor([0, 1, 2, 3, 4, 5], dtype=torch.int32)
(tensor([0, 0, 0, 0, 0], dtype=torch.int32), tensor([1, 2, 3, 4, 5], dtype=torch.int32))
(tensor([0, 0, 0, 0, 0], dtype=torch.int32), tensor([1, 2, 3, 4, 5], dtype=torch.int32), tensor([0, 1, 2, 3, 4], dtype=torch.int32))

为图中的节点添加feat和label等特征或属性信息

  • 仅允许使用数值类型(如单精度浮点型、双精度浮点型和整型)的特征。这些特征可以是标量、向量或多维张量。
  • 每个节点特征具有唯一名称,每个边特征也具有唯一名称。节点和边的特征可以具有相同的名称。
  • 通过张量分配创建特征时,DGL会将特征赋给图中的每个节点和每条边。该张量的第一维必须与图中节点或边的数量一致。 不能将特征赋给图中节点或边的子集。
g.ndata['feat'] = torch.randn(g.num_nodes(), 3)
# 不同名称的特征可以具有不同形状
g.ndata['x'] = torch.randn(g.num_nodes(), 5)
g.ndata['label'] = torch.tensor([0, 1, 2, 3, 4, 5])
# 边特征
g.edata['feat'] = torch.ones(g.num_edges(), dtype=torch.int32)
print(g)
print(g.ndata['feat'])
print(g.ndata['label'])
# 获取节点1的特征
print(g.ndata['feat'][1])
# 获取边0和3的特征
print(g.edata['feat'][torch.tensor([0, 3])])
Graph(num_nodes=6, num_edges=5,
      ndata_schemes={'feat': Scheme(shape=(3,), dtype=torch.float32), 'label': Scheme(shape=(), dtype=torch.int64), 'x': Scheme(shape=(5,), dtype=torch.float32)}
      edata_schemes={'feat': Scheme(shape=(), dtype=torch.int32)})
tensor([[-0.4046, -1.5649, -0.5510],
        [-1.1374, -1.0940,  1.7150],
        [ 0.2465,  0.0811, -1.9171],
        [ 0.8162,  0.4573, -1.3169],
        [ 0.3926,  0.2399, -1.2495],
        [ 0.1937,  0.1652,  0.3655]])
tensor([0, 1, 2, 3, 4, 5])
tensor([-1.1374, -1.0940,  1.7150])
tensor([1, 1], dtype=torch.int32)

加权图

对于加权图,用户可以将权重储存为一个边特征w

g.edata['w'] = torch.tensor([0.1, 0.6, 0.9, 0.7, 0.2])  # 数量必须与边数一致
print(g)
Graph(num_nodes=6, num_edges=5,
      ndata_schemes={'feat': Scheme(shape=(3,), dtype=torch.float32), 'label': Scheme(shape=(), dtype=torch.int64), 'x': Scheme(shape=(5,), dtype=torch.float32)}
      edata_schemes={'feat': Scheme(shape=(), dtype=torch.int32), 'w': Scheme(shape=(), dtype=torch.float32)})

生成一个train_mask以及onhot的例子

train_mask = torch.zeros((g.ndata['feat'].shape[0],), dtype=torch.long)
train_mask[0] = train_mask[1] = 1
print(train_mask)
tensor([1, 1, 0, 0, 0, 0])
num_classes = 6
onehot = torch.zeros(g.ndata['feat'].shape[0], num_classes)
onehot[train_mask, g.ndata['label'][train_mask]] = 1
print(onehot)
tensor([[1., 0., 0., 0., 0., 0.],
        [0., 1., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0.]])

子图的一些操作

print(g.out_degree(0))
print(g.in_degree(0))
5
0
print(g.subgraph([1, 2, 3]))
print(g.subgraph([0, 1, 3]))
Graph(num_nodes=3, num_edges=0,
      ndata_schemes={'feat': Scheme(shape=(3,), dtype=torch.float32), 'label': Scheme(shape=(), dtype=torch.int64), 'x': Scheme(shape=(5,), dtype=torch.float32), '_ID': Scheme(shape=(), dtype=torch.int32)}
      edata_schemes={'feat': Scheme(shape=(), dtype=torch.int32), 'w': Scheme(shape=(), dtype=torch.float32), '_ID': Scheme(shape=(), dtype=torch.int32)})
Graph(num_nodes=3, num_edges=2,
      ndata_schemes={'feat': Scheme(shape=(3,), dtype=torch.float32), 'label': Scheme(shape=(), dtype=torch.int64), 'x': Scheme(shape=(5,), dtype=torch.float32), '_ID': Scheme(shape=(), dtype=torch.int32)}
      edata_schemes={'feat': Scheme(shape=(), dtype=torch.int32), 'w': Scheme(shape=(), dtype=torch.float32), '_ID': Scheme(shape=(), dtype=torch.int32)})
sg1 = g.subgraph([0, 1, 3])
print(sg1.nodes())
print(sg1.ndata[dgl.NID])  #打印子图节点在原图中的nid
# 子图中的节点继承了原图中的ndata和edata
print(sg1.ndata['feat'])
print(sg1.ndata['label'])
tensor([0, 1, 2], dtype=torch.int32)
tensor([0, 1, 3], dtype=torch.int32)
tensor([[-0.4046, -1.5649, -0.5510],
        [-1.1374, -1.0940,  1.7150],
        [ 0.8162,  0.4573, -1.3169]])
tensor([0, 1, 3])

有向图到无向图的转换

newg = dgl.add_reverse_edges(g)
print(newg.edges())
newg = dgl.to_bidirected(g)
print(newg.edges())
(tensor([0, 0, 0, 0, 0, 1, 2, 3, 4, 5], dtype=torch.int32), tensor([1, 2, 3, 4, 5, 0, 0, 0, 0, 0], dtype=torch.int32))
(tensor([0, 0, 0, 0, 0, 1, 2, 3, 4, 5], dtype=torch.int32), tensor([1, 2, 3, 4, 5, 0, 0, 0, 0, 0], dtype=torch.int32))

保存图,从磁盘加载图

dgl.save_graphs('./graph.dgl', g)
(load_g,), _ = dgl.load_graphs('./graph.dgl')
print(load_g)
Graph(num_nodes=6, num_edges=5,
      ndata_schemes={'x': Scheme(shape=(5,), dtype=torch.float32), 'label': Scheme(shape=(), dtype=torch.int64), 'feat': Scheme(shape=(3,), dtype=torch.float32)}
      edata_schemes={'w': Scheme(shape=(), dtype=torch.float32), 'feat': Scheme(shape=(), dtype=torch.int32)})
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用DGL创建自己的数据集来用于分类,可以按照以下步骤操作: 1.准备数据:将形数据存储为形文件或使用Python脚本生成形数据。确保每个节点都有唯一的ID,并且形数据以节点和边列表的形式存储。 2.使用DGL创建Graph对象:使用DGL创建一个空形对象,并使用节点和边列表填充它。 3.添加标签:为每个节点添加标签,这将成为我们的目标变量。标签可以是任何类型的标记,例如整数或字符串。 4.划分数据集:将数据集划分为训练集、验证集和测试集。 5.使用DGLDataset创建自定义数据集:使用DGL提供的DGLDataset类创建自定义数据集。在这个类中,你需要实现__init__、__getitem__和__len__方法。__init__方法用于加载数据,__getitem__方法用于返回单个数据样本,__len__方法用于返回数据集的大小。 6.创建数据加载器:使用DGL提供的Dataloader类创建数据加载器。 7.训练和测试:使用创建的数据加载器进行训练和测试。 以下是一个简单的示例,演示如何使用DGL创建自己的数据集: ```python import dgl from dgl.data import DGLDataset from dgl.dataloading import GraphDataLoader class MyDataset(DGLDataset): def __init__(self): super().__init__(name='mydataset') # Load data and labels # data is a list of tuples (src, dst) # labels is a list of integers self.data, self.labels = load_data_and_labels() # Create a DGL graph object self.graph = dgl.graph((self.data[:, 0], self.data[:, 1])) # Add labels to nodes self.graph.ndata['label'] = self.labels # Split dataset into train, validation, and test sets self.train_idx, self.valid_idx, self.test_idx = split_dataset() def __getitem__(self, idx): return self.graph, self.graph.ndata['label'][idx] def __len__(self): return len(self.graph) # Create a data loader dataset = MyDataset() train_loader = GraphDataLoader(dataset, batch_size=32, shuffle=True) # Train and test the model for epoch in range(num_epochs): for batched_graph, labels in train_loader: # Train the model pass # Test the model for batched_graph, labels in test_loader: # Evaluate the model pass ``` 在这个示例中,我们首先使用load_data_and_labels函数加载数据和标签,然后使用dgl.graph函数创建一个DGL对象。我们将标签作为节点数据添加到形中,并使用split_dataset函数将数据集划分为训练、验证和测试集。 接下来,我们使用MyDataset类创建自定义数据集,并使用GraphDataLoader类创建数据加载器。在训练和测试循环中,我们使用数据加载器加载数据,并用它们训练和测试模型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值