RelBench: Relational Deep Learning Benchmark

repository·main·Indexed 18 days ago

https://github.com/stanford-star/relbench

A benchmark for end-to-end deep learning on relational databases, providing large-scale datasets, standardized task specifications, data loading, and evaluation metrics. Version 2.1.2 includes core functionality for managing relational datasets and tasks, a modeling suite requiring PyTorch and PyTorch Geometric, and support for TGB, CTU, and 4DBInfer dataset integrations.

Tokens
10K
Snippets
40
Records
42
Agent score
63%

What's inside relbench

  1. Access node features and edges in the RelBench graph

    main

    The data object is a HeteroData instance where node types are identified by their originating table name.

    • Node Features: Access a node type's features via data[node_type]. This returns a tuple containing a TensorFrame (analogous to a feature matrix) and a timestamp. You can index the TensorFrame directly: data["races"].tf[10].
    • Edges: Access edges between node types using the syntax data[(source_node_type, edge_type, target_node_type)]. Edge types follow the f2p convention (e.g., f2p_circuitId), where f stands for foreign key and p for primary key.
    # Access TensorFrame for features
    features = data["races"].tf[10:20]
    
    # Access edges between 'races' and 'circuits'
    edges = data[("races", "f2p_circuitId", "circuits")]
  2. Use Temporal Graph Benchmark (TGB) datasets

    main

    TGB datasets and tasks can be loaded in the RelBench format. These cover:

    • Bipartite link prediction (tgbl-*)
    • Heterogeneous link prediction (thgl-*)
    • Node property prediction (tgbn-*)

    Official TGB evaluation protocols (such as one-vs-many MRR / Hits@10 for link prediction and NDCG@10 for node property prediction) are implemented in relbench/tasks/tgb.py. Standard RelBench-style evaluation is also supported.

  3. Convert a database to a heterogeneous temporal graph

    main

    RelBench uses make_pkey_fkey_graph to transform a relational database into a HeteroData object. This process involves:

    1. Determining Column Types: Use get_stype_proposal(db) to automatically detect the stype (modality) for each column. Always verify this dictionary for accuracy.
    2. Configuring Text Encoders: If your data contains text, provide a TextEmbedderConfig containing a text embedding model (e.g., using sentence-transformers).
    3. Materializing the Graph: Call make_pkey_fkey_graph with the database, column types, and text encoder configuration. You can specify a cache_dir to store the materialized graph for faster subsequent loads.
    from relbench.modeling.utils import get_stype_proposal
    from relbench.modeling.graph import make_pkey_fkey_graph
    from torch_frame.config.text_embedder import TextEmbedderConfig
    
    # 1. Get column types
    db = dataset.get_db()
    col_to_stype_dict = get_stype_proposal(db)
    
    # 2. Setup text embedding (example using SentenceTransformer)
    # ... define GloveTextEmbedding class ...
    text_embedder_cfg = TextEmbedderConfig(
        text_embedder=GloveTextEmbedding(device=device), 
        batch_size=256
    )
    
    # 3. Create the graph
    data, col_stats_dict = make_pkey_fkey_graph(
        db,
        col_to_stype_dict=col_to_stype_dict,
        text_embedder_cfg=text_embedder_cfg,
        cache_dir="./data/rel-f1_materialized_cache"
    )
  4. RelBench Tutorials

    main

    For guided learning, refer to the following notebooks in the tutorials/ directory:

    • Load and explore RelBench data: load_data.ipynb
    • Train your first GNN-based model: train_model.ipynb
    • Use your own data in RelBench: custom_dataset.ipynb
    • Define your own ML tasks in RelBench: custom_task.ipynb
  5. Install RelBench

    main

    You can install the core RelBench functionality, which includes data and task loading, using pip.

    To use the full modeling suite (relbench.modeling), which requires PyTorch, PyTorch Geometric, and PyTorch Frame, install the [full] extra.

    To run the provided example scripts, install the [example] extra.

    # Core functionality only
    pip install relbench
    
    # Full modeling suite (includes PyTorch dependencies)
    pip install relbench[full]
    
    # For running example scripts
    pip install relbench[example]
  6. Install RelBench and its dependencies

    main

    To use RelBench for graph machine learning on relational datasets, you need to install relbench along with torch, torch-geometric (and its associated libraries), and pytorch_frame. Note that specific versions of torch and its extensions may be required depending on your environment (e.g., CPU vs CUDA).

    !pip install torch==2.4.0
    !pip install torch-geometric torch-sparse torch-scatter torch-cluster torch-spline-conv pyg-lib -f https://data.pyg.org/whl/torch-2.4.0+cpu.html
    !pip install pytorch_frame
    !pip install relbench
  7. Implement the `make_db` function and `Database` object

    main

    The make_db function is responsible for preprocessing raw data (from URLs or local files) into the RelBench format. It should return a relbench.base.Database object, which is a collection of relbench.base.Table objects.

    Creating a Table object

    Each table in the database is instantiated using the relbench.base.Table class with the following parameters:

    • df: A pd.DataFrame containing the table data.
    • fkey_col_to_pkey_table: A dictionary mapping foreign-key columns to their corresponding primary-key table names.
    • pkey_col: The name of the primary key column (or None).
    • time_col: The name of the column representing the row's creation time (or None). If None, the row is treated as created at -inf.

    Pkey/Fkey Reindexing

    When you use dataset.get_db(), RelBench automatically calls db.reindex_pkeys_and_fkeys(). This converts primary and foreign keys into consecutive integers starting from 0. To preserve original ID values for features or cross-referencing, add a duplicate column that is not marked as the pkey_col.

    from relbench.base import Database, Table
    import pandas as pd
    
    # Inside make_db...
    tables = {
        "users": Table(
            df=users_df,
            fkey_col_to_pkey_table={},
            pkey_col="user_id",
            time_col="created_at"
        ),
        "orders": Table(
            df=orders_df,
            fkey_col_to_pkey_table={"user_id": "users"},
            pkey_col="order_id",
            time_col="order_date"
        )
    }
    return Database(tables)
  8. Use and register custom datasets

    main

    Once a Dataset subclass is defined, you can instantiate it directly or register it for use with the global get_dataset API.

    Direct Usage

    Instantiate the class with a cache_dir. Use .get_db() to retrieve the database with temporal splitting applied, or .make_db() to retrieve the full database (useful for debugging).

    Registration

    Use register_dataset to make your dataset available via get_dataset. Note that the registry is not persistent across Python processes; you must re-register the dataset every time you start a new session (e.g., when running baseline scripts).

    Note: When registering, you can pass additional args and kwargs that will be used during the dataset's initialization.

    # Direct usage
    my_dataset = MyCustomDataset(cache_dir="./cache")
    db = my_dataset.get_db()
    
    # Registration
    from relbench.datasets import register_dataset, get_dataset
    
    register_dataset("my-custom-id", MyCustomDataset, arg1="value")
    new_dataset = get_dataset("my-custom-id")
  9. Create a custom dataset by subclassing `Dataset`

    main

    To define a custom dataset in RelBench, you must subclass relbench.base.Dataset. A valid subclass requires implementing three components:

    1. val_timestamp: A pd.Timestamp defining the validation split point.
    2. test_timestamp: A pd.Timestamp defining the test split point.
    3. make_db function: A method that returns a relbench.base.Database object.

    Temporal Splitting Logic

    RelBench uses these timestamps to prevent temporal leakage:

    • Validation Set: Only database rows up to val_timestamp are used for prediction. Ground truth labels for the validation set can only use rows up to test_timestamp.
    • Test Set: Only database rows up to test_timestamp are used for prediction. Ground truth labels for the test set use rows after test_timestamp.
    • Training Set: Ground truth labels for the training set can only use rows up to val_timestamp.
    from relbench.base import Dataset
    import pandas as pd
    
    class MyCustomDataset(Dataset):
        val_timestamp = pd.Timestamp("2023-01-01")
        test_timestamp = pd.Timestamp("2024-01-01")
    
        def make_db(self) -> Database:
            # Implementation logic here
            pass
  10. Register a custom task for global access

    main

    You can register a custom task so it becomes available via relbench.tasks.get_task. This allows the task to use standardized caching locations: ~/.cache/relbench/<dataset-name>/tasks/<task-name>.

    Note: The registry is not persistent across Python processes. If you are running external scripts (like those in examples/), you must call register_task within those scripts before calling get_task.

    Steps:

    1. Ensure the dataset is already registered.
    2. Call register_task(dataset_name, task_name, task_class).
    3. Access via get_task(dataset_name, task_name).
    from relbench.tasks import register_task, get_task, get_task_names
    
    # Register the task
    register_task("rel-f1", "custom_driver-dnf", DriverDNFTask)
    
    # Verify registration
    print(get_task_names("rel-f1"))
    
    # Retrieve the task
    task = get_task("rel-f1", "custom_driver-dnf")