PyG教程(2):图数据
一.概述
PyG是面向图数据的,它同时支持同构图(homogeneous graphs)和异构图(heterogeneous)。同构图指只包含一种类型的节点和边的图(下图左)。而异构图指包含两种及以上类型的节点和边的图(下图右)。
在PyG中,同构图被描述为torch_geometric.data.Data
类的实例,而异构图被描述为torch_geometric.data.HeteroData
的实例。
本文主要介绍PyG关于同构图的的相关操作,操作环境为:
pytorch = 1.10.1
cuda = 11.3
torch_geometric = 2.0.4
二.基本图操作
2.1 图的创建
同构图是用Data
类是进行描述的,因此首先查看其初始化函数的参数列表:
def __init__(self, x: OptTensor = None, edge_index: OptTensor = None,edge_attr: OptTensor = None, y: OptTensor = None,pos: OptTensor = None, **kwargs):
对应的参数说明为:
参数 | 说明 |
---|---|
x
|
节点特征矩阵,shape为[num_nodes, num_node_features] ,Tensor 类型
|
edge_index
|
边索引(边表),shape为[2, num_edges] ,在这个包含两行的数组中,第1行与第2行中对应索引位置的值分别表示一条边的源节点和目标节点,LongTensor 类型。
|
edge_attr
|
边特征矩阵,shape为[num_edges, num_edges_featrues] ,Tensor 类型
|
y
|
图级标签或节点级标签,Tensor 类型
|
pos
|
节点的位置矩阵,shape为[num_nodes, num_dimensions] ,Tensor 类型
|
**kwargs
|
用户自定义的额外属性,传入格式需为attr_name=attr_value
|
Data
类的初始化函数中参数默认值都为None
,这意味着没有哪个参数是必要的,在实际使用时需要根据待构造图的实际情况来传入相应的属性。
2.2 常用的图属性与方法
在PyG中,对于一个Data
对象其包含众多属性和方法,这里列举一下常用的,更详细的请参见官网Data部分。
方法/属性 | 说明 |
---|---|
num_node_features /num_features
|
图节点数特征(维度)数 |
num_edge_features
|
图中边的特征(维度)数 |
keys
|
图属性名列表 |
num_edges
|
图边数 |
num_nodes
|
图节点数 |
is_directed() /is_undirected()
|
是否为有向图/无向图 |
is_cuda
|
图是否存储在GPU上 |
has_self_loops() /contains_self_loops()
|
图中节点是否包含自环 |
has_isolated_nodes() /contains_isolated_nodes()
|
图中是否包含孤立节点 |
to(device)
|
将图实例放置到指定的设备(GPU或CPU)上 |
clone()
|
对图进行深拷贝 |
2.3 演示示例
首先创建一个包含5个顶点、12条边的无向图。需要注意的是,在edge_index
中边都有有方向的,即从源节点到目标节点。若要创建从节点vvv到节点uuu的无向边,则需要在edge_index
中传入两条相应的边,即(u,v), (v,u)
。
import torch
import torch_geometric.data as data
from torch_geometric.utils import to_networkx
import matplotlib.pyplot as plt
import networkx as nxedge_index = torch.LongTensor([[0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4],[1, 2, 4, 0, 2, 1, 0, 3, 2, 4, 3, 0]])
x = torch.ones(5, 2)
g = data.Data(edge_index=edge_index, x=x)
print(g)
"""
Data(edge_index=[2, 12], x=[5, 2])
"""
# 转换为nextworkx格式的图并可视化
g = to_networkx(g)
nx.draw(g, with_labels=g.nodes)
plt.show()
创建的图可视化结果为:
对上述创建的Data
对象应用2.2节介绍的部分方法实例代码如下:
print(g.num_nodes, g.num_edges)
# 5 12
print(g.keys)
# ['x', 'edge_index']
print(g.num_node_features)
# 2
print(g.is_undirected())
# True
print(g.has_isolated_nodes())
# False
若要将自己创建的图实例保存到本地磁盘或从本地磁盘加载保存的图数据,可以使用torch.save()
和torch.load()
:
torch.save([g], "temp/data.pt")
g = torch.load("temp/data.pt")
print(g)
# [Data(edge_index=[2, 12], x=[5, 2])]
三.进阶图操作
在torch_geometric.utils
模块中包含了许多对图数据的高级操作方法,下面将对其中最常用的方法进行介绍。
3.1 度的计算
通过degree(index, num_nodes=None)
方法可以计算图中节点的度,其中:
index
:edge_index
中的两个维度中任意一个num_nodes
:节点的数量,可选参数
示例代码:
print(degree(g.edge_index[0]))
# tensor([3., 2., 3., 2., 2.])print(degree(g.edge_index[1]))
# tensor([3., 2., 3., 2., 2.])
3.2 自环的添加与删除
自环指节点指向自身的边。在utils
中处理自环的方法包括:
contains_self_loops(edge_index)
:判断图中节点是否包含自环。remove_self_loops(edge_index)
:删除图中所有的自环。add_self_loops(edge_index)
:为图中的节点添加自环,对于有自环的节点,它会再为该节点添加一个自环。add_remaining_self_loops
:为图中还没有自环的节点添加自环。
示例代码:
print(contains_self_loops(g.edge_index))
# Falseedge_index, _ = add_self_loops(g.edge_index)
print(edge_index)
"""
tensor([[0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 0, 1, 2, 3, 4],[1, 2, 4, 0, 2, 1, 0, 3, 2, 4, 3, 0, 0, 1, 2, 3, 4]])
"""edge_index, _ = add_remaining_self_loops(edge_index)
print(edge_index)
"""
没有添加新的自环
tensor([[0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 0, 1, 2, 3, 4],[1, 2, 4, 0, 2, 1, 0, 3, 2, 4, 3, 0, 0, 1, 2, 3, 4]])
"""edge_index, _ = remove_self_loops(edge_index)
print(edge_index)
"""
tensor([[0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4],[1, 2, 4, 0, 2, 1, 0, 3, 2, 4, 3, 0]])
"""
3.2 子图提取
utils
中提供了若干方法用来在图中提取子图。
subgraph(subset, edge_index)
:根据给定的图节点集合subset
来抽取图中包含这些节点的子图。k_hop_subgraph(node_idx, num_hops, edge_index)
:提取给定节点集node_idx
能经过num_hops
跳到达的所有节点组成的子图(包括node_idx
本身)。
sub_graph
方法示例代码:
def draw(edge_index):graph = data.Data(edge_index=edge_index)graph = to_networkx(graph)print(graph.nodes)nx.draw(graph, with_labels=graph.nodes)plt.show()edge_index, _ = subgraph(subset=torch.LongTensor([0, 1, 2]), edge_index=g.edge_index)
draw(edge_index)
提取的子图可视化如下所示:
k_hop_subgraph
方法的示例代码如下所示:
g = k_hop_subgraph(node_idx=[0], num_hops=1, edge_index=g.edge_index)
print(g)
"""
(tensor([0, 1, 2, 4]), tensor([[0, 0, 0, 1, 1, 2, 2, 4],[1, 2, 4, 0, 2, 1, 0, 0]]), tensor([0]), tensor([ True, True, True, True, True, True, True, False, False, False,False, True]))
"""
从上图可以看出,该方法返回一个4元组,元组的4个元素依次为:子图的节点集、子图的边集、用来查询的节点集(中心节点集)、指示原始图g
中的边是否在子图中的布尔数组。我们取子图的边集进行可视化结果如下:
3.4 转换为无向图
通过to_undirected(edge_index)
可以将一个图转换为无向图:
edge_index = torch.LongTensor([[0, 0], [1, 2]])
edge_index = to_undirected(edge_index)
print(edge_index)
"""
tensor([[0, 0, 1, 2],[1, 2, 0, 0]])
"""
结语
参考资料:
- torch_geometric.data
- torch_geometric.utils
本文主要介绍了PyG中对单个图的相关操作方法,从上面的操作可以看出对于PyG对图结构的操作其实就是在操作edge_index
(该属性本来就用来在PyG中保存图的结构信息)。
PyG教程(2):图数据相关推荐
- (DataWhale)图神经网络Task01:基于PyG包的图数据的表示与使用
文章目录 PyG`Data`类初识 `graph_data`对象的创建: `graph_data`实例初探 PyG`Dataset`类初识 内置数据集(Cora)的下载 作业1 PyGData类初识 ...
- Keras图数据学习
[导读]本文介绍了一个理由Keras和TensorFlow进行图数据学习.分类的工程. Github链接: https://github.com/CVxTz/graph_classification ...
- PYG教程【三】对Cora数据集进行半监督节点分类
Cora数据集 PyG包含有大量的基准数据集.初始化数据集非常简单,数据集初始化会自动下载原始数据文件,并且会将它们处理成Data格式. 如下图所示,Cora数据集中只有一个图,该图包含2708个节点 ...
- 初识图机器学习(part2)--图数据
学习笔记,仅供参考 学习资料:图机器学习教程 文章目录 图机器学习 图数据 图数据常见的描述形式 邻接矩阵的特点 邻接列表的特点 无向图的图数据 带权图的图数据 二部图 广度优先搜索(BFS) 深度优 ...
- 函数调用关系图如何画_彩铅画入门植物教程 | 如何用彩铅画一株多肉?多肉彩铅画教程步骤图详细...
画画不难,难的是不拿起手中的笔去画. 彩铅画入门植物教程 | 如何用彩铅画一株多肉?多肉彩铅画教程步骤图详细 多肉的质感如何表达呢?还是那句话:艺术来源于生活,要仔细观察.拿我们今天画的多肉来说,首先 ...
- EEGLAB系列教程5:数据预处理2(ICA去伪迹)
EEGLAB系列教程5:数据预处理2(ICA去伪迹) 今天介绍EEG数据处理系列教程5,在前面的几期中,已经介绍了数据基本处理过程,可以参见以下链接: EEGLAB系列教程1:安装和启动 EEGLAB ...
- FME教程:表格数据分组统计总数的三种实现方式
在FME中进行表格数据分组统计总数的三种方式,实现类似SQL中分组统计总数的功能. 一.业务场景 现在有图1所示的一份Excel表格数据,要求统计每个村的户数,如图2所示. 图1 Excel表格数据 ...
- ADODB 入门学习基础教程[多图]
ADODB 入门学习基础教程[多图] 1. 前言 ADODB 是 Active Data Objects Data Base 的简称,它是一种 PHP 存取数据库的函式组件.现在 SFS3 系统 (校 ...
- 数据可视化工具-小马BI简单教程【大数据专业必学】
数据可视化工具-小马BI简单教程[大数据专业必学] 高效处理数据 一.数据接入 二.数据处理 三.可视化分析 推荐一款轻量级数据可视化工具--小马BI 这款工具有助于发掘数据驱动业务的价值,对产品,运 ...
- 可视化图表进阶教程:业务数据地图的绘制
在上篇文章--<可视化图表入门教程>中,我们学会了基础可视化图表的使用,那么进阶可视化图表需要掌握哪些图表类型呢?本篇文章将为大家讲解"可视化图表进阶教程:业务数据地图的绘制&q ...
最新文章
- The substring() Method in JDK 6 and JDK 7
- shell习题第6题:监听80端口
- Java多线程之线程虚假唤醒
- python核心编程第六章练习6-12
- keepalived详解(三)——keepalived与Nginx配合实战
- error trying to exec 'cc1plus': execvp: 没有那个文件或目录
- 阿里云 DNS 运维服务的演进和实践
- 微信朋友圈服务器缓存,如何找到微信朋友圈照片缓存
- 天津90、北京54坐标和WGS84坐标
- 微信公众号(服务号)授权登录
- Word恢复忘记保存的文件(打开任意.asd文件)
- python字典根据值求键
- windows多显示器任务栏设置:拖动窗口后任务栏显示在对应的显示器上
- linux内存管理笔记(十一)---CMA
- 复数的辐角的主值的计算公式
- 文件误删秒恢复!微软又发布了一款命令行神器!
- 引入spring-boot-starter-redis包报错 :unknown
- 渗透分支写脚本_抖音文案怎么写吸引人?最新文案创作技巧分享(赠文案脚本模板)...
- 嵌入式AI基础知识介绍
- osgEarth示例分析——osgearth_shadercomp