OnDiskDataset for Heterogeneous Graph

Open In Colab GitHub

This tutorial shows how to create OnDiskDataset for heterogeneous graph that could be used in GraphBolt framework. The major difference from creating dataset for homogeneous graph is that we need to specify node/edge types for edges, feature data, training/validation/test sets.

By the end of this tutorial, you will be able to

  • organize graph structure data.

  • organize feature data.

  • organize training/validation/test set for specific tasks.

To create an OnDiskDataset object, you need to organize all the data including graph structure, feature data and tasks into a directory. The directory should contain a metadata.yaml file that describes the metadata of the dataset.

Now let’s generate various data step by step and organize them together to instantiate OnDiskDataset finally.

Install DGL package

[1]:
# Install required packages.
import os
import torch
import numpy as np
os.environ['TORCH'] = torch.__version__
os.environ['DGLBACKEND'] = "pytorch"

# Install the CPU version.
device = torch.device("cpu")
!pip install --pre dgl -f https://data.dgl.ai/wheels-test/repo.html

try:
    import dgl
    import dgl.graphbolt as gb
    installed = True
except ImportError as error:
    installed = False
    print(error)
print("DGL installed!" if installed else "DGL not found!")
Looking in links: https://data.dgl.ai/wheels-test/repo.html
Requirement already satisfied: dgl in /home/ubuntu/prod-doc/readthedocs.org/user_builds/dgl/envs/2.0.x/lib/python3.7/site-packages/dgl-2.0.0-py3.7-linux-x86_64.egg (2.0.0)
Requirement already satisfied: numpy>=1.14.0 in /home/ubuntu/prod-doc/readthedocs.org/user_builds/dgl/envs/2.0.x/lib/python3.7/site-packages (from dgl) (1.21.6)
Requirement already satisfied: scipy>=1.1.0 in /home/ubuntu/prod-doc/readthedocs.org/user_builds/dgl/envs/2.0.x/lib/python3.7/site-packages (from dgl) (1.7.3)
Requirement already satisfied: networkx>=2.1 in /home/ubuntu/prod-doc/readthedocs.org/user_builds/dgl/envs/2.0.x/lib/python3.7/site-packages (from dgl) (2.6.3)
Requirement already satisfied: requests>=2.19.0 in /home/ubuntu/prod-doc/readthedocs.org/user_builds/dgl/envs/2.0.x/lib/python3.7/site-packages (from dgl) (2.31.0)
Requirement already satisfied: tqdm in /home/ubuntu/prod-doc/readthedocs.org/user_builds/dgl/envs/2.0.x/lib/python3.7/site-packages (from dgl) (4.66.1)
Requirement already satisfied: psutil>=5.8.0 in /home/ubuntu/prod-doc/readthedocs.org/user_builds/dgl/envs/2.0.x/lib/python3.7/site-packages (from dgl) (5.9.7)
Requirement already satisfied: torchdata>=0.5.0 in /home/ubuntu/prod-doc/readthedocs.org/user_builds/dgl/envs/2.0.x/lib/python3.7/site-packages (from dgl) (0.5.1)
Requirement already satisfied: charset-normalizer<4,>=2 in /home/ubuntu/prod-doc/readthedocs.org/user_builds/dgl/envs/2.0.x/lib/python3.7/site-packages (from requests>=2.19.0->dgl) (3.3.2)
Requirement already satisfied: idna<4,>=2.5 in /home/ubuntu/prod-doc/readthedocs.org/user_builds/dgl/envs/2.0.x/lib/python3.7/site-packages (from requests>=2.19.0->dgl) (3.6)
Requirement already satisfied: urllib3<3,>=1.21.1 in /home/ubuntu/prod-doc/readthedocs.org/user_builds/dgl/envs/2.0.x/lib/python3.7/site-packages (from requests>=2.19.0->dgl) (2.0.7)
Requirement already satisfied: certifi>=2017.4.17 in /home/ubuntu/prod-doc/readthedocs.org/user_builds/dgl/envs/2.0.x/lib/python3.7/site-packages (from requests>=2.19.0->dgl) (2023.11.17)
Requirement already satisfied: portalocker>=2.0.0 in /home/ubuntu/prod-doc/readthedocs.org/user_builds/dgl/envs/2.0.x/lib/python3.7/site-packages (from torchdata>=0.5.0->dgl) (2.7.0)
Requirement already satisfied: torch==1.13.1 in /home/ubuntu/prod-doc/readthedocs.org/user_builds/dgl/envs/2.0.x/lib/python3.7/site-packages (from torchdata>=0.5.0->dgl) (1.13.1)
Requirement already satisfied: typing-extensions in /home/ubuntu/prod-doc/readthedocs.org/user_builds/dgl/envs/2.0.x/lib/python3.7/site-packages (from torch==1.13.1->torchdata>=0.5.0->dgl) (4.7.1)
Requirement already satisfied: nvidia-cuda-runtime-cu11==11.7.99 in /home/ubuntu/prod-doc/readthedocs.org/user_builds/dgl/envs/2.0.x/lib/python3.7/site-packages (from torch==1.13.1->torchdata>=0.5.0->dgl) (11.7.99)
Requirement already satisfied: nvidia-cudnn-cu11==8.5.0.96 in /home/ubuntu/prod-doc/readthedocs.org/user_builds/dgl/envs/2.0.x/lib/python3.7/site-packages (from torch==1.13.1->torchdata>=0.5.0->dgl) (8.5.0.96)
Requirement already satisfied: nvidia-cublas-cu11==11.10.3.66 in /home/ubuntu/prod-doc/readthedocs.org/user_builds/dgl/envs/2.0.x/lib/python3.7/site-packages (from torch==1.13.1->torchdata>=0.5.0->dgl) (11.10.3.66)
Requirement already satisfied: nvidia-cuda-nvrtc-cu11==11.7.99 in /home/ubuntu/prod-doc/readthedocs.org/user_builds/dgl/envs/2.0.x/lib/python3.7/site-packages (from torch==1.13.1->torchdata>=0.5.0->dgl) (11.7.99)
Requirement already satisfied: setuptools in /home/ubuntu/prod-doc/readthedocs.org/user_builds/dgl/envs/2.0.x/lib/python3.7/site-packages (from nvidia-cublas-cu11==11.10.3.66->torch==1.13.1->torchdata>=0.5.0->dgl) (68.0.0)
Requirement already satisfied: wheel in /home/ubuntu/prod-doc/readthedocs.org/user_builds/dgl/envs/2.0.x/lib/python3.7/site-packages (from nvidia-cublas-cu11==11.10.3.66->torch==1.13.1->torchdata>=0.5.0->dgl) (0.42.0)
WARNING:root:The OGB package is out of date. Your version is 1.2.4, while the latest version is 1.3.6.
DGL installed!

Data preparation

In order to demonstrate how to organize various data, let’s create a base directory first.

[2]:
base_dir = './ondisk_dataset_heterograph'
os.makedirs(base_dir, exist_ok=True)
print(f"Created base directory: {base_dir}")
Created base directory: ./ondisk_dataset_heterograph

Generate graph structure data

For heterogeneous graph, we need to save different edge edges(namely node pairs) into separate CSV files.

Note: when saving to file, do not save index and header.

[3]:
import numpy as np
import pandas as pd

# For simplicity, we create a heterogeneous graph with
# 2 node types: `user`, `item`
# 2 edge types: `user:like:item`, `user:follow:user`
# And each node/edge type has the same number of nodes/edges.
num_nodes = 1000
num_edges = 10 * num_nodes

# Edge type: "user:like:item"
like_edges_path = os.path.join(base_dir, "like-edges.csv")
like_edges = np.random.randint(0, num_nodes, size=(num_edges, 2))
print(f"Part of [user:like:item] edges: {like_edges[:5, :]}\n")

df = pd.DataFrame(like_edges)
df.to_csv(like_edges_path, index=False, header=False)
print(f"[user:like:item] edges are saved into {like_edges_path}\n")

# Edge type: "user:follow:user"
follow_edges_path = os.path.join(base_dir, "follow-edges.csv")
follow_edges = np.random.randint(0, num_nodes, size=(num_edges, 2))
print(f"Part of [user:follow:user] edges: {follow_edges[:5, :]}\n")

df = pd.DataFrame(follow_edges)
df.to_csv(follow_edges_path, index=False, header=False)
print(f"[user:follow:user] edges are saved into {follow_edges_path}\n")
Part of [user:like:item] edges: [[467 794]
 [966 870]
 [321 690]
 [ 10 192]
 [345 535]]

[user:like:item] edges are saved into ./ondisk_dataset_heterograph/like-edges.csv

Part of [user:follow:user] edges: [[729 425]
 [184 562]
 [599 304]
 [836 897]
 [ 71 935]]

[user:follow:user] edges are saved into ./ondisk_dataset_heterograph/follow-edges.csv

Generate feature data for graph

For feature data, numpy arrays and torch tensors are supported for now. Let’s generate feature data for each node/edge type.

[4]:
# Generate node[user] feature in numpy array.
node_user_feat_0_path = os.path.join(base_dir, "node-user-feat-0.npy")
node_user_feat_0 = np.random.rand(num_nodes, 5)
print(f"Part of node[user] feature [feat_0]: {node_user_feat_0[:3, :]}")
np.save(node_user_feat_0_path, node_user_feat_0)
print(f"Node[user] feature [feat_0] is saved to {node_user_feat_0_path}\n")

# Generate another node[user] feature in torch tensor
node_user_feat_1_path = os.path.join(base_dir, "node-user-feat-1.pt")
node_user_feat_1 = torch.rand(num_nodes, 5)
print(f"Part of node[user] feature [feat_1]: {node_user_feat_1[:3, :]}")
torch.save(node_user_feat_1, node_user_feat_1_path)
print(f"Node[user] feature [feat_1] is saved to {node_user_feat_1_path}\n")

# Generate node[item] feature in numpy array.
node_item_feat_0_path = os.path.join(base_dir, "node-item-feat-0.npy")
node_item_feat_0 = np.random.rand(num_nodes, 5)
print(f"Part of node[item] feature [feat_0]: {node_item_feat_0[:3, :]}")
np.save(node_item_feat_0_path, node_item_feat_0)
print(f"Node[item] feature [feat_0] is saved to {node_item_feat_0_path}\n")

# Generate another node[item] feature in torch tensor
node_item_feat_1_path = os.path.join(base_dir, "node-item-feat-1.pt")
node_item_feat_1 = torch.rand(num_nodes, 5)
print(f"Part of node[item] feature [feat_1]: {node_item_feat_1[:3, :]}")
torch.save(node_item_feat_1, node_item_feat_1_path)
print(f"Node[item] feature [feat_1] is saved to {node_item_feat_1_path}\n")

# Generate edge[user:like:item] feature in numpy array.
edge_like_feat_0_path = os.path.join(base_dir, "edge-like-feat-0.npy")
edge_like_feat_0 = np.random.rand(num_edges, 5)
print(f"Part of edge[user:like:item] feature [feat_0]: {edge_like_feat_0[:3, :]}")
np.save(edge_like_feat_0_path, edge_like_feat_0)
print(f"Edge[user:like:item] feature [feat_0] is saved to {edge_like_feat_0_path}\n")

# Generate another edge[user:like:item] feature in torch tensor
edge_like_feat_1_path = os.path.join(base_dir, "edge-like-feat-1.pt")
edge_like_feat_1 = torch.rand(num_edges, 5)
print(f"Part of edge[user:like:item] feature [feat_1]: {edge_like_feat_1[:3, :]}")
torch.save(edge_like_feat_1, edge_like_feat_1_path)
print(f"Edge[user:like:item] feature [feat_1] is saved to {edge_like_feat_1_path}\n")

# Generate edge[user:follow:user] feature in numpy array.
edge_follow_feat_0_path = os.path.join(base_dir, "edge-follow-feat-0.npy")
edge_follow_feat_0 = np.random.rand(num_edges, 5)
print(f"Part of edge[user:follow:user] feature [feat_0]: {edge_follow_feat_0[:3, :]}")
np.save(edge_follow_feat_0_path, edge_follow_feat_0)
print(f"Edge[user:follow:user] feature [feat_0] is saved to {edge_follow_feat_0_path}\n")

# Generate another edge[user:follow:user] feature in torch tensor
edge_follow_feat_1_path = os.path.join(base_dir, "edge-follow-feat-1.pt")
edge_follow_feat_1 = torch.rand(num_edges, 5)
print(f"Part of edge[user:follow:user] feature [feat_1]: {edge_follow_feat_1[:3, :]}")
torch.save(edge_follow_feat_1, edge_follow_feat_1_path)
print(f"Edge[user:follow:user] feature [feat_1] is saved to {edge_follow_feat_1_path}\n")
Part of node[user] feature [feat_0]: [[0.41505534 0.91765563 0.42208126 0.98579883 0.59278339]
 [0.51208172 0.34784905 0.99311211 0.58382405 0.68962532]
 [0.77226343 0.96706396 0.96838978 0.44781381 0.83313106]]
Node[user] feature [feat_0] is saved to ./ondisk_dataset_heterograph/node-user-feat-0.npy

Part of node[user] feature [feat_1]: tensor([[0.9050, 0.6177, 0.8911, 0.3230, 0.6870],
        [0.7668, 0.4201, 0.3444, 0.7537, 0.6714],
        [0.5586, 0.6677, 0.0688, 0.9210, 0.6662]])
Node[user] feature [feat_1] is saved to ./ondisk_dataset_heterograph/node-user-feat-1.pt

Part of node[item] feature [feat_0]: [[0.55369073 0.34309915 0.13065727 0.00832949 0.00626264]
 [0.76209787 0.58081435 0.89212929 0.18492317 0.74169953]
 [0.9324283  0.23798798 0.74906285 0.84389583 0.2679008 ]]
Node[item] feature [feat_0] is saved to ./ondisk_dataset_heterograph/node-item-feat-0.npy

Part of node[item] feature [feat_1]: tensor([[0.9627, 0.6042, 0.2281, 0.6706, 0.9775],
        [0.9660, 0.5187, 0.4179, 0.3247, 0.4740],
        [0.2612, 0.5848, 0.4360, 0.4813, 0.2865]])
Node[item] feature [feat_1] is saved to ./ondisk_dataset_heterograph/node-item-feat-1.pt

Part of edge[user:like:item] feature [feat_0]: [[0.90751135 0.28660653 0.81188428 0.86894531 0.65061801]
 [0.4868063  0.81316716 0.93822758 0.37506622 0.95276048]
 [0.63631097 0.83822857 0.83891063 0.85196396 0.93880381]]
Edge[user:like:item] feature [feat_0] is saved to ./ondisk_dataset_heterograph/edge-like-feat-0.npy

Part of edge[user:like:item] feature [feat_1]: tensor([[0.4377, 0.7025, 0.0803, 0.1252, 0.1780],
        [0.4810, 0.6209, 0.4703, 0.3550, 0.1360],
        [0.3867, 0.0159, 0.5700, 0.3808, 0.4333]])
Edge[user:like:item] feature [feat_1] is saved to ./ondisk_dataset_heterograph/edge-like-feat-1.pt

Part of edge[user:follow:user] feature [feat_0]: [[0.73433386 0.1915201  0.81692537 0.75374063 0.05433826]
 [0.01259273 0.42667193 0.01958812 0.32582272 0.78059527]
 [0.97134147 0.78161428 0.92770488 0.16617456 0.19729047]]
Edge[user:follow:user] feature [feat_0] is saved to ./ondisk_dataset_heterograph/edge-follow-feat-0.npy

Part of edge[user:follow:user] feature [feat_1]: tensor([[0.7142, 0.6745, 0.8118, 0.8217, 0.7771],
        [0.7946, 0.7319, 0.4472, 0.0805, 0.3288],
        [0.6704, 0.3664, 0.5825, 0.0015, 0.8030]])
Edge[user:follow:user] feature [feat_1] is saved to ./ondisk_dataset_heterograph/edge-follow-feat-1.pt

Generate tasks

OnDiskDataset supports multiple tasks. For each task, we need to prepare training/validation/test sets respectively. Such sets usually vary among different tasks. In this tutorial, let’s create a Node Classification task and Link Prediction task.

Node Classification Task

For node classification task, we need node IDs and corresponding labels for each training/validation/test set. Like feature data, numpy arrays and torch tensors are supported for these sets.

[5]:
# For illustration, let's generate item sets for each node type.
num_trains = int(num_nodes * 0.6)
num_vals = int(num_nodes * 0.2)
num_tests = num_nodes - num_trains - num_vals

user_ids = np.arange(num_nodes)
np.random.shuffle(user_ids)

item_ids = np.arange(num_nodes)
np.random.shuffle(item_ids)

# Train IDs for user.
nc_train_user_ids_path = os.path.join(base_dir, "nc-train-user-ids.npy")
nc_train_user_ids = user_ids[:num_trains]
print(f"Part of train ids[user] for node classification: {nc_train_user_ids[:3]}")
np.save(nc_train_user_ids_path, nc_train_user_ids)
print(f"NC train ids[user] are saved to {nc_train_user_ids_path}\n")

# Train labels for user.
nc_train_user_labels_path = os.path.join(base_dir, "nc-train-user-labels.pt")
nc_train_user_labels = torch.randint(0, 10, (num_trains,))
print(f"Part of train labels[user] for node classification: {nc_train_user_labels[:3]}")
torch.save(nc_train_user_labels, nc_train_user_labels_path)
print(f"NC train labels[user] are saved to {nc_train_user_labels_path}\n")

# Train IDs for item.
nc_train_item_ids_path = os.path.join(base_dir, "nc-train-item-ids.npy")
nc_train_item_ids = item_ids[:num_trains]
print(f"Part of train ids[item] for node classification: {nc_train_item_ids[:3]}")
np.save(nc_train_item_ids_path, nc_train_item_ids)
print(f"NC train ids[item] are saved to {nc_train_item_ids_path}\n")

# Train labels for item.
nc_train_item_labels_path = os.path.join(base_dir, "nc-train-item-labels.pt")
nc_train_item_labels = torch.randint(0, 10, (num_trains,))
print(f"Part of train labels[item] for node classification: {nc_train_item_labels[:3]}")
torch.save(nc_train_item_labels, nc_train_item_labels_path)
print(f"NC train labels[item] are saved to {nc_train_item_labels_path}\n")

# Val IDs for user.
nc_val_user_ids_path = os.path.join(base_dir, "nc-val-user-ids.npy")
nc_val_user_ids = user_ids[num_trains:num_trains+num_vals]
print(f"Part of val ids[user] for node classification: {nc_val_user_ids[:3]}")
np.save(nc_val_user_ids_path, nc_val_user_ids)
print(f"NC val ids[user] are saved to {nc_val_user_ids_path}\n")

# Val labels for user.
nc_val_user_labels_path = os.path.join(base_dir, "nc-val-user-labels.pt")
nc_val_user_labels = torch.randint(0, 10, (num_vals,))
print(f"Part of val labels[user] for node classification: {nc_val_user_labels[:3]}")
torch.save(nc_val_user_labels, nc_val_user_labels_path)
print(f"NC val labels[user] are saved to {nc_val_user_labels_path}\n")

# Val IDs for item.
nc_val_item_ids_path = os.path.join(base_dir, "nc-val-item-ids.npy")
nc_val_item_ids = item_ids[num_trains:num_trains+num_vals]
print(f"Part of val ids[item] for node classification: {nc_val_item_ids[:3]}")
np.save(nc_val_item_ids_path, nc_val_item_ids)
print(f"NC val ids[item] are saved to {nc_val_item_ids_path}\n")

# Val labels for item.
nc_val_item_labels_path = os.path.join(base_dir, "nc-val-item-labels.pt")
nc_val_item_labels = torch.randint(0, 10, (num_vals,))
print(f"Part of val labels[item] for node classification: {nc_val_item_labels[:3]}")
torch.save(nc_val_item_labels, nc_val_item_labels_path)
print(f"NC val labels[item] are saved to {nc_val_item_labels_path}\n")

# Test IDs for user.
nc_test_user_ids_path = os.path.join(base_dir, "nc-test-user-ids.npy")
nc_test_user_ids = user_ids[-num_tests:]
print(f"Part of test ids[user] for node classification: {nc_test_user_ids[:3]}")
np.save(nc_test_user_ids_path, nc_test_user_ids)
print(f"NC test ids[user] are saved to {nc_test_user_ids_path}\n")

# Test labels for user.
nc_test_user_labels_path = os.path.join(base_dir, "nc-test-user-labels.pt")
nc_test_user_labels = torch.randint(0, 10, (num_tests,))
print(f"Part of test labels[user] for node classification: {nc_test_user_labels[:3]}")
torch.save(nc_test_user_labels, nc_test_user_labels_path)
print(f"NC test labels[user] are saved to {nc_test_user_labels_path}\n")

# Test IDs for item.
nc_test_item_ids_path = os.path.join(base_dir, "nc-test-item-ids.npy")
nc_test_item_ids = item_ids[-num_tests:]
print(f"Part of test ids[item] for node classification: {nc_test_item_ids[:3]}")
np.save(nc_test_item_ids_path, nc_test_item_ids)
print(f"NC test ids[item] are saved to {nc_test_item_ids_path}\n")

# Test labels for item.
nc_test_item_labels_path = os.path.join(base_dir, "nc-test-item-labels.pt")
nc_test_item_labels = torch.randint(0, 10, (num_tests,))
print(f"Part of test labels[item] for node classification: {nc_test_item_labels[:3]}")
torch.save(nc_test_item_labels, nc_test_item_labels_path)
print(f"NC test labels[item] are saved to {nc_test_item_labels_path}\n")
Part of train ids[user] for node classification: [142  64 218]
NC train ids[user] are saved to ./ondisk_dataset_heterograph/nc-train-user-ids.npy

Part of train labels[user] for node classification: tensor([9, 3, 9])
NC train labels[user] are saved to ./ondisk_dataset_heterograph/nc-train-user-labels.pt

Part of train ids[item] for node classification: [341 147 311]
NC train ids[item] are saved to ./ondisk_dataset_heterograph/nc-train-item-ids.npy

Part of train labels[item] for node classification: tensor([8, 2, 9])
NC train labels[item] are saved to ./ondisk_dataset_heterograph/nc-train-item-labels.pt

Part of val ids[user] for node classification: [484  51 943]
NC val ids[user] are saved to ./ondisk_dataset_heterograph/nc-val-user-ids.npy

Part of val labels[user] for node classification: tensor([8, 6, 0])
NC val labels[user] are saved to ./ondisk_dataset_heterograph/nc-val-user-labels.pt

Part of val ids[item] for node classification: [166 844 420]
NC val ids[item] are saved to ./ondisk_dataset_heterograph/nc-val-item-ids.npy

Part of val labels[item] for node classification: tensor([0, 3, 3])
NC val labels[item] are saved to ./ondisk_dataset_heterograph/nc-val-item-labels.pt

Part of test ids[user] for node classification: [ 82 838 152]
NC test ids[user] are saved to ./ondisk_dataset_heterograph/nc-test-user-ids.npy

Part of test labels[user] for node classification: tensor([5, 2, 3])
NC test labels[user] are saved to ./ondisk_dataset_heterograph/nc-test-user-labels.pt

Part of test ids[item] for node classification: [715 385 712]
NC test ids[item] are saved to ./ondisk_dataset_heterograph/nc-test-item-ids.npy

Part of test labels[item] for node classification: tensor([1, 8, 0])
NC test labels[item] are saved to ./ondisk_dataset_heterograph/nc-test-item-labels.pt

Organize Data into YAML File

Now we need to create a metadata.yaml file which contains the paths, dadta types of graph structure, feature data, training/validation/test sets. Please note that all path should be relative to metadata.yaml.

For heterogeneous graph, we need to specify the node/edge type in type fields. For edge type, canonical etype is required which is a string that’s concatenated by source node type, etype, and destination node type together with :.

Notes: - all path should be relative to metadata.yaml. - Below fields are optional and not specified in below example. - in_memory: indicates whether to load dada into memory or mmap. Default is True.

Please refer to YAML specification for more details.

[7]:
yaml_content = f"""
    dataset_name: heterogeneous_graph_nc_lp
    graph:
      nodes:
        - type: user
          num: {num_nodes}
        - type: item
          num: {num_nodes}
      edges:
        - type: "user:like:item"
          format: csv
          path: {os.path.basename(like_edges_path)}
        - type: "user:follow:user"
          format: csv
          path: {os.path.basename(follow_edges_path)}
    feature_data:
      - domain: node
        type: user
        name: feat_0
        format: numpy
        path: {os.path.basename(node_user_feat_0_path)}
      - domain: node
        type: user
        name: feat_1
        format: torch
        path: {os.path.basename(node_user_feat_1_path)}
      - domain: node
        type: item
        name: feat_0
        format: numpy
        path: {os.path.basename(node_item_feat_0_path)}
      - domain: node
        type: item
        name: feat_1
        format: torch
        path: {os.path.basename(node_item_feat_1_path)}
      - domain: edge
        type: "user:like:item"
        name: feat_0
        format: numpy
        path: {os.path.basename(edge_like_feat_0_path)}
      - domain: edge
        type: "user:like:item"
        name: feat_1
        format: torch
        path: {os.path.basename(edge_like_feat_1_path)}
      - domain: edge
        type: "user:follow:user"
        name: feat_0
        format: numpy
        path: {os.path.basename(edge_follow_feat_0_path)}
      - domain: edge
        type: "user:follow:user"
        name: feat_1
        format: torch
        path: {os.path.basename(edge_follow_feat_1_path)}
    tasks:
      - name: node_classification
        num_classes: 10
        train_set:
          - type: user
            data:
              - name: seed_nodes
                format: numpy
                path: {os.path.basename(nc_train_user_ids_path)}
              - name: labels
                format: torch
                path: {os.path.basename(nc_train_user_labels_path)}
          - type: item
            data:
              - name: seed_nodes
                format: numpy
                path: {os.path.basename(nc_train_item_ids_path)}
              - name: labels
                format: torch
                path: {os.path.basename(nc_train_item_labels_path)}
        validation_set:
          - type: user
            data:
              - name: seed_nodes
                format: numpy
                path: {os.path.basename(nc_val_user_ids_path)}
              - name: labels
                format: torch
                path: {os.path.basename(nc_val_user_labels_path)}
          - type: item
            data:
              - name: seed_nodes
                format: numpy
                path: {os.path.basename(nc_val_item_ids_path)}
              - name: labels
                format: torch
                path: {os.path.basename(nc_val_item_labels_path)}
        test_set:
          - type: user
            data:
              - name: seed_nodes
                format: numpy
                path: {os.path.basename(nc_test_user_ids_path)}
              - name: labels
                format: torch
                path: {os.path.basename(nc_test_user_labels_path)}
          - type: item
            data:
              - name: seed_nodes
                format: numpy
                path: {os.path.basename(nc_test_item_ids_path)}
              - name: labels
                format: torch
                path: {os.path.basename(nc_test_item_labels_path)}
      - name: link_prediction
        num_classes: 10
        train_set:
          - type: "user:like:item"
            data:
              - name: node_pairs
                format: numpy
                path: {os.path.basename(lp_train_like_node_pairs_path)}
          - type: "user:follow:user"
            data:
              - name: node_pairs
                format: numpy
                path: {os.path.basename(lp_train_follow_node_pairs_path)}
        validation_set:
          - type: "user:like:item"
            data:
              - name: node_pairs
                format: numpy
                path: {os.path.basename(lp_val_like_node_pairs_path)}
              - name: negative_dsts
                format: torch
                path: {os.path.basename(lp_val_like_neg_dsts_path)}
          - type: "user:follow:user"
            data:
              - name: node_pairs
                format: numpy
                path: {os.path.basename(lp_val_follow_node_pairs_path)}
              - name: negative_dsts
                format: torch
                path: {os.path.basename(lp_val_follow_neg_dsts_path)}
        test_set:
          - type: "user:like:item"
            data:
              - name: node_pairs
                format: numpy
                path: {os.path.basename(lp_test_like_node_pairs_path)}
              - name: negative_dsts
                format: torch
                path: {os.path.basename(lp_test_like_neg_dsts_path)}
          - type: "user:follow:user"
            data:
              - name: node_pairs
                format: numpy
                path: {os.path.basename(lp_test_follow_node_pairs_path)}
              - name: negative_dsts
                format: torch
                path: {os.path.basename(lp_test_follow_neg_dsts_path)}
"""
metadata_path = os.path.join(base_dir, "metadata.yaml")
with open(metadata_path, "w") as f:
  f.write(yaml_content)

Instantiate OnDiskDataset

Now we’re ready to load dataset via dgl.graphbolt.OnDiskDataset. When instantiating, we just pass in the base directory where metadata.yaml file lies.

During first instantiation, GraphBolt preprocesses the raw data such as constructing FusedCSCSamplingGraph from edges. All data including graph, feature data, training/validation/test sets are put into preprocessed directory after preprocessing. Any following dataset loading will skip the preprocess stage.

After preprocessing, load() is required to be called explicitly in order to load graph, feature data and tasks.

[8]:
dataset = gb.OnDiskDataset(base_dir).load()
graph = dataset.graph
print(f"Loaded graph: {graph}\n")

feature = dataset.feature
print(f"Loaded feature store: {feature}\n")

tasks = dataset.tasks
nc_task = tasks[0]
print(f"Loaded node classification task: {nc_task}\n")
lp_task = tasks[1]
print(f"Loaded link prediction task: {lp_task}\n")
Start to preprocess the on-disk dataset.
Finish preprocessing the on-disk dataset.
Loaded graph: FusedCSCSamplingGraph(csc_indptr=tensor([    0,     6,    15,  ..., 19990, 19999, 20000]),
                      indices=tensor([1141, 1138, 1670,  ..., 1783, 1828, 1663]),
                      num_nodes=2000, num_edges={'user:follow:user': 10000, 'user:like:item': 10000}, node_type_offset=tensor([   0, 1000, 2000]), type_per_edge=tensor([1, 1, 1,  ..., 0, 0, 0]), node_type_to_id={'item': 0, 'user': 1}, edge_type_to_id={'user:follow:user': 0, 'user:like:item': 1}, node_attributes={}, edge_attributes={})

Loaded feature store: TorchBasedFeatureStore{(<OnDiskFeatureDataDomain.NODE: 'node'>, 'user', 'feat_0'): TorchBasedFeature(feature=tensor([[0.4151, 0.9177, 0.4221, 0.9858, 0.5928],
                                                        [0.5121, 0.3478, 0.9931, 0.5838, 0.6896],
                                                        [0.7723, 0.9671, 0.9684, 0.4478, 0.8331],
                                                        ...,
                                                        [0.7345, 0.0064, 0.3112, 0.8005, 0.2012],
                                                        [0.8150, 0.8746, 0.1886, 0.5609, 0.2126],
                                                        [0.2490, 0.7400, 0.4889, 0.6889, 0.8506]], dtype=torch.float64),
                                        metadata={},
                      ), (<OnDiskFeatureDataDomain.NODE: 'node'>, 'user', 'feat_1'): TorchBasedFeature(feature=tensor([[0.9050, 0.6177, 0.8911, 0.3230, 0.6870],
                                                        [0.7668, 0.4201, 0.3444, 0.7537, 0.6714],
                                                        [0.5586, 0.6677, 0.0688, 0.9210, 0.6662],
                                                        ...,
                                                        [0.6528, 0.3100, 0.6397, 0.2612, 0.9996],
                                                        [0.1340, 0.9555, 0.6049, 0.0640, 0.1738],
                                                        [0.0172, 0.7919, 0.8340, 0.6239, 0.8840]]),
                                        metadata={},
                      ), (<OnDiskFeatureDataDomain.NODE: 'node'>, 'item', 'feat_0'): TorchBasedFeature(feature=tensor([[0.5537, 0.3431, 0.1307, 0.0083, 0.0063],
                                                        [0.7621, 0.5808, 0.8921, 0.1849, 0.7417],
                                                        [0.9324, 0.2380, 0.7491, 0.8439, 0.2679],
                                                        ...,
                                                        [0.0833, 0.6963, 0.3752, 0.0952, 0.8233],
                                                        [0.7627, 0.4978, 0.5134, 0.6561, 0.0683],
                                                        [0.5852, 0.1084, 0.2321, 0.0113, 0.0997]], dtype=torch.float64),
                                        metadata={},
                      ), (<OnDiskFeatureDataDomain.NODE: 'node'>, 'item', 'feat_1'): TorchBasedFeature(feature=tensor([[0.9627, 0.6042, 0.2281, 0.6706, 0.9775],
                                                        [0.9660, 0.5187, 0.4179, 0.3247, 0.4740],
                                                        [0.2612, 0.5848, 0.4360, 0.4813, 0.2865],
                                                        ...,
                                                        [0.2204, 0.7627, 0.9338, 0.1205, 0.0078],
                                                        [0.9253, 0.8664, 0.0033, 0.2549, 0.9328],
                                                        [0.6851, 0.3841, 0.6685, 0.7249, 0.5756]]),
                                        metadata={},
                      ), (<OnDiskFeatureDataDomain.EDGE: 'edge'>, 'user:like:item', 'feat_0'): TorchBasedFeature(feature=tensor([[0.9075, 0.2866, 0.8119, 0.8689, 0.6506],
                                                        [0.4868, 0.8132, 0.9382, 0.3751, 0.9528],
                                                        [0.6363, 0.8382, 0.8389, 0.8520, 0.9388],
                                                        ...,
                                                        [0.0716, 0.6736, 0.1494, 0.5584, 0.9322],
                                                        [0.5544, 0.8116, 0.5174, 0.4140, 0.1721],
                                                        [0.2330, 0.5700, 0.5069, 0.7953, 0.9318]], dtype=torch.float64),
                                        metadata={},
                      ), (<OnDiskFeatureDataDomain.EDGE: 'edge'>, 'user:like:item', 'feat_1'): TorchBasedFeature(feature=tensor([[0.4377, 0.7025, 0.0803, 0.1252, 0.1780],
                                                        [0.4810, 0.6209, 0.4703, 0.3550, 0.1360],
                                                        [0.3867, 0.0159, 0.5700, 0.3808, 0.4333],
                                                        ...,
                                                        [0.7102, 0.9970, 0.2187, 0.4286, 0.8679],
                                                        [0.1863, 0.2363, 0.8688, 0.1947, 0.5732],
                                                        [0.7071, 0.7855, 0.2220, 0.4651, 0.8986]]),
                                        metadata={},
                      ), (<OnDiskFeatureDataDomain.EDGE: 'edge'>, 'user:follow:user', 'feat_0'): TorchBasedFeature(feature=tensor([[0.7343, 0.1915, 0.8169, 0.7537, 0.0543],
                                                        [0.0126, 0.4267, 0.0196, 0.3258, 0.7806],
                                                        [0.9713, 0.7816, 0.9277, 0.1662, 0.1973],
                                                        ...,
                                                        [0.9470, 0.1084, 0.4355, 0.1903, 0.6707],
                                                        [0.1120, 0.7896, 0.7724, 0.8638, 0.7482],
                                                        [0.4387, 0.6119, 0.3333, 0.6841, 0.8543]], dtype=torch.float64),
                                        metadata={},
                      ), (<OnDiskFeatureDataDomain.EDGE: 'edge'>, 'user:follow:user', 'feat_1'): TorchBasedFeature(feature=tensor([[0.7142, 0.6745, 0.8118, 0.8217, 0.7771],
                                                        [0.7946, 0.7319, 0.4472, 0.0805, 0.3288],
                                                        [0.6704, 0.3664, 0.5825, 0.0015, 0.8030],
                                                        ...,
                                                        [0.1286, 0.1227, 0.2860, 0.8042, 0.7731],
                                                        [0.5312, 0.8282, 0.9610, 0.1379, 0.8229],
                                                        [0.2149, 0.7657, 0.6729, 0.7860, 0.7915]]),
                                        metadata={},
                      )}

Loaded node classification task: OnDiskTask(validation_set=ItemSetDict(items={'user': ItemSet(items=(tensor([484,  51, 943, 492, 446, 391, 837, 266, 322,  46, 242, 563, 345,  39,
                                                                  399, 589, 316, 786, 199,  95,  87, 353, 996, 303, 814, 470, 716, 202,
                                                                  629, 251, 299, 561, 863, 670, 229, 780,   3, 459, 593, 582, 802,  33,
                                                                  488, 809, 272,  98, 194, 177, 915, 486, 305, 570, 313, 984, 247, 231,
                                                                  792, 213, 966, 569, 325, 925,  23, 968, 687, 290, 674, 982, 795, 974,
                                                                  888, 740, 209, 135, 828, 521, 264, 101, 728, 689, 622, 628, 192, 475,
                                                                   20, 673, 774, 626, 370, 864, 318,  27, 817, 816,  91, 112, 553,  12,
                                                                  128, 858, 328, 900, 898, 600,  76, 122, 718, 654,  63, 108,  13, 986,
                                                                  512, 228, 407, 425, 204, 682, 542, 419, 103, 883, 937, 341, 524, 889,
                                                                  292, 923, 288, 655, 148, 693, 363, 972, 560, 785, 979, 638, 410, 861,
                                                                  711, 388,  92, 260,  37, 547, 818, 315, 819, 604, 478, 790, 154, 383,
                                                                  116, 812, 764, 346, 115, 665, 201, 306, 585, 777, 323, 270, 534, 702,
                                                                  160, 602, 921, 309, 829, 732, 319, 852, 171, 376, 339, 380,  48, 612,
                                                                  514, 813, 710, 279, 143, 304,  10, 942, 453, 878, 659, 725, 147, 704,
                                                                  294, 127, 991, 253]), tensor([8, 6, 0, 1, 4, 2, 1, 2, 4, 8, 2, 0, 5, 2, 3, 4, 8, 9, 1, 6, 7, 3, 6, 8,
                                                                  7, 9, 4, 9, 4, 5, 5, 2, 5, 0, 2, 6, 7, 0, 6, 0, 0, 8, 5, 6, 6, 9, 5, 9,
                                                                  0, 6, 0, 0, 6, 0, 2, 7, 1, 2, 4, 3, 4, 5, 6, 4, 0, 8, 7, 7, 8, 3, 4, 3,
                                                                  6, 3, 2, 9, 5, 2, 1, 6, 5, 3, 6, 4, 2, 6, 1, 7, 0, 9, 9, 4, 0, 6, 8, 5,
                                                                  0, 0, 9, 5, 0, 0, 0, 1, 5, 9, 3, 3, 1, 1, 1, 9, 8, 5, 6, 6, 9, 8, 5, 5,
                                                                  9, 4, 7, 6, 2, 1, 1, 7, 8, 1, 3, 5, 1, 3, 7, 3, 8, 6, 5, 4, 0, 3, 7, 0,
                                                                  7, 0, 4, 1, 5, 9, 7, 1, 6, 1, 3, 8, 8, 2, 9, 2, 7, 7, 3, 5, 3, 9, 7, 7,
                                                                  4, 0, 4, 3, 6, 9, 1, 8, 0, 5, 1, 3, 5, 3, 7, 2, 0, 1, 5, 0, 3, 5, 3, 2,
                                                                  7, 0, 9, 4, 1, 0, 0, 8])),
                                                    names=('seed_nodes', 'labels'),
                                            ), 'item': ItemSet(items=(tensor([166, 844, 420, 882, 676, 889, 751, 200, 668, 866, 401, 461, 114, 631,
                                                                  634, 471, 734,   2, 219, 392, 768,  47, 973, 704, 430, 780, 927, 609,
                                                                  918, 951, 167, 134, 269, 724, 262, 157, 154, 813, 412, 850, 459, 673,
                                                                  202, 585, 527, 615, 876, 611, 797, 874, 776, 541, 660, 958,  59, 550,
                                                                  730, 754, 531, 180,  17, 106, 396, 925, 800, 172, 940, 126, 917, 807,
                                                                  566, 910, 510, 759, 260, 605, 819,  24, 295, 377, 138, 945, 419, 977,
                                                                   45, 583, 725, 115, 403, 211, 779, 500, 743, 129, 388, 464, 290, 653,
                                                                  410, 987, 929, 489, 588, 572, 909, 425, 670, 495, 183, 842, 644, 953,
                                                                  462, 203, 739, 845, 367,  48, 692, 648, 494, 277, 870, 320, 125, 825,
                                                                  593, 643, 968, 997, 702, 690, 292,  43, 373, 536, 772, 176, 859, 160,
                                                                  137, 267, 481, 254, 881, 628, 646, 284, 543, 879, 835, 525, 777, 383,
                                                                  214, 694, 669, 360, 746, 533, 805, 758, 467, 529, 865,  22, 545,  80,
                                                                  895, 905, 102, 567, 240, 318,  19, 382, 118, 711, 547, 120, 431, 941,
                                                                   16, 266, 189, 877, 511, 259, 370, 998, 328, 301, 206, 652, 407, 199,
                                                                  787, 822, 185, 986]), tensor([0, 3, 3, 6, 4, 6, 7, 0, 4, 0, 8, 4, 4, 4, 3, 2, 5, 5, 2, 7, 3, 6, 7, 4,
                                                                  2, 6, 6, 9, 2, 4, 4, 5, 9, 9, 9, 7, 2, 2, 2, 3, 8, 3, 6, 7, 0, 4, 1, 4,
                                                                  6, 0, 8, 5, 7, 0, 7, 3, 3, 1, 8, 2, 8, 4, 4, 6, 6, 8, 9, 5, 1, 9, 5, 9,
                                                                  5, 0, 5, 8, 3, 8, 2, 5, 5, 6, 7, 4, 4, 0, 1, 2, 6, 9, 9, 6, 6, 5, 7, 6,
                                                                  6, 3, 1, 2, 0, 5, 6, 8, 0, 2, 4, 9, 9, 8, 0, 0, 3, 0, 8, 2, 1, 1, 5, 2,
                                                                  9, 1, 4, 9, 4, 8, 3, 4, 7, 8, 0, 6, 5, 6, 7, 8, 5, 0, 4, 2, 6, 3, 1, 8,
                                                                  7, 6, 6, 2, 1, 9, 9, 8, 2, 4, 2, 8, 2, 5, 5, 5, 2, 7, 5, 0, 4, 5, 4, 3,
                                                                  9, 1, 8, 2, 3, 0, 6, 1, 0, 9, 1, 0, 4, 5, 1, 4, 0, 3, 0, 6, 3, 3, 3, 1,
                                                                  7, 9, 8, 1, 1, 3, 2, 4])),
                                                    names=('seed_nodes', 'labels'),
                                            )},
                                      names=('seed_nodes', 'labels'),
                          ),
           train_set=ItemSetDict(items={'user': ItemSet(items=(tensor([142,  64, 218, 713,  14, 158, 712, 107, 461, 726, 259,  67, 360, 415,
                                                               1, 832,  61,  78, 268, 439, 504, 495, 412,  30, 396,  59, 245, 874,
                                                             367, 471, 558, 603, 690, 516,  21, 694, 789, 126, 106, 808, 914, 250,
                                                             244, 911, 623, 770, 373, 406, 448, 277, 667, 754, 730, 183, 395, 430,
                                                             867,  40, 527, 321, 886, 422, 615, 994,  73, 772, 169,  45, 416, 684,
                                                             205, 327, 699, 344, 720, 384, 529, 156, 296, 579,  56, 977, 757, 366,
                                                             203, 887, 162, 752, 722, 402, 382, 379, 877, 805, 320,   8, 845, 643,
                                                             100, 608,  97,   0, 153, 136, 274, 971, 872, 184, 449, 464, 263, 865,
                                                             354, 653, 480, 501, 733, 840, 998, 276, 624, 409,  94, 144, 335, 890,
                                                             946, 333, 487, 458, 922, 614, 208,  19, 578, 854, 763, 357, 134, 417,
                                                             188, 149, 503, 451, 584, 823, 511, 217, 129, 281, 378, 869, 800, 807,
                                                             616, 651, 876, 799,  31, 240, 920, 567, 368, 530, 884, 737, 749, 176,
                                                             510, 678,  44, 803, 494, 189, 168, 496, 660, 182, 308, 700, 598, 892,
                                                             468, 868, 873, 491, 748, 361, 781, 559,  36, 969, 672,  24, 599, 216,
                                                             776, 113, 844, 540, 437, 236, 934, 771,  77, 933, 721, 778, 948, 181,
                                                               4, 411, 528, 706, 525, 172, 352, 631, 452, 902, 293, 692, 955, 139,
                                                             875, 348, 909, 879, 500,  89, 723, 862, 350, 981, 810, 543, 314, 788,
                                                             913, 397, 548, 469, 965, 225, 498, 645, 170, 523, 155, 583, 811,  81,
                                                              57, 847, 362, 574, 927, 489, 773,  25, 285,  58, 759, 300, 956, 715,
                                                             326, 853, 120, 926, 756, 621, 262, 848, 630, 347, 509, 904,  60,  22,
                                                             233,  93, 104, 114, 686, 330, 200, 275, 499, 282, 138, 444, 930, 130,
                                                             632, 929,  41, 132, 445, 531, 903, 140, 545, 117, 210, 894, 466, 949,
                                                             987, 271, 669, 661, 843, 198, 254, 658, 151, 533, 719, 551, 440, 432,
                                                             950, 846, 708, 685, 709, 337, 223, 586, 856, 485, 544, 539, 230, 555,
                                                             993, 607, 650, 855, 656, 761, 758, 131, 358, 518, 537, 195, 408,  86,
                                                             696, 783, 109, 145, 850, 312,   7, 592, 359, 226, 310, 457, 473, 857,
                                                             404,  55, 317, 442,  49, 123,  26, 634, 297, 400, 746, 164, 398, 798,
                                                             797, 688, 871, 178,  34, 698, 738, 978, 919, 841, 995, 447, 392, 649,
                                                             588, 833, 206, 796, 827,   5, 606, 729, 167, 249, 125, 552, 133, 962,
                                                               9, 110, 331, 349, 610, 265, 597,  62, 804, 907, 175, 745, 441, 677,
                                                             662, 839, 664, 782,  96, 587, 734, 493, 765, 532,  85, 124,  11, 535,
                                                             794, 952, 431, 369, 596, 214, 355, 859, 885, 403, 975, 174, 291, 751,
                                                             932, 340, 675, 568, 513, 954, 273, 750, 329, 731, 261, 479, 787, 426,
                                                             221,  42, 613, 165,  83, 671, 866, 897, 502, 284, 637, 196, 679, 976,
                                                             936, 791,  66, 970, 508, 769, 219, 727,  17, 575, 880, 928, 550, 520,
                                                             917, 906, 572, 617, 243, 703, 640, 742, 193, 102, 918, 157, 541, 625,
                                                             215, 105, 985, 739, 784, 220, 338, 820, 536, 609, 257, 554, 187, 434,
                                                             483, 428,  15, 960, 372,  38, 775, 581, 641, 356, 324,  84, 424, 438,
                                                             590, 701, 161, 577, 747, 639, 591, 375, 938, 908, 652, 185, 983, 232,
                                                             269, 111, 256, 980, 538, 990, 141, 717, 648, 423, 834, 905, 605, 989,
                                                             394, 433, 657, 342, 951, 476, 642, 467, 371, 150, 735, 647,  68, 237,
                                                             390, 278, 389, 564, 695, 860, 627, 767, 336, 806, 477, 443, 822, 248,
                                                             472, 435, 743, 381, 801, 992, 705, 332, 825, 222, 414, 947]), tensor([9, 3, 9, 7, 8, 8, 8, 6, 3, 4, 1, 8, 0, 5, 3, 2, 1, 1, 7, 1, 0, 0, 8, 1,
                                                             6, 9, 4, 0, 2, 8, 6, 2, 9, 2, 5, 4, 2, 0, 8, 8, 4, 0, 3, 8, 8, 0, 2, 9,
                                                             7, 2, 9, 7, 1, 2, 7, 2, 7, 0, 6, 8, 6, 7, 6, 6, 4, 2, 4, 9, 3, 6, 1, 1,
                                                             2, 2, 0, 2, 5, 3, 7, 4, 1, 6, 8, 8, 2, 0, 7, 4, 6, 6, 6, 8, 4, 1, 1, 4,
                                                             2, 3, 0, 4, 8, 2, 3, 6, 6, 8, 9, 1, 5, 9, 9, 3, 8, 0, 0, 8, 5, 6, 2, 4,
                                                             3, 5, 9, 4, 0, 1, 7, 7, 8, 5, 4, 1, 9, 0, 6, 3, 3, 8, 6, 4, 8, 4, 4, 8,
                                                             8, 6, 4, 9, 2, 1, 5, 3, 5, 5, 6, 6, 5, 0, 5, 1, 9, 2, 4, 8, 9, 5, 3, 8,
                                                             3, 2, 2, 0, 9, 2, 9, 3, 4, 8, 2, 3, 2, 5, 4, 9, 2, 7, 3, 0, 2, 8, 7, 6,
                                                             2, 3, 3, 9, 7, 9, 4, 3, 4, 1, 2, 2, 2, 9, 9, 5, 6, 6, 6, 4, 8, 1, 9, 3,
                                                             2, 5, 7, 5, 4, 1, 1, 1, 8, 3, 7, 5, 8, 7, 4, 4, 8, 1, 4, 3, 4, 8, 5, 5,
                                                             0, 4, 0, 4, 6, 4, 2, 4, 9, 3, 9, 7, 6, 5, 8, 2, 0, 2, 0, 1, 6, 2, 6, 9,
                                                             1, 5, 1, 5, 9, 8, 1, 3, 5, 4, 7, 8, 3, 0, 1, 8, 1, 3, 9, 0, 2, 5, 6, 6,
                                                             3, 4, 8, 1, 6, 1, 5, 5, 9, 1, 7, 5, 9, 0, 9, 9, 7, 3, 1, 6, 9, 8, 3, 7,
                                                             2, 3, 4, 7, 5, 0, 5, 0, 3, 5, 6, 0, 7, 6, 2, 1, 0, 2, 6, 2, 5, 3, 0, 5,
                                                             0, 8, 0, 3, 9, 9, 0, 0, 9, 9, 3, 9, 4, 3, 9, 8, 4, 3, 9, 4, 5, 1, 9, 2,
                                                             9, 7, 0, 3, 9, 1, 7, 4, 2, 9, 2, 6, 0, 9, 8, 7, 2, 6, 2, 4, 0, 7, 9, 0,
                                                             2, 1, 9, 0, 8, 7, 4, 1, 0, 9, 3, 2, 1, 6, 4, 9, 4, 4, 1, 8, 5, 9, 7, 8,
                                                             2, 3, 3, 4, 2, 2, 9, 1, 6, 5, 0, 6, 3, 6, 0, 6, 9, 7, 8, 0, 4, 2, 5, 2,
                                                             7, 8, 4, 0, 6, 8, 2, 2, 7, 9, 3, 6, 6, 5, 8, 0, 8, 9, 5, 5, 4, 1, 8, 1,
                                                             5, 5, 1, 5, 5, 5, 9, 4, 8, 4, 9, 6, 8, 5, 0, 7, 8, 7, 3, 2, 3, 6, 0, 7,
                                                             5, 4, 1, 8, 9, 5, 0, 6, 8, 5, 8, 6, 3, 8, 5, 3, 2, 1, 7, 3, 3, 7, 7, 5,
                                                             3, 3, 9, 4, 8, 9, 7, 0, 4, 2, 7, 9, 8, 9, 1, 9, 9, 7, 3, 0, 0, 5, 1, 6,
                                                             5, 1, 6, 8, 2, 6, 2, 4, 4, 7, 6, 3, 7, 8, 5, 1, 0, 3, 8, 1, 0, 4, 9, 6,
                                                             4, 4, 8, 3, 6, 0, 0, 4, 1, 9, 6, 7, 8, 7, 2, 7, 4, 2, 8, 8, 5, 1, 8, 9,
                                                             1, 5, 2, 1, 9, 2, 0, 2, 2, 2, 0, 7, 1, 0, 7, 4, 6, 5, 1, 5, 3, 0, 1, 7])),
                                               names=('seed_nodes', 'labels'),
                                       ), 'item': ItemSet(items=(tensor([341, 147, 311, 681, 749, 897, 163,  54, 394, 654, 847, 618, 592, 714,
                                                             524, 750, 744, 791, 168, 488,   6, 967, 706,  71, 162, 839, 241, 235,
                                                             962, 305, 156, 748,  98, 399, 741, 378, 626, 995, 264, 232, 384, 811,
                                                             614, 532, 186, 579, 963, 479, 455, 352,  99,  73,  13, 620, 342, 405,
                                                             651, 736, 336,  30, 194,  29, 484, 285, 473, 658, 204, 192, 764, 935,
                                                             400, 944, 638, 530,  36, 639, 270, 453,  76, 287, 688,  51, 282, 505,
                                                             629, 993, 289, 353, 753, 470, 981, 728, 327, 888, 630, 152, 656, 610,
                                                             246,  60, 956, 562, 445, 990, 298, 699, 696, 568, 523, 745,  27, 272,
                                                             486, 563, 450, 560,  55, 911, 752, 829, 124, 778, 806, 344, 504, 411,
                                                             709, 476, 942, 992, 858, 923, 159, 818, 767,  40, 581, 549,   7,  23,
                                                             698, 677, 920, 912, 799,  81, 539, 943, 578,  94, 133, 843, 976, 540,
                                                             274, 130, 222, 788, 238, 316, 416, 849, 439, 109, 622, 809, 308, 798,
                                                             679, 674, 693, 208, 210, 949,  12, 848, 684, 950, 979,  38, 132,  97,
                                                             906, 559, 366, 196, 515, 421, 434, 249, 742, 600, 207, 454, 720, 268,
                                                             884, 689, 801, 775, 703, 356, 363, 989, 700, 306, 302, 789, 926, 424,
                                                              37, 469, 346, 731, 663,  39, 838, 580, 376, 501,  96, 555,  89, 179,
                                                             671, 553, 276, 851, 440, 117, 326, 902, 919, 188, 598, 710, 355, 348,
                                                             793, 582, 230, 493, 330, 331, 546, 397, 324,  90, 804, 423,  56,  92,
                                                             617, 317, 855, 833, 599,  49, 766,  20,   8, 841, 701, 472, 830, 664,
                                                             840, 408, 946, 686, 517, 265, 503, 465, 242, 228, 719, 557, 957, 142,
                                                               0, 427,  50, 406, 398, 640, 177, 786,  65, 491, 616, 347, 442, 633,
                                                             832, 457, 512, 237, 460,  11,  85, 304, 103, 747, 250, 862, 361, 900,
                                                             650,  88, 448, 784, 339, 122, 140, 727, 231, 275, 164, 417, 475,  67,
                                                             901, 364, 762, 127, 223, 548, 329, 496, 939, 964, 960, 896,  41, 528,
                                                             755, 456, 823, 868, 256, 519, 961, 538, 587, 854,  15, 518, 451, 253,
                                                             135,  86, 175, 597, 375, 354, 381, 174, 513, 783, 623,  53, 659, 955,
                                                             521, 395, 921, 999, 184, 283, 299, 359, 796, 173, 827, 595,  83, 891,
                                                             641, 637, 965, 984, 722, 498,  70, 321, 100, 983, 128, 368, 307, 247,
                                                             971, 502, 826, 931, 322, 948,   9, 309, 860, 499, 224, 569, 717, 426,
                                                             867, 487,  18, 141, 158, 514, 480, 155, 520, 111,  34,  77,  95, 551,
                                                             432, 729, 351, 836, 769, 151, 821,  63, 380, 286, 245, 974, 215, 657,
                                                             216, 740,  68, 437, 994, 212, 165, 255, 584, 718,  93,  69, 802, 507,
                                                             871, 571, 107, 608,   5, 606, 435, 449, 131, 234, 209, 969, 251, 613,
                                                             225, 636, 988, 602, 604, 667, 782, 319, 313, 846, 447, 413, 325, 182,
                                                             273, 586, 303, 338, 191, 178, 812, 340, 721, 716, 705, 278, 482, 108,
                                                             252, 350, 770, 315, 737, 444, 386, 732,  52, 685, 490, 815, 468, 116,
                                                             820, 389,  57, 756, 291, 526, 181, 771,  10, 436, 803, 161, 574, 975,
                                                             294, 773, 878, 873,  58, 852, 869, 193, 908, 934, 894, 757, 790, 343,
                                                             922, 726, 236, 229, 795, 978, 221, 774, 244, 554, 257, 576, 369, 577,
                                                             314, 890, 647,  75, 856, 349, 516, 535, 390, 239, 522, 624, 952, 625,
                                                             857, 477, 880, 959, 853, 632, 443,  72, 201, 621, 136, 556, 357, 893,
                                                              79, 261, 697, 932,  25, 433,  32, 506, 603, 113, 429, 661, 112, 886,
                                                             914, 954, 296, 110, 170,   4, 810, 334, 458, 371,  66, 933]), tensor([8, 2, 9, 3, 7, 4, 9, 9, 7, 7, 6, 1, 0, 8, 5, 0, 7, 4, 9, 3, 1, 0, 6, 3,
                                                             6, 2, 5, 6, 8, 6, 4, 3, 9, 6, 4, 3, 9, 1, 3, 3, 3, 8, 5, 2, 5, 2, 6, 0,
                                                             7, 0, 7, 8, 5, 7, 3, 6, 6, 3, 7, 9, 5, 5, 8, 3, 0, 1, 0, 3, 1, 6, 6, 6,
                                                             2, 7, 2, 0, 4, 1, 3, 1, 6, 7, 5, 0, 4, 4, 3, 1, 2, 0, 8, 0, 1, 9, 6, 4,
                                                             5, 5, 5, 2, 3, 6, 5, 3, 8, 9, 5, 9, 9, 2, 6, 5, 2, 5, 7, 7, 7, 1, 3, 4,
                                                             7, 5, 6, 4, 9, 0, 6, 5, 9, 0, 2, 8, 7, 8, 3, 2, 2, 2, 8, 8, 0, 5, 5, 2,
                                                             0, 2, 8, 7, 9, 7, 8, 5, 1, 0, 0, 2, 9, 2, 2, 6, 6, 1, 6, 4, 0, 6, 0, 8,
                                                             1, 7, 4, 2, 6, 1, 0, 6, 4, 4, 1, 6, 8, 8, 9, 0, 9, 6, 4, 7, 8, 7, 7, 0,
                                                             5, 3, 8, 2, 9, 1, 9, 0, 7, 9, 1, 8, 7, 5, 9, 7, 8, 3, 0, 8, 7, 3, 6, 6,
                                                             1, 6, 9, 8, 5, 5, 2, 3, 0, 6, 2, 1, 6, 8, 6, 0, 9, 0, 6, 3, 8, 1, 5, 1,
                                                             5, 0, 2, 6, 1, 2, 0, 3, 1, 0, 5, 3, 1, 1, 2, 8, 1, 1, 5, 4, 3, 7, 6, 4,
                                                             2, 4, 2, 6, 0, 5, 1, 0, 1, 3, 2, 1, 8, 2, 1, 0, 4, 7, 0, 2, 4, 4, 3, 5,
                                                             0, 1, 9, 2, 3, 8, 3, 6, 8, 1, 7, 3, 5, 9, 6, 8, 8, 0, 7, 2, 2, 7, 9, 2,
                                                             0, 9, 6, 6, 2, 4, 5, 7, 1, 3, 7, 5, 8, 1, 2, 6, 4, 9, 5, 0, 0, 4, 4, 3,
                                                             0, 2, 0, 4, 9, 6, 6, 8, 7, 9, 9, 7, 4, 6, 1, 5, 5, 4, 2, 3, 1, 1, 3, 2,
                                                             9, 1, 2, 4, 1, 3, 0, 3, 6, 3, 9, 0, 6, 0, 6, 9, 8, 1, 0, 0, 5, 9, 7, 1,
                                                             3, 3, 3, 7, 6, 6, 2, 2, 7, 0, 4, 4, 9, 5, 0, 5, 3, 9, 3, 3, 3, 1, 3, 6,
                                                             3, 6, 8, 5, 7, 7, 9, 1, 4, 8, 3, 1, 4, 3, 2, 9, 9, 6, 2, 7, 7, 6, 0, 4,
                                                             0, 0, 6, 4, 0, 5, 3, 1, 7, 8, 4, 2, 3, 6, 7, 8, 8, 0, 3, 4, 9, 6, 8, 3,
                                                             8, 0, 3, 2, 3, 4, 8, 9, 2, 3, 8, 9, 8, 4, 4, 6, 1, 0, 1, 5, 0, 3, 6, 9,
                                                             3, 3, 4, 8, 4, 6, 8, 6, 8, 8, 7, 4, 7, 0, 9, 6, 5, 4, 7, 5, 6, 7, 9, 8,
                                                             5, 3, 5, 2, 5, 8, 4, 7, 9, 0, 5, 2, 8, 9, 4, 6, 5, 3, 5, 4, 6, 8, 6, 9,
                                                             2, 2, 3, 4, 3, 9, 0, 5, 8, 2, 2, 6, 7, 2, 0, 0, 1, 6, 3, 8, 6, 7, 1, 6,
                                                             1, 4, 8, 7, 7, 9, 8, 9, 7, 8, 4, 4, 4, 4, 7, 5, 9, 1, 4, 1, 3, 8, 8, 9,
                                                             5, 3, 3, 1, 4, 3, 0, 6, 9, 6, 8, 3, 0, 2, 6, 6, 0, 4, 6, 0, 5, 3, 1, 5])),
                                               names=('seed_nodes', 'labels'),
                                       )},
                                 names=('seed_nodes', 'labels'),
                     ),
           test_set=ItemSetDict(items={'user': ItemSet(items=(tensor([ 82, 838, 152, 481, 241,  74, 999, 549, 393, 967, 815, 668, 163, 899,
                                                            893, 465, 429, 418, 334, 944, 891,  72, 988, 741, 159, 580, 420, 374,
                                                            646, 736, 301, 768, 252, 940, 766, 224, 211, 882,  35, 611, 959, 173,
                                                             90, 912, 881, 405, 298, 386, 680, 289, 835, 507, 691, 311, 924, 364,
                                                            935, 565, 601, 207,  69, 910,  52, 755, 849, 619, 377, 744, 246, 497,
                                                            707, 961, 896, 760, 573, 566, 456, 302, 546, 212, 179,  28, 836,  32,
                                                            239, 385,  29, 963, 421, 286, 191, 190, 287, 234, 556, 762, 941, 676,
                                                            635,  18, 562, 824, 119, 118,  47, 482, 517, 945, 842, 895, 576, 958,
                                                            474, 681, 594, 526, 283, 280, 343, 450, 351, 295, 997,  71,  65, 633,
                                                            427,  79, 916, 235,  88,  99, 522, 714, 931, 463, 830, 620, 146, 227,
                                                            436, 258, 618, 557, 851, 636,   2, 697, 753,  54, 505, 267,  70, 460,
                                                            663,  50,  53, 462, 964,   6, 821, 186,  80, 953, 901, 166, 413, 490,
                                                            255, 401, 939, 307, 506, 779, 365, 793, 180, 973,  75, 870, 121, 455,
                                                            387, 724, 826, 454,  16, 519, 644, 137, 238, 571, 515,  43, 197, 831,
                                                            957, 595, 666, 683]), tensor([5, 2, 3, 3, 0, 4, 7, 3, 5, 1, 7, 1, 2, 9, 4, 1, 2, 8, 6, 8, 7, 6, 8, 7,
                                                            7, 2, 0, 7, 4, 7, 4, 6, 7, 2, 3, 3, 2, 3, 9, 9, 1, 3, 4, 0, 3, 9, 0, 8,
                                                            5, 4, 8, 3, 7, 9, 9, 9, 9, 1, 4, 2, 1, 1, 3, 2, 0, 6, 6, 9, 1, 1, 1, 9,
                                                            7, 6, 4, 8, 3, 9, 7, 1, 4, 9, 5, 7, 4, 8, 6, 8, 0, 9, 8, 5, 0, 3, 9, 3,
                                                            7, 7, 3, 4, 1, 8, 5, 3, 4, 8, 3, 1, 1, 9, 3, 5, 3, 2, 5, 4, 5, 6, 6, 2,
                                                            0, 4, 7, 2, 2, 6, 7, 4, 7, 0, 2, 0, 2, 4, 8, 1, 1, 5, 7, 7, 5, 2, 8, 5,
                                                            8, 1, 2, 2, 5, 6, 9, 4, 6, 1, 6, 7, 9, 5, 8, 2, 0, 3, 8, 5, 9, 2, 2, 8,
                                                            9, 5, 1, 1, 5, 5, 6, 7, 1, 2, 5, 4, 4, 3, 7, 1, 0, 2, 5, 4, 7, 8, 4, 6,
                                                            1, 8, 9, 5, 9, 2, 8, 5])),
                                              names=('seed_nodes', 'labels'),
                                      ), 'item': ItemSet(items=(tensor([715, 385, 712, 834, 708, 150, 422, 904, 492, 707,  64, 497, 590, 197,
                                                            263, 612, 544, 218, 474, 561, 139, 119, 402,   3, 248, 243, 337, 534,
                                                            903, 372, 379, 875, 665, 635, 297, 930, 936, 220,  91, 723, 691, 765,
                                                            683, 310, 226, 924, 391, 761, 415, 463, 233, 409,  35, 695,  46, 121,
                                                            915, 279, 478, 814,  78, 187, 645, 672, 824, 374, 763, 816, 205,  21,
                                                            483,  14, 101,  61, 738, 713, 332, 414, 596, 570, 928, 760, 980, 887,
                                                            552,  62, 271, 938,  28, 601,  33, 575, 558, 362,  87, 153, 198,  74,
                                                            687, 907, 227, 509,  82, 655, 393,  42, 794, 913,  84,  31, 972, 123,
                                                            428, 666, 864, 148, 258, 190, 195, 970, 104, 861, 564, 649, 323, 966,
                                                            678, 781,  26, 438, 735, 831, 594, 146,  44, 144, 149, 985, 872, 828,
                                                            817, 682, 418, 365, 485, 537, 792, 863, 619, 217, 589, 143, 508, 466,
                                                            441, 169, 675, 387, 937, 808, 883, 885, 591, 293, 642, 892,   1, 573,
                                                            280, 145, 105, 565, 627, 312, 358, 947, 898, 300, 281, 680, 288, 982,
                                                            607, 345, 837, 542, 662, 916, 991, 335, 446, 171, 899, 333, 404, 785,
                                                            996, 733, 213, 452]), tensor([1, 8, 0, 1, 7, 6, 9, 0, 2, 3, 2, 4, 8, 0, 3, 6, 2, 0, 1, 6, 8, 6, 8, 6,
                                                            3, 7, 8, 9, 6, 8, 9, 3, 2, 6, 2, 3, 4, 7, 0, 0, 3, 3, 9, 3, 1, 6, 9, 1,
                                                            4, 4, 3, 8, 4, 6, 8, 8, 2, 7, 2, 8, 1, 9, 3, 2, 3, 2, 7, 6, 3, 4, 5, 3,
                                                            3, 3, 8, 4, 5, 6, 1, 0, 8, 1, 4, 7, 2, 3, 6, 3, 0, 9, 1, 1, 8, 9, 5, 6,
                                                            0, 8, 5, 6, 2, 8, 1, 1, 2, 9, 6, 4, 7, 3, 3, 2, 5, 3, 9, 7, 6, 5, 9, 6,
                                                            0, 0, 6, 7, 2, 2, 5, 5, 4, 7, 7, 7, 5, 1, 4, 1, 1, 1, 1, 8, 9, 7, 5, 2,
                                                            0, 1, 3, 4, 0, 4, 3, 1, 9, 4, 5, 9, 2, 3, 6, 7, 5, 5, 0, 2, 6, 0, 0, 4,
                                                            7, 8, 7, 9, 1, 3, 0, 9, 5, 2, 4, 2, 9, 5, 2, 0, 5, 8, 9, 8, 3, 6, 7, 8,
                                                            6, 1, 2, 1, 8, 6, 9, 6])),
                                              names=('seed_nodes', 'labels'),
                                      )},
                                names=('seed_nodes', 'labels'),
                    ),
           metadata={'name': 'node_classification', 'num_classes': 10},
)

Loaded link prediction task: OnDiskTask(validation_set=ItemSetDict(items={'user:like:item': ItemSet(items=(tensor([[820, 466],
                                                                  [829, 175],
                                                                  [481, 782],
                                                                  ...,
                                                                  [398, 199],
                                                                  [321, 428],
                                                                  [947,  54]]), tensor([[671, 993, 565,  ..., 390,  59,   3],
                                                                  [254, 364, 442,  ..., 841,  62, 820],
                                                                  [375, 602, 947,  ..., 408,  73, 925],
                                                                  ...,
                                                                  [700, 494, 969,  ..., 111, 997,  44],
                                                                  [ 46, 692, 300,  ..., 680, 537, 733],
                                                                  [502, 531,  40,  ..., 181, 412, 872]])),
                                                    names=('node_pairs', 'negative_dsts'),
                                            ), 'user:follow:user': ItemSet(items=(tensor([[213, 202],
                                                                  [672, 971],
                                                                  [534, 401],
                                                                  ...,
                                                                  [488,  74],
                                                                  [355, 231],
                                                                  [771,  77]]), tensor([[147, 571, 319,  ..., 809, 431, 462],
                                                                  [908, 539, 695,  ..., 613, 628, 929],
                                                                  [342, 654,  66,  ..., 440,  50, 125],
                                                                  ...,
                                                                  [977, 767, 910,  ..., 773, 469, 312],
                                                                  [134, 539, 451,  ..., 134, 584, 352],
                                                                  [324, 888, 985,  ..., 488, 135,  45]])),
                                                    names=('node_pairs', 'negative_dsts'),
                                            )},
                                      names=('node_pairs', 'negative_dsts'),
                          ),
           train_set=ItemSetDict(items={'user:like:item': ItemSet(items=(tensor([[467, 794],
                                                             [966, 870],
                                                             [321, 690],
                                                             ...,
                                                             [579, 373],
                                                             [715, 612],
                                                             [598, 560]]),),
                                               names=('node_pairs',),
                                       ), 'user:follow:user': ItemSet(items=(tensor([[729, 425],
                                                             [184, 562],
                                                             [599, 304],
                                                             ...,
                                                             [418, 823],
                                                             [422,  69],
                                                             [643,  62]]),),
                                               names=('node_pairs',),
                                       )},
                                 names=('node_pairs',),
                     ),
           test_set=ItemSetDict(items={'user:like:item': ItemSet(items=(tensor([128, 400]), tensor([[465, 344, 982,  ..., 624, 406, 723],
                                                            [225,   7, 415,  ..., 335, 272, 859],
                                                            [952, 795, 594,  ..., 167, 770, 728],
                                                            ...,
                                                            [687, 971, 917,  ..., 396, 646, 300],
                                                            [894, 960, 446,  ..., 201,  43, 694],
                                                            [387, 550,  83,  ..., 566, 716, 327]])),
                                              names=('node_pairs', 'negative_dsts'),
                                      ), 'user:follow:user': ItemSet(items=(tensor([538, 982]), tensor([[260, 250, 250,  ..., 394, 241, 612],
                                                            [749, 467, 824,  ..., 827, 608, 834],
                                                            [724, 657, 158,  ..., 324, 237, 219],
                                                            ...,
                                                            [269,  89, 952,  ...,  49, 145, 535],
                                                            [845, 819, 316,  ...,  99, 450,  55],
                                                            [790, 291, 212,  ..., 490, 656, 752]])),
                                              names=('node_pairs', 'negative_dsts'),
                                      )},
                                names=('node_pairs', 'negative_dsts'),
                    ),
           metadata={'name': 'link_prediction', 'num_classes': 10},
)