图神经网络学习
本文主要对图的基础知识以及PyG中Data对象和Dataset对象的使用做简单描述。
图基本知识
图的分类
图的度和邻居
图的邻接矩阵
PyG学习
Data类
首先,假设给定如下一张图:
该图是无权无向图,图中共有5个节点,每个节点用一个三维向量来表示。我们构建一个表示该图数据的Data对象。
首先将所需要的包导入
import torch
from torch_geometric.data import Data
其次,构建节点特征矩阵:
x = [[0,1,0],[1,1,3],[2,1,0],[3,1,3],[4,2,3]]
x = torch.tensor(x, dtype=torch.int)
x
输出的节点特征矩阵如下:
构造edge_index,edge_index 的每一列定义一条边,其中第一行为边起始节点的索引,第二行为边结束节点的索引。这种表示方法被称为COO格式(coordinate format),通常用于表示稀疏矩阵。PyG不是用稠密矩阵
A
∈
{
0
,
1
}
∣
V
∣
×
∣
V
∣
\mathbf{A} \in\{0,1\}^{|\mathcal{V}| \times |\mathcal{V}|}
A∈{0,1}∣V∣×∣V∣来持有邻接矩阵的信息,而是用仅存储邻接矩阵中非元素的稀疏矩阵来表示图。
coordinate format简单介绍
开始构造edge_index:
edge_index = torch.tensor([[0, 1, 1, 2, 0, 4, 3, 4],
[1, 0, 2, 1, 4, 0, 4, 3]], dtype=torch.long)
edge_index
构建Data对象:
data = Data(x=x, edge_index=edge_index)
data
输出结果如下:
因为图为无向图,所以存在8条边,5个节点,每个节点有三个特征。
查看构造的data对象的属性:
data.num_nodes # 5 ---->节点数为5
data.num_edges # 8 ---->边数为8
data.num_features # 3 ----> 节点特征维度为3
data.is_directed() # False ----->无向图
data.contains_isolated_nodes() # False ---->不包含孤立节点
data.contains_self_loops() # False ----> 没有添加自环
'edge_attr' in data # False ----> 该对象没有设置边属性
通过其他方式构造Data对象
1.将dict字典对象转为Data对象
graph_dict = { 'x': x,
'edge_index': edge_index,
# 'edge_attr': edge_attr,
# 'y': y, 'num_nodes': num_nodes,
# 'other_attr': other_attr
}
graph_data = Data.from_dict(graph_dict)
graph_data
上述代码用到的from_dict是一个类方法:
@classmethod
def from_dict(cls, dictionary):
r"""Creates a data object from a python dictionary."""
data = cls()
for key, item in dictionary.items():
data[key] = item
return data
Dataset类
PyG内置了大量常用的基准数据集,接下来我们以PyG内置的Planetoid数据集为例,来学习PyG中图数据集的表示及使用。
数据集下载地址
数据集根据自己情况下载到自定义的目录:
from torch_geometric.datasets import Planetoid
dataset = Planetoid(root='/dataset/Cora', name='Cora')
查看dataset属性:
dataset.num_classes # 7 ----> Cora数据集包含七种类别的节点(每篇节点代表一篇文章)
dataset.num_features # 1433 ----> 节点特征维度 1433
data = dataset[0]
data # Data(edge_index=[2, 10556], test_mask=[2708], train_mask=[2708], val_mask=[2708], x=[2708, 1433], y=[2708])
data.is_undirected() # True
data.train_mask.sum().item() # 140
data.val_mask.sum().item() # 500
data.test_mask.sum().item() # 1000
作业
请通过继承Data类实现一个类,专门用于表示“机构-作者-论文”的网络。该网络包含“机构“、”作者“和”论文”三类节点,以及“作者-机构“和 “作者-论文“两类边。对要实现的类的要求:1)用不同的属性存储不同节点的属性;2)用不同的属性存储不同的边(边没有属性);3)逐一实现获取不同节点数量的方法。
构造一个网络如下:
import torch
from torch_geometric.data import Data
x = [[0,1,0],[1,1,3],[4,2,3],[2,1,0],[3,1,3]]
x = torch.tensor(x, dtype=torch.int)
x
edge_index = torch.tensor([[0, 1, 0, 2, 1, 3, 2, 4],
[1, 0, 2, 0, 3, 1, 4, 2]], dtype=torch.long)
edge_index
class NewData(Data):
def __init__(self, x=None, edge_index=None,
ins_num=None, author_num=None, article_num=None, edge_attr=None):
super(Data, self).__init__()
self.x = x
self.edge_index = edge_index
self.num_nodes = ins_num + author_num + article_num
self.edge_attr = edge_attr
self.institution_x = x[:ins_num]
self.author_x = x[ins_num:ins_num+author_num]
self.article_x = x[ins_num+author_num:]
self.author_ins = edge_index[:,:2*ins_num*author_num]
self.author_article = edge_index[:,2*ins_num*author_num:]
new_data = NewData(x, edge_index,1,2,2)
new_data
输出结果如下:
查看new_data属性
new_data.author_article
输出作者到论文的边的信息:
new_data.author_x
输出作者节点的属性信息:
new_data.article_x
输出论文节点的属性信息:
new_data.num_nodes # 5
new_data.num_edges # 8
new_data.is_undirected() # True
new_data.contains_isolated_nodes() # False
new_data.contains_self_loops() # False
new_data.is_coalesced() # False