|
1 |
| -# InductiveQE |
2 |
| -Official implementation of Inductive Logical Query Answering in Knowledge Graphs (NeurIPS 2022) |
| 1 | +# Inductive Logical Query Answering in Knowledge Graphs (NeurIPS 2022) # |
| 2 | + |
| 3 | +<p align="center"> |
| 4 | +<a href="https://arxiv.org/pdf/2210.08008.pdf"><img src="http://img.shields.io/badge/Paper-PDF-red.svg" alt="NeurIPS paper"></a> |
| 5 | +<a href="https://doi.org/10.5281/zenodo.7306046"><img src="https://zenodo.org/badge/DOI/10.5281/zenodo.7306046.svg" alt="InductiveQE dataset"></a> |
| 6 | +</p> |
| 7 | + |
| 8 | + |
| 9 | + |
| 10 | +This is the official code base of the paper |
| 11 | + |
| 12 | +[Inductive Logical Query Answering in Knowledge Graphs][paper] |
| 13 | + |
| 14 | +[Mikhail Galkin](https://migalkin.github.io), |
| 15 | +[Zhaocheng Zhu](https://kiddozhu.github.io), |
| 16 | +[Hongyu Ren](http://hyren.me/), |
| 17 | +[Jian Tang](https://jian-tang.com) |
| 18 | + |
| 19 | +[paper]: https://arxiv.org/abs/2210.08008 |
| 20 | + |
| 21 | +## Overview ## |
| 22 | + |
| 23 | +**Important: the camera-ready NeurIPS'22 version was identified to have datasets with possible test set leakages. |
| 24 | +The new version including this repository and updated Arxiv submission have new datasets and experiments where this |
| 25 | +issue has been fixed. We recommend to use the latest version of datasets ([2.0 on Zenodo][dataset]) and experiments ([v2 on arXiv][paper]) for further |
| 26 | +comparisons.** |
| 27 | + |
| 28 | +[dataset]: https://zenodo.org/record/7306046 |
| 29 | + |
| 30 | +Inductive query answering is the setup where at inference time an underlying graph can have new, unseen entities. |
| 31 | +In this paper, we study a practical inductive setup when a training graph **is extended** with more nodes and edges |
| 32 | +at inference time. That is, an inference graph is always a superset of the training graph. |
| 33 | +Note that the inference graph always shares the same set of relation types with the training graph. |
| 34 | + |
| 35 | +The two big implications of the inductive setup: |
| 36 | +* test queries involve new, unseen nodes where answers can be both seen and unseen nodes; |
| 37 | +* training queries now might have more answers among new nodes. |
| 38 | + |
| 39 | +The two inductive approaches implemented in this repo: |
| 40 | +1. **NodePiece-QE** (Inductive node representations): based on [NodePiece](https://github.com/migalkin/NodePiece) and [CQD](https://github.com/pminervini/KGReasoning/). |
| 41 | +Train on 1p link prediction, **inference-only** zero-shot logical query answering over unseen entities. |
| 42 | +The NodePiece encoder can be extended with the additional GNN encoder (CompGCN) that is denoted as **NodePiece-QE w/ GNN** in the paper. |
| 43 | +2. **Inductive GNN-QE** (Inductive relational structure representations): based on [GNN-QE](https://github.com/DeepGraphLearning/GNN-QE). |
| 44 | +Trainable on complex queries, achieves higher performance than NodePiece-QE but is more expensive to train. |
| 45 | + |
| 46 | +We additionally provide a dummy Edge-type Heuristic (`model.HeuristicBaseline`) that only considers possible tails of the last relation projection step of any query pattern. |
| 47 | + |
| 48 | +## Data ## |
| 49 | + |
| 50 | +We created 10 new inductive query answering datasets where validation/test graphs extend the training graph and contain new entities: |
| 51 | +* Small-scale: 9 datasets based on FB15k-237 with the ratio of *inference-to-train nodes* varies from 106% to 550%, total of 15k nodes for various splits. |
| 52 | +* Large-scale: 1 dataset based on OGB WikiKG2 with the fixed ratio of 133% and 1.5M training nodes but with 500K new nodes and 5M new edges at inference. |
| 53 | + |
| 54 | +<details> |
| 55 | +<summary>Datasets Description</summary> |
| 56 | + |
| 57 | +Each dataset is a zip archive containing 17 files: |
| 58 | + |
| 59 | +* `train_graph.txt` (pt for wikikg) - original training graph |
| 60 | +* `val_inference.txt` (pt) - inference graph (validation split), new nodes in validation are disjoint with the test inference graph |
| 61 | +* `val_predict.txt` (pt) - missing edges in the validation inference graph to be predicted. |
| 62 | +* `test_inference.txt` (pt) - inference graph (test splits), new nodes in test are disjoint with the validation inference graph |
| 63 | +* `test_predict.txt` (pt) - missing edges in the test inference graph to be predicted. |
| 64 | +* `train/valid/test_queries.pkl` - queries of the respective split, 14 query types for fb-derived datasets, 9 types for WikiKG (EPFO-only) |
| 65 | +* `*_answers_easy.pkl` - easy answers to respective queries that do not require predicting missing links but only edge traversal |
| 66 | +* `*_answers_hard.pkl` - hard answers to respective queries that DO require predicting missing links and against which the final metrics will be computed |
| 67 | +* `train_answers_valid.pkl` - the extended set of answers for training queries on the bigger validation graph, most of training queries have at least 1 more new answers. This is supposed to be an inference-only dataset to measure faithfulness of trained models |
| 68 | +* `train_answers_test.pkl` - the extended set of answers for training queries on the bigger test graph, most of training queries have at least 1 more new answers. This is supposed to be an inference-only dataset to measure faithfulness of trained models |
| 69 | +* `og_mappings.pkl` - contains entity2id / relation2id dictionaries mapping local node/relation IDs from a respective dataset to the original fb15k237 / wikikg2 |
| 70 | +* `stats.txt` - a small file with dataset stats |
| 71 | +</details> |
| 72 | + |
| 73 | +All datasets are available on [Zenodo](https://zenodo.org/record/7306046), please refer to v2.0 of the datasets. |
| 74 | +The datasets will be downloaded automatically upon the first run. |
| 75 | + |
| 76 | +Additionally, we provide lightweight dumps ([Zenodo](https://zenodo.org/record/7306061)) just of those graphs (without queries and answers) for training simple link prediction and KG completion models. |
| 77 | +Please refer to v2.0 of the datasets. |
| 78 | + |
| 79 | +## Installation ## |
| 80 | + |
| 81 | +The dependencies can be installed via either conda or pip. NodePiece-QE and GNN-QE are compatible |
| 82 | +with Python 3.7/3.8/3.9 and PyTorch >= 1.8.0. |
| 83 | + |
| 84 | +### From Conda ### |
| 85 | + |
| 86 | +```bash |
| 87 | +conda install torchdrug pytorch cudatoolkit -c milagraph -c pytorch -c pyg |
| 88 | +conda install pytorch-sparse pytorch-scatter -c pyg |
| 89 | +conda install easydict pyyaml -c conda-forge |
| 90 | +``` |
| 91 | + |
| 92 | +### From Pip ### |
| 93 | + |
| 94 | +```bash |
| 95 | +pip install torchdrug torch |
| 96 | +pip install easydict pyyaml |
| 97 | +pip install wandb tensorboardx |
| 98 | +``` |
| 99 | + |
| 100 | +Then install `torch-scatter` and `torch-sparse` following the instructions in the [Github repo](https://github.com/rusty1s/pytorch_sparse). |
| 101 | +For example, for PyTorch 1.10 and CUDA 10.2: |
| 102 | + |
| 103 | +```bash |
| 104 | +pip install torch-scatter torch-sparse -f https://data.pyg.org/whl/torch-1.10.0+cu102.html |
| 105 | +``` |
| 106 | + |
| 107 | + |
| 108 | +## Usage ## |
| 109 | + |
| 110 | +### NodePiece-QE ### |
| 111 | + |
| 112 | +Conceptually, running NodePiece-QE consists of two parts: |
| 113 | +1. Training a neural link predictor using NodePiece (+ optional GNN), saving materialized embeddings of the test graph. |
| 114 | +2. Running CQD over the saved embeddings. |
| 115 | + |
| 116 | +**Step 1: Training a Link Predictor** |
| 117 | + |
| 118 | +Use the `NodePiece` model with the task `InductiveKnowledgeGraphCompletion` applied to the dataset of choice. |
| 119 | + |
| 120 | +We prepared 5 configs for FB15k-237-derived datasets in the `config/lp_pretraining` directory, 2 for NodePiece w/o GNN |
| 121 | +and 3 for NodePiece w/ GNN, following the reported hyperparameters in the paper. |
| 122 | +`_550` configs have a higher `input_dim` so we decided to have a dedicated file for them to send less params to the |
| 123 | +training script. |
| 124 | + |
| 125 | +We also provide 2 configs for the WikiKG graph and recommend running pre-training in the multi-gpu mode due to the size |
| 126 | +of the graph. |
| 127 | + |
| 128 | +Example of training a vanilla NodePiece on the 175% dataset: |
| 129 | + |
| 130 | +```bash |
| 131 | +python script/run.py -c config/lp_pretraining/nodepiece_nognn.yaml --ratio 175 --temp 0.5 --epochs 2000 --gpus [0] --logger console |
| 132 | +``` |
| 133 | + |
| 134 | +NodePiece + GNN on the 175% dataset: |
| 135 | +```bash |
| 136 | +python script/run.py -c config/lp_pretraining/nodepiece_gnn.yaml --ratio 175 --temp 1.0 --epochs 1000 --gpus [0] --logger console |
| 137 | +``` |
| 138 | + |
| 139 | +For datasets of ratios 106-150 use the 5-layer GNN config `config/lp_pretraining/nodepiece_gnn.yaml`. |
| 140 | + |
| 141 | +* Use `--gpus null` to run the scripts on a CPU. |
| 142 | +* Use `--logger wandb` to send training logs to wandb, don't forget to prepend env variable `WANDB_ENTITY=(your_entity)` |
| 143 | +before executing the python script. |
| 144 | + |
| 145 | +After training, materialized entity and relation embeddings of the test graph will be stored in the `output_dir` folder. |
| 146 | + |
| 147 | +WikiKG training requires a vocabulary of mined NodePiece anchors, we ship a precomputed |
| 148 | +vocab `20000_anchors_d0.4_p0.4_r0.2_25sp_bfs.pkl` together with the `wikikg.zip` archive. |
| 149 | +You can mine your own vocab playing around with the `NodePieceTokenizer` -- mining is implemented on a GPU and |
| 150 | +should be much faster than the original NodePiece implementation. |
| 151 | + |
| 152 | +An example WikiKG link prediction pre-training config should contain `--vocab` param to the mined vocab, e.g., |
| 153 | +```bash |
| 154 | +python script/run.py -c config/lp_pretraining/wikikg_nodepiece_nognn.yaml --gpus [0] --vocab /path/to/pickle/vocab.pkl |
| 155 | +``` |
| 156 | + |
| 157 | +We highly recommend training both no-GNN and GNN versions of NodePiece on WikiKG using several GPUs, for example |
| 158 | +```bash |
| 159 | +python -m torch.distributed.launch --nproc_per_node=2 script/run.py -c config/lp_pretraining/wikikg_nodepiece_nognn.yaml --gpus [0,1] --vocab /path/to/pickle/vocab.pkl |
| 160 | +``` |
| 161 | + |
| 162 | +**Step 2: CQD Inference** |
| 163 | + |
| 164 | +Use the pre-trained link predictor to run CQD inference over EPFO queries (negation is not supported in this version of CQD). |
| 165 | + |
| 166 | +Example of running CQD on the pre-trained 200d NodePiece w/ GNN model over the 175% dataset |
| 167 | +* Note that we need to specify a 2x smaller embedding dimension of the training model as by default we train a |
| 168 | +ComplEx model with two parts - real and complex; |
| 169 | +* Use the full path to the **embeddings** of the pre-trained models, they are named smth like `/path/epoch_1000_ents` |
| 170 | +and `/path/epoch_1000_rels`, so just use the common prefix `/path/epoch_1000`. |
| 171 | + |
| 172 | +```bash |
| 173 | +python cqd/main.py --cuda --do_test --data_path ./data/175 -d 100 -cpu 6 --log_steps 10000 --test_log_steps 10000 --geo cqd --print_on_screen --cqd-k 32 --cqd-sigmoid --tasks "1p.2p.3p.2i.3i.ip.pi.2u.up" --inductive --checkpoint_path /path/epoch_1000 --skip_tr |
| 174 | +``` |
| 175 | + |
| 176 | +To evaluate training queries on the bigger test graphs, use the argument `--eval_train` |
| 177 | + |
| 178 | +```bash |
| 179 | +python cqd/main.py --cuda --do_test --data_path ./data/175 -d 100 -cpu 6 --log_steps 10000 --test_log_steps 10000 --geo cqd --print_on_screen --cqd-k 32 --cqd-sigmoid --tasks "1p.2p.3p.2i.3i.ip.pi.2u.up" --inductive --checkpoint_path /path/epoch_1000 --eval_train |
| 180 | +``` |
| 181 | + |
| 182 | +### GNN-QE ### |
| 183 | + |
| 184 | +To train GNN-QE and evaluate on the valid/test queries and desired dataset ratio, use the `gnnqe_main.yaml` config. |
| 185 | +Example on the 175% dataset: |
| 186 | + |
| 187 | +```bash |
| 188 | +python script/run.py -c config/complex_query/gnnqe_main.yaml --ratio 175 --gpus [0] |
| 189 | +``` |
| 190 | + |
| 191 | +Alternatively, you may specify `--gpus null` to run GNN-QE on a CPU. |
| 192 | + |
| 193 | +The hyperparameters are designed for 32GB GPUs, but you may adjust the batch size in the config file |
| 194 | +to fit a smaller GPU memory. |
| 195 | + |
| 196 | +To run GNN-QE with multiple GPUs or multiple machines, use the following commands |
| 197 | + |
| 198 | +```bash |
| 199 | +python -m torch.distributed.launch --nproc_per_node=2 script/run.py -c config/complex_query/gnnqe_main.yaml --gpus [0,1] |
| 200 | +``` |
| 201 | + |
| 202 | +```bash |
| 203 | +python -m torch.distributed.launch --nnodes=4 --nproc_per_node=4 script/run.py -c config/complex_query/gnnqe_main.yaml --gpus [0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3] |
| 204 | +``` |
| 205 | + |
| 206 | +To evaluate training queries on the bigger test graphs, use the config `gnnqe_eval_train.yaml` and specify the |
| 207 | +checkpoint `--checkpoint` of the trained model. The best performing checkpoint is written in the log files after training the `main` config. |
| 208 | +For example, if the best performing 175% model is `model_epoch_1.pth` then the path will be: |
| 209 | +```bash |
| 210 | +python script/run.py -c config/complex_query/gnnqe_eval_train.yaml --ratio 175 --gpus [0] --checkpoint /path/to/model/model_epoch_1.pth |
| 211 | +``` |
| 212 | + |
| 213 | +### Heuristic Baseline ### |
| 214 | + |
| 215 | +Finally, we provide configs for the inference-only rule-based heuristic baseline |
| 216 | +that only considers possible tails of the last relation projection step of any query pattern. |
| 217 | +The two configs are `config/complex_query/heuristic_main.yaml` and `config/complex_query/heuristic_eval_train.yaml`. |
| 218 | + |
| 219 | +To run the baseline on test queries (for example, on the 175% dataset): |
| 220 | + |
| 221 | +```bash |
| 222 | +python script/run.py -c config/complex_query/heuristic_main.yaml --ratio 175 --gpus [0] |
| 223 | +``` |
| 224 | + |
| 225 | +To run the baseline on train queries over bigger test graphs: |
| 226 | +```bash |
| 227 | +python script/run.py -c config/complex_query/heuristic_eval_train.yaml --ratio 175 --gpus [0] |
| 228 | +``` |
| 229 | + |
| 230 | +## Citation ## |
| 231 | + |
| 232 | +If you find this project useful in your research, please cite the following paper |
| 233 | + |
| 234 | +```bibtex |
| 235 | +@inproceedings{galkin2022inductive, |
| 236 | + title={Inductive Logical Query Answering in Knowledge Graphs}, |
| 237 | + author={Mikhail Galkin and Zhaocheng Zhu and Hongyu Ren and Jian Tang}, |
| 238 | + booktitle={Advances in Neural Information Processing Systems}, |
| 239 | + year={2022}, |
| 240 | + url={https://openreview.net/forum?id=-vXEN5rIABY} |
| 241 | +} |
| 242 | +``` |
0 commit comments