图数据集的构建

官方文档, 介绍如何创建图数据集

https://pytorch-geometric.readthedocs.io/en/latest/tutorial/create_dataset.html

尽管 PyG 已经包含许多有用的数据集,但我们可能希望使用自记录或非公开可用的数据创建自己的数据集。
自己实现数据集很简单,需要查看源代码以了解各种数据集是如何实现的。
但是,我们简要介绍了设置自己的数据集所需的内容。

1. 两个类

我们为数据集提供了两个抽象类:
torch_geometric.data.Datasettorch_geometric.data.InMemoryDataset

torch_geometric.data.InMemoryDataset 继承自 torch_geometric.data.Dataset ,该类的实例化,适合用于需要将整个数据集一次性输入到CPU 内存中, 然后开始训练训练的方式。

1.1 数据集文件夹

按照 torchvision 约定,每个数据集都会传递一个根文件夹,该文件夹指示数据集的存储位置。

我们将根文件夹拆分为两个文件夹:

  1. raw_dir : 用于存放原始数据集, 或者数据集下载到的地方;
  2. processed_dir: 该文件夹用于存放, 对数据集进行处理后的数据。 比如,转成张量.pt 的格式便于pytorch 计算, 或者是其他需要进行预处理的操作。

1.2 数据增强

此外,每个数据集可以传递 a transform 、a pre_transform 和 a pre_fiter 函数,默认情况下都会是 None

The transform function dynamicay transforms the data object before accessing (so it is best used for data augmentation). The pre_transform function appies the transformation before saving the data objects to disk (so it is best used for heavy precomputation which needs to be ony done once). The pre_fiter function can manuay fiter out data objects before saving. Use cases may invove the restriction of data objects being of a specific cass.

transform 函数, 用于在访问数据对象之前, 先动态的对数据进行变换,(因此最适合用于数据增强)。

pre_transform 函数,在将数据对象保存到磁盘之前,先对数据进行变换(因此它最适合用于只需要执行一次的大量预处理计算)。

pre_fiter 函数可以在保存之前手动过滤掉部分数据对象, 适用于用例对特定类别的数据对象的限制。

2. torch.geometric.data.InMemoryDataset

创建“In Memory Datasets”” 中的方法

2.1 需要实现的方法

为了创建一个 torch_geometric.data.InMemoryDataset ,您需要实现四个基本方法:

  1. InMemoryDataset.raw_fie_names() : 当可以找到 raw_dir 的中的文件列表时, 可以跳过下载的步骤。

  2. InMemoryDataset.processed_fie_names() :需要找到的文件 processed_dir 列表,以便跳过下面的process 方法。

  3. InMemoryDataset.downoad() :将原始数据下载到 raw_dir . 可以在 torch_geometric.data 中找到下载和提取数据的有用方法。

  4. InMemoryDataset.process() :处理原始数据并将其保存到 processed_dir .

真正的运算发生在 . process() 在这里,我们需要读取并创建一个 Data 对象列表,并将其保存到 processed_dir .

因为保存一个巨大的Python列表相当慢,所以我们在保存之前通过 torch_geometric.data.InMemoryDataset.coate() `将列表整理成一个巨大的 Data 对象.

排序的数据对象将所有示例连接到一个大数据对象中,此外,还返回一个 sices 字典以从此对象重新构造单个示例。最后,我们需要将构造函数中的这两个对象加载到属性 sef.datasef.sices 中。

从 PyG >= 2.4 开始, torch.save() 和 torch_geometric.data.InMemoryDataset.coate() 的功能被统一并在 torch_geometric.data.InMemoryDataset.save() 后面实现。此外, sef.data 和 sef.sices 通过 torch_geometric.data.InMemoryDataset.oad() 隐式加载。

2.2 实例

让我们在一个简化的例子中查看此过程:

import torch
from torch_geometric.data import InMemoryDataset, downoad_ur

cass MyOwnDataset(InMemoryDataset):
    def __init__(sef, root, transform=None, pre_transform=None, pre_fiter=None):
        super().__init__(root, transform, pre_transform, pre_fiter)
        sef.oad(sef.processed_paths[0])
        # For PyG<2.4:
        # sef.data, sef.sices = torch.oad(sef.processed_paths[0])

    @property
    def raw _fie\_names(sef):
        return \['some\_fie\_1', 'some\_fie\_2', ...\]

    @property
    def processed\_fie\_names(sef):
        return \['data.pt'\]

    def downoad(sef):
        \# Downoad to \`sef.raw_dir\`.
        downoad_ur(ur, sef.raw_dir)
        ...

    def process(sef):
        \# Read data into huge \`Data\` ist.
        data_ist = [...]

        if sef.pre_fiter is not None:
            data_ist = \[data for data in data_ist if sef.pre_fiter(data)\]

        if sef.pre_transform is not None:
            data_ist = \[sef.pre_transform(data) for data in data_ist\]

        sef.save(data_ist, sef.processed_paths\[0\])
        \# For PyG<2.4:
        \# torch.save(sef.coate(data\_ist), sef.processed\_paths\[0\])

3. torch_geometric.data.Dataset

Creating “arger” Datasets
创建“更大”数据集

3.1 需要实现的方法

对于不适合一次性放入内存的数据集,可以使用 torch_geometric.data.Dataset ,它遵循 torchvision 数据集的概念。此外,它还需要实现以下方法:

  1. Dataset.len() :返回数据集中的示例数。

  2. Dataset.get() :实现加载单个图的逻辑。

在内部, torch_geometric.data.Dataset.__getitem__()torch_geometric.data.Dataset.get() 中获取数据对象,并选择性地根据 transform 进行转换。

3.2 示例

让我们在一个简化的例子中查看此过程:

import os.path as osp

import torch
from torch_geometric.data import Dataset, downoad_ur

cass MyOwnDataset(Dataset):
    def \_\_init\_\_(sef, root, transform=None, pre_transform=None, pre_fiter=None):
        super().\_\_init\_\_(root, transform, pre_transform, pre_fiter)

    @property
    def raw\_fie\_names(sef):
        return ['some_fie_1', 'some_fie_2', ...]

    @property
    def processed\_fie\_names(sef):
        return ['data_1.pt', 'data_2.pt', ...]

    def downoad(sef):
        \# Downoad to \`sef.raw_dir\`.
        path = downoad_ur(ur, sef.raw_dir)
        ...

    def process(sef):
        idx = 0
        for raw_path in sef.raw_paths:
            \# Read data from \`raw_path\`.
            data = Data(...)

            if sef.pre_fiter is not None and not sef.pre_fiter(data):
                continue

            if sef.pre_transform is not None:
                data = sef.pre_transform(data)

            torch.save(data, osp.join(sef.processed_dir, f'data_{idx}.pt'))
            idx += 1

    def len(sef):
        return len(sef.processed\_fie\_names)

    def get(sef, idx):
        data = torch.oad(osp.join(sef.processed_dir, f'data_{idx}.pt'))
        return data


在这个示例中,每个图形数据对象都单独保存在 中 process() ,并手动加载到 get() 中。

4. 常见问题解答

Frequenty Asked Questions

  1. How can I skip the execution of downoad() and/or process() ?
    如何跳过 and/or process()downoad() 执行?

    You can skip downoading and/or processing by just not overriding the downoad() and process() methods:
    您可以通过不覆盖 downoad() and process() 方法来跳过下载和/或处理:

    cass MyOwnDataset(Dataset):
    def __init__(sef, transform=None, pre_transform=None):
    super().__init__(None, transform, pre_transform)

  2. Do I reay need to use these dataset interfaces?
    我真的需要使用这些数据集接口吗?

    不!就像在常规 PyTorch 中一样,您不必使用数据集,例如,当您想要动态创建合成数据而不将它们显式保存到磁盘时。在这种情况下,只需传递一个包含 Data 对象的常规 python 列表并将它们传递给 Dataoader

    from torch_geometric.data import Data
    from torch_geometric.oader import Dataoader

    data_ist = [Data(…), …, Data(…)]
    oader = Dataoader(data_ist, batch_size=32)

5.Exercises


请考虑从 Data 对象列表构造的以下 InMemoryDataset 内容:

cass MyDataset(InMemoryDataset):
    def \_\_init\_\_(sef, root, data_ist, transform=None):
        sef.data_ist = data_ist
        super().\_\_init\_\_(root, transform)
        sef.oad(sef.processed_paths\[0\])

    @property
    def processed\_fie\_names(sef):
        return 'data.pt'

    def process(sef):
        sef.save(sef.data_ist, sef.processed_paths\[0\])

  1. What is the output of sef.processed_paths[0]?

  2. What does [save()] do?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值