构建输入数据

Hint

DHG包含许多可用于训练模型和测试模型的数据集。 在这一节中,将会介绍如何使用DHG的 data 模块、构建数据对象的结构和构建自定义数据集的方法及指定预处理步骤。 我们期待您在 GitHub 提交pull request贡献数据集, 请参考 贡献教程 的指引。

使用方法

如果您的网络没问题,你可以直接使用 dhg.data 内的如下数据集:

>>> import dhg
>>> d = dhg.data.Cora()
>>> d
cora dataset:
->  num_classes
->  num_vertices
->  num_edges
->  dim_features
->  features
->  edge_list
->  labels
->  train_mask
->  val_mask
->  test_mask
>>> d = dhg.data.Cooking200()
>>> d
cooking_200 dataset:
->  num_classes
->  num_vertices
->  num_edges
->  edge_list
->  labels
->  train_mask
->  val_mask
->  test_mask
>>> d = dhg.data.MovieLens1M()
>>> d
movielens_1m dataset:
->  num_users
->  num_items
->  num_interactions
->  train_adj_list
->  test_adj_list

或者可以手动从 DHG’s data repository 下载数据集。 然后,您可以把数据集放置在 dhg.CAHE_ROOT 文件夹或者其它任何目录。 可以使用如下代码获取 CACHE_ROOT

>>> dhg.CACHE_ROOT
PosixPath('/home/fengyifan/.dhg')

如果数据集存放在您的指定目录 <your-directory> ,可以使用如下代码导入数据集:

Note

需要将您下载的数据集的父目录传给参数 data_root

>>> dhg.data.Cora(data_root=<your-directory>)

一旦您导入了数据集并且获取数据集对象 d ,可以使用如下代码获取数据集的 预处理后的数据项

>>> d = dhg.data.Cora()
>>> # print all available items in the dataset
>>> d
cora dataset:
->  num_classes
->  num_vertices
->  num_edges
->  dim_features
->  features
->  edge_list
->  labels
->  train_mask
->  val_mask
->  test_mask
>>> d['num_classes']
7
>>> d["edge_list"]
[(0, 633), (0, 1862), (0, 2582), (1, 2), ..., (2707, 165), (2707, 1473), (2707, 2706)]
>>> d['features']
tensor([[0., 0., 0.,  ..., 0., 0., 0.],
        [0., 0., 0.,  ..., 0., 0., 0.],
        [0., 0., 0.,  ..., 0., 0., 0.],
        ...,
        [0., 0., 0.,  ..., 0., 0., 0.],
        [0., 0., 0.,  ..., 0., 0., 0.],
        [0., 0., 0.,  ..., 0., 0., 0.]])
>>> d['labels']
>>> d['labels']
tensor([3, 4, 4,  ..., 3, 3, 3])
>>> d['train_mask']
tensor([ True,  True,  True,  ..., False, False, False])
>>> d = dhg.data.MovieLens1M()
>>> # print all available items in the dataset
>>> d
movielens_1m dataset:
->  num_users
->  num_items
->  num_interactions
->  train_adj_list
->  test_adj_list
>>> d['num_users']
6022
>>> d['test_adj_list']
[[0, 2968, 228, 38, 422, 2769], [1, 621, 900, ...], ..., [..., 1579, 3039, 1699, 1195]]

如果需要获取 未预处理的数据项,需要调用 raw() 方法:

>>> d = dhg.data.Cora()
>>> ft = d['features']
>>> ft.sum(1)
tensor([1.0000, 1.0000, 1.0000,  ..., 1.0000, 1.0000, 1.0000])
>>> raw_ft = d.raw('features')
>>> raw_ft.sum(1)
matrix([[ 9.],
        [23.],
        [19.],
        ...,
        [18.],
        [14.],
        [13.]], dtype=float32)

Cora数据集内的顶点特征默认使用L1归一化预处理。 下一步,可以参考 从边列表构建图 教程,来从Cora数据集中构建用于训练的图结构。

模块架构设计

下图展示构建DHG数据集模块的架构设计。

dataset_architecture

建立自己的数据集

首先,您的数据集类应该继承DHG数据集的基类 BaseData

>>> from dhg.data import BaseData

数据集中的所有数据项都在 _content 字典中配置。 同时,支持以下操作:

  • 从远程服务器下载 -> 从本地文件加载 -> 预处理并返回

  • 从本地文件加载 -> 预处理并返回

  • 直接返回

可以在 这里 找到DHG支持的加载函数。

可以在 这里 找到DHG支持的预处理函数。

如果数据项 item 需要从远程服务器下载,您需要在 _content 字典中指定键 uponloaderpreprocess 。 键 upon 为字典列表,每一个字典至少包含 键 filenamemd5filename 为需要下载的文件名, md5 为文件的md5校验码。 默认情况下,远程文件会存放在 REMOTE_DATASETS_ROOT \ data_root \ name \ filename 目录。

self._content = {
    'item': {
        'upon': [
            {'filename': 'part1.pkl', 'md5': '', bk_url: None},
            {'filename': 'part2.pkl', 'md5': '', bk_url: None},
        ],
        'loader': loader_function,
        'preprocess': [datapipe1, datapipe2],
    },
    ...
}

如果数据项 item 依赖本地文件,还需要在 _content 字典中指定键 uponloaderpreprocess 。 但文件需要放置在 data_root \ name \ filename 文件夹。 然后, BaseData 类会自动检查文件的md5校验码。

self._content = {
    'item': {
        'upon': [
            {'filename': 'part1.pkl', 'md5': '', bk_url: None},
            {'filename': 'part2.pkl', 'md5': '', bk_url: None},
        ],
        'loader': loader_function,
        'preprocess': [datapipe1, datapipe2],
    },
    ...
}

如果数据项 item 是一个固定的值,您可以直接在 _content 字典指定 value

self._content = {
    'item': 666666,
    ...
}

图数据集示例

class Cora(BaseData):
    def __init__(self, data_root: Optional[str] = None) -> None:
        super().__init__('cora', data_root)
        self._content = {
            "num_classes": 7,
            "num_vertices": 2708,
            "num_edges": 10858,
            "dim_features": 1433,
            'features': {
                'upon': [{ 'filename': 'features.pkl', 'md5': '05b45e9c38cc95f4fc44b3668cc9ddc9' }],
                'loader': load_from_pickle,
                'preprocess': [to_tensor, partial(norm_ft, ord=1)],
            },
            'edge_list': {
                'upon': [{ 'filename': 'edge_list.pkl', 'md5': 'f488389c1edd0d898ce273fbd27822b3' }],
                'loader': load_from_pickle,
            },
            'labels': {
                'upon': [{ 'filename': 'labels.pkl', 'md5': 'e506014762052c6a36cb583c28bdae1d' }],
                'loader': load_from_pickle,
                'preprocess': [to_long_tensor],
            },
            'train_mask': {
                'upon': [{ 'filename': 'train_mask.pkl', 'md5': 'a11357a40e1f0b5cce728d1a961b8e13' }],
                'loader': load_from_pickle,
                'preprocess': [to_bool_tensor],
            },
            'val_mask': {
                'upon': [{ 'filename': 'val_mask.pkl', 'md5': '355544da566452601bcfa74d30539a71' }],
                'loader': load_from_pickle,
                'preprocess': [to_bool_tensor],
            },
            'test_mask': {
                'upon': [{ 'filename': 'test_mask.pkl', 'md5': 'bbfc87d661560f55f6946f8cb9d602b9' }],
                'loader': load_from_pickle,
                'preprocess': [to_bool_tensor],
            },
        }

超图数据集示例

class Cooking200(BaseData):
    def __init__(self, data_root: Optional[str] = None) -> None:
        super().__init__("cooking_200", data_root)
        self._content = {
            "num_classes": 20,
            "num_vertices": 7403,
            "num_edges": 2755,
            "edge_list": {
                "upon": [
                    {
                        "filename": "edge_list.pkl",
                        "md5": "2cd32e13dd4e33576c43936542975220",
                    }
                ],
                "loader": load_from_pickle,
            },
            "labels": {
                "upon": [
                    {
                        "filename": "labels.pkl",
                        "md5": "f1f3c0399c9c28547088f44e0bfd5c81",
                    }
                ],
                "loader": load_from_pickle,
                "preprocess": [to_long_tensor],
            },
            "train_mask": {
                "upon": [
                    {
                        "filename": "train_mask.pkl",
                        "md5": "66ea36bae024aaaed289e1998fe894bd",
                    }
                ],
                "loader": load_from_pickle,
                "preprocess": [to_bool_tensor],
            },
            "val_mask": {
                "upon": [
                    {
                        "filename": "val_mask.pkl",
                        "md5": "6c0d3d8b752e3955c64788cc65dcd018",
                    }
                ],
                "loader": load_from_pickle,
                "preprocess": [to_bool_tensor],
            },
            "test_mask": {
                "upon": [
                    {
                        "filename": "test_mask.pkl",
                        "md5": "0e1564904551ba493e1f8a09d103461e",
                    }
                ],
                "loader": load_from_pickle,
                "preprocess": [to_bool_tensor],
            },
        }

<用户-物品>二分图示例

class MovieLens1M(BaseData):
    def __init__(self, data_root: Optional[str] = None) -> None:
        super().__init__("movielens_1m", data_root)
        self._content = {
            "num_users": 6022,
            "num_items": 3043,
            "num_interactions": 995154,
            "train_adj_list": {
                "upon": [
                    {
                        "filename": "train.txt",
                        "md5": "db93f671bc5d1b1544ce4c29664f6778",
                    }
                ],
                "loader": partial(load_from_txt, dtype="int", sep=" "),
            },
            "test_adj_list": {
                "upon": [
                    {
                        "filename": "test.txt",
                        "md5": "5e55bcbb6372ad4c6fafe79989e2f956",
                    }
                ],
                "loader": partial(load_from_txt, dtype="int", sep=" "),
            },
        }