程序 = 数据结构 + 算法。若想使用 PyTorch geometric 中各种有用的模型和函数,数据集的结构必须符合 PyG 的既定标准,例如 PyG 自带的 Planetoid 等数据集类。为了处理自己独有的数据集,我们必须掌握如何将原始数据转化为对应的数据集类。
PyG 构建数据集分两种, 一种继承 torch_geometric.data.InMemoryDataset,一次性加载所有数据到内存;另一种继承torch_geometric.data.Dataset, 分次加载到内存。对于占用内存有限的数据集,我们可以将所有数据都存储到内存里,通过继承 InMemoryDataset 去构建数据集类。
在本文中,我们主要学习如何构建 InMemoryDataset 类,以及完成基于节点表征学习的图节点预测和边预测任务。
1. 图数据集构建:继承 InMemoryDataset 类
1.1 准备好原始的数据文件(raw)
在使用 Planetoid 中的数据集做练习的时候,我们发现程序会自动下载后缀为 'x', 'tx', 'allx', 'y', 'ty', 'ally', 'graph', 'test.index' 的数据文件,然后将其处理为后缀为 'pt' 的数据文件,最后被读取成为能够被 Python 处理的 Data 对象。
因此,我们必须需要了解原始的数据文件结构,才能知道如何转化、处理我们自己的数据集。
ind.dataset_str.x # the feature vectors of the training instances
ind.dataset_str.tx # the feature vectors of the test instances
ind.dataset_str.allx # the feature vectors of both labeled and unlabeled training instances (a superset of ind.dataset_str.x)
# The objects as scipy.sparse.csr.csr_matrix object
ind.dataset_str.y # the one-hot labels of the labeled training instances
ind.dataset_str.ty # the one-hot labels of the test instances
ind.dataset_str.ally # the labels for instances in ind.dataset_str.allx
# The objects as numpy.ndarray object
ind.dataset_str.graph # a dict in the format {index: [index_of_neighbor_nodes]} as collections.defaultdict object;
ind.dataset_str.test.index # the indices of test instances in graph, for the inductive setting as list object.
#All objects above must be saved using python pickle module.
#:param dataset_str: Dataset name
在准备好原始的数据文件后(下载或自己生成),我们就可以继续处理生成 Data 对象。如果我们将自己生成的原始数据文件放到网络上,也可以构建一个类似 Planetoid 的数据集类以方便使用。
1.2 InMemoryDataset 类简介
简介:创建在 CPU 内存里运行的图数据集的数据集基类 父类:torch_geometric.data.dataset.Dataset
类初始化及其参数说明:
CLASS InMemoryDataset(root: Optional[str] = None, transform: Optional[Callable] = None, pre_transform: Optional[Callable] = None, pre_filter: Optional[Callable] = None)
-
root
:字符串类型,存储数据集的文件夹的路径。该文件夹下有两个文件夹:-
一个文件夹为记录在
raw_dir
,它用于存储未处理的文件,从网络上下载的数据集原始文件会被存放到这里; -
另一个文件夹记录在
processed_dir
,处理后的数据被保存到这里,以后从此文件夹下加载文件即可获得 Data 对象。 -
注:raw_dir 和 processed_dir 是属性方法,我们可以自定义要使用的文件夹。 root 的目录结构如下图所示:
-
其他的重要参数如下(可不设置):
-
transform
:函数类型,一个数据转换函数。此函数在每一次数据获取过程中都会被执行。此函数应该用于数据增广(Data Augmentation)。 -
pre_transform
:函数类型,一个数据转换函数。此函数在Data对象被保存到文件前调用。因此它应该用于只执行一次的数据预处理。 -
pre_filter
:函数类型,一个检查数据是否要保留的函数。
通过继承 InMemoryDataset 类来构造一个我们自己的数据集类,我们需要实现四个基本方法:
-
raw_file_names()
:属性方法,返回一个数据集原始文件的文件名列表,数据集原始文件应该能在raw_dir
文件夹中找到,否则调用download()
函数下载文件到raw_dir文件夹。 -
processed_file_names()
:属性方法,返回一个存储处理过的数据的文件的文件名列表,存储处理过的数据的文件应该能在processed_dir
文件夹中找到,否则调用 process() 函数对样本做处理,然后保存处理过的数据到processed_dir
文件夹下的文件里。 -
download()
: 下载数据集原始文件到raw_dir
文件夹。 -
process()
: 处理数据,保存处理好的数据到processed_dir
文件夹下的文件。 其中,比较重要的,区分数据集类不同的是 download 和 process 函数,需要设定数据集的下载地址和数据处理方式。raw_file_names 和 processed_file_names 一般不变。
1.3 InMemoryDataset 数据集类实例
通过例子我们可以更快地掌握 InMemoryDataset 的使用方法和注意事项。我们将首先学习 PlanetoidPubMed 数据集类的构造,其次学习使用时会程序运行的过程。构造代码如下所示:
import os.path as osp
import torch
from torch_geometric.data import (InMemoryDataset, download_url)
from torch_geometric.io import read_planetoid_data
class PlanetoidPubMed(InMemoryDataset):
url = 'https://github.com/kimiyoung/planetoid/raw/master/data'
# url = 'https://gitee.com/rongqinchen/planetoid/raw/master/data'
# 如果github的链接不可用,请使用gitee的链接
def __init__(self, root, transform=None, pre_transform=None):
super(PlanetoidPubMed, self).__init__(root, transform, pre_transform)
self.data, self.slices = torch.load(self.processed_paths[0])
# 在本实例中载入 data.pt 文件
# processed_paths()属性方法是在基类中定义的,它对self.processed_dir文件夹与processed_file_names()属性方法的返回的每一个文件