Python 包 dhg 中超图的数据格式


1 dhg 介绍

下面是官方介绍

DHG (DeepHypergraph) 是基于 PyTorch 的深度学习包, 可用于图神经网络以及超图神经网络。 其支持从 顶点到顶点从一个域的顶点到另一个域的顶点从顶点到超边,、从超边到顶点从顶点集到顶点集 等低阶或高阶信息传递的通用框架。

其支持大量低阶关联结构(图、有向图、二分图等)以及高阶关联结构(超图等)。 大量基于谱域的操作(例如基于拉普拉斯的平滑)和基于空域的操作(例如从域到域的信息传递)集成在不同的关联结构中。 其为不同任务的性能评测提供多种通用评测指标,并且覆盖多种当前最先进的模型以便简单使用。 我们同样为低阶或高阶关联结构提供多种可视化工具。

除此之外,DHG的 dhg.experiments 模块基于 Optuna 实现了 Auto-ML, 可以帮您调整模型训练超参数以便轻松超过最先进的的模型。

批注:如果对超图还不太了解的话,可以看看我的其他博客。

传送门


2 超图数据

最近在研究超图,因此接触了这个包。对于超图数据集结构有了一个粗浅的了解,分享出来和更多的同道交流。

在使用之前,确保当前的 Python 环境已经安装好了 dhg。导入数据集 Cooking200,作为样例来解读。

from dhg.data import Cooking200

if __name__ == "__main__":
	# for example
    data = Cooking200()

通过上面 3 行代码,就加载好了超图数据集 “Cooking200”。

接下来的所有操作,都是在交互环境中进行的。
(1) 查看变量 data 结构

>>> data
This is cooking_200 dataset:
  ->  num_classes
  ->  num_vertices
  ->  num_edges
  ->  edge_list
  ->  labels
  ->  train_mask
  ->  val_mask
  ->  test_mask
Please try `data['name']` to get the specified data.

输出一段文本信息,并给出提示 “请采用 data[‘name’] 形式来获取指定部分数据”。
变量 data 的数据结构类似于字典(dict)。

(2) 查看 data 的类型

>>> type(data)
<class 'dhg.data.cooking_200.Cooking200'>

变量 data 的类型为 dhg.data.cooking_200.Cooking200,是一个 Cooking200 类变量。

(3) 查看类别数量

>>> data['num_classes']
20

输出结果为整数 20,表明 Cooking200 是一个包含 20 个分类类别的数据集。

(4) 查看顶点个数

>>> data['num_vertices']
7403

输出结果为整数 7403, 表明由 Cooking200 数据集构建的超图包含 7403 个顶点。

(5) 查看超边数量

>>> data['num_edges']
2755

输出结果为整数 2755,表明由 Cooking200 数据集构建的超图包含 2755 条超边。

(6) 查看超边

>>> data['edge_list']
[[0, 56, 174, 433, 447, 586, 820, 965, 1120, 1288, 1578, 2208, 2420, 2582, 2626, 3359, 3799, 3860, 3918, 4074, 4498, 4708, 5004, 5095, 5114, 5262, 5409, 5444, 5472, 5998, 6082, 6309, 6601, 6692, 7074, 7192, 7290],
[0, 42, 58, 78, 139, 251, 268, 466, 633, 710, 745, 749, 768, 790, 822, 882, 899, 949, 954, 972, 1094, 1254, 1285, 1313, 1340, 1367, 1472, 1522, 1553, 1591, 1637, 1639, 1641, 1677, 1721, 1726, 1780, 1863, 1888, 1948, 1953, 1978, 1994, 1995, 2002, 2057, 2105, 2203, 2406, 2466, 2474, 2488, 2519, 2663, 2721, 2727, 2750, 2787, 2794, 2890, 2953, 3005, 3047, 3126, 3175, 3191, 3197, 3210, 3251, 3279, 3298, 3299, 3377, 3494, 3521, 3566, 3585, 3645, 3661, 3665, 3757, 3777, 3832, 3837, 3860, 3936, 3951, 3969, 3995, 4023, 4046, 4052, 4133, 4175, 4236, 4316, 4334, 4339, 4341, 4398, 4420, 4473, 4537, 4543, 4565, 4606, 4615, 4646, 4671, 4677, 4729, 4731, 4734, 4764, 4848, 4881, 4930, 4969, 4970, 4973, 4990, 4999, 5032, 5052, 5053, 5062, 5159, 5189, 5227, 5379, 5383, 5407, 5417, 5421, 5448, 5456, 5503, 5534, 5584, 5603, 5632, 5705, 5706, 5708, 5756, 5910, 5965, 5990, 6051, 6214, 6247, 6252, 6499, 6521, 6672, 6694, 6722, 6759, 6807, 6859, 6869, 6896, 6919, 6928, 6940, 7003, 7036, 7091, 7134, 7151, 7218, 7252, 7259, 7359],
[...],
]

>>> len(data['edge_list'])
2755

输出结果为长度不等的列表组成的列表。列表中的每一个元素都是顶点组成的超边(列表),每个顶点用一个整数标记。这里具体存储的超边。

(7) 查看标签及其大小

>>> data['labels']
tensor([ 5, 12,  6,  ..., 15, 12, 12])

>>> data['labels'].shape
torch.Size([7403])

输出结果是一个包含 7403 个整型值的张量。每个值是一个整数,用于标记每个标签值。

前面提到过 data[‘num_classses’] 表示的是数据集中类别数,那么 data[‘labels’] 中的非重复元素个数应该与之相等。试一试:

>>> data['labels'].min()
tensor(0)

>>> data['labels'].max()
tensor(19)

标签的最小值为 0,最大值为 19,因此标签值共有(19-0+1=20)个,与 data[‘num_classes’] 值相等。

批注:这种方法有一个限制条件,标签值必须是顺序编码,中间不能有缺失。

还有一种更加普适的方法,不存在任何限制条件。

>>> set(data['labels'].numpy())
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}

>>> len(set(data['labels'].numpy()))
20

用 set() 方法对 data[‘labels’] 中的标签值进行取集合操作,只剩下不重复的标签值留下。人工查看一下,确实是 0-19 之间的编码。如果个数比较多,容易出错。所以进一步地,使用 len() 方法求取集合的长度,获得不重复的标签值数量。

批注:直接对 Tensor 进行集合操作,会导致 Tensor 中每个元素都被独立出来,并不会得到数学意义上的集合。因此,需要先使用 Tensor.numpy() 方法对 Tensor 进行 Numpy 转换。在此基础上,再使用 set() 操作。

(8) 查看训练掩码

>>> data['train_mask']
tensor([False, False, False,  ..., False, False, False])

>>> data['train_mask'].shape
torch.Size([7403])

输出结果是一个包含 7403 个布尔值的张量,其大小与标签集的大小一致。

(9) 查看验证掩码

>>> data['val_mask']
tensor([False, False, False,  ..., False, False, False])

>>> data['val_mask'].shape
torch.Size([7403])

输出结果是一个包含 7403 个布尔值的张量,其大小与标签集的大小一致。

(10) 查看测试掩码

>>> data['test_mask']
tensor([True, True, True,  ..., True, True, True])

>>> data['test_mask'].shape
torch.Size([7403])

输出结果是一个包含 7403 个布尔值的张量,其大小与标签集的大小一致。

批注:那么上面三个是干什么用的呢?

实际上,在人工智能领域,数据一般分为训练集和测试集。训练集用于模型的构建、训练、参数调整等,测试集用于验证模型的可用性。划分成训练集和测试集,会导致训练完成后,模型不知道自身怎么样,是好是坏。评价必须要等到测试时才知道。为了解决这个问题,研究人员进一步将数据集分为训练集、验证集、测试集。验证集的作用就是在训练过程中对模型进行评估,及时得到反馈调整模型,优化参数等等。这一举措,有利于构建表现更优秀的模型。

数据集作用
训练集模型构建、训练
验证集对训练的模型进行验证反馈
测试集最终的评价、测试

说回这个数据集,data[‘train_mask’]、data[‘val_mask’]、data[‘test_mask’] 就是用作训练集、验证集、测试集用的。

但是实际操作时,难道放三个数据集?也可以,不过不是很便捷。更常见的操作是,一个原始数据,然后加上数据标记。

当一行(样本)数据被标记为 “train” 时,该行数据被用作训练(样本)数据;当被标记为 “val” 时,该行数据被用作验证(样本)数据;当被标记为 “test” 时,该行数据被用作测试(样本)数据。当然,也可以是其他标记方式,如 “0,1, 2” 等。

data[‘train_mask’]、data[‘val_mask’]、data[‘test_mask’] 采用的是布尔类型的变量,当值为 True 时,该行(样本)数据被放到对应的集合中。

>>> data['train_mask'].sum()
tensor(200)

>>> data['val_mask'].sum()
tensor(200)

>>> data['test_mask'].sum()
tensor(7003)

由于变量类型采用的是布尔类型,这就给了我们可以操作的空间。布尔值是可以累加的,由此可以计算出每个部分数据集的占比。

数据集数量占比
训练集2002.70 %
验证集2002.70 %
测试集700394.60 %

批注:训练集的占比也太小了吧。


3 总结

那么,将上面的信息进行汇总,总结一下。
数据集 Cooking200 的基本信息如下表所示:

变量信息来源
类别数量20data[‘num_classes’]
顶点数量7403data[‘num_vertices’]
超边数量2755data[‘num_edges’]
超边内容data[‘edge_list’]
标签值data[‘labels’]
训练集大小200data[‘train_mask’]
验证集大小200data[‘val_mask’]
测试集大小7003data[‘val_mask’]

批注:其实还有一些隐藏信息,需要各位去挖掘了。


4 参考

  1. Y. Feng, H. You, Z. Zhang, R. Ji et.al. Hypergraph neural networks. In Proceedings of the AAAI conference on artificial intelligence, 2019 (Vol. 33, No. 01, pp. 3558-3565).
  2. DHG简介
  • 20
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值