README.md 4.18 KB
Newer Older
rusty1s's avatar
rusty1s committed
1
2
3
4
5
<h1 align="center">PyGAS: Auto-Scaling GNNs in PyG</h1>

<img width="100%" src="https://raw.githubusercontent.com/rusty1s/pyg_autoscale/master/figures/overview.png?token=ABU7ZAXZ7WT3RIOSYHIDIVDAEI3SY" />

--------------------------------------------------------------------------------
rusty1s's avatar
rusty1s committed
6

rusty1s's avatar
rusty1s committed
7
8
*PyGAS* is the practical realization of our *<ins>G</ins>NN<ins>A</ins>uto<ins>S</ins>cale* (GAS) framework, which scales arbitrary message-passing GNNs to large graphs, as described in our paper:

rusty1s's avatar
rusty1s committed
9
Matthias Fey, Jan E. Lenssen, Frank Weichert, Jure Leskovec: **[GNNAutoScale: Scalable and Expressive Graph Neural Networks via Historical Embeddings]()** *(ICML 2021)*
rusty1s's avatar
rusty1s committed
10

rusty1s's avatar
rusty1s committed
11
GAS prunes entire sub-trees of the computation graph by utilizing historical embeddings from prior training iterations, leading to constant GPU memory consumption in respect to input mini-batch size, and maximally expressivity.
rusty1s's avatar
rusty1s committed
12
13

*PyGAS* is implemented in [PyTorch](https://pytorch.org/) and utilizes the [PyTorch Geometric](https://github.com/rusty1s/pytorch_geometric) (PyG) library.
rusty1s's avatar
rusty1s committed
14
It provides an easy-to-use interface to convert a common and custom GNN from PyG into its scalable variant:
rusty1s's avatar
rusty1s committed
15

rusty1s's avatar
rusty1s committed
16
```python
rusty1s's avatar
update  
rusty1s committed
17
from torch_geometric.nn import SAGEConv
rusty1s's avatar
rusty1s committed
18
from torch_geometric_autoscale import ScalableGNN
rusty1s's avatar
rusty1s committed
19
from torch_geometric_autoscale import metis, permute, SubgraphLoader
rusty1s's avatar
rusty1s committed
20
21

class GNN(ScalableGNN):
rusty1s's avatar
update  
rusty1s committed
22
23
24
25
26
27
28
29
    def __init__(self, num_nodes, in_channels, hidden_channels,
                 out_channels, num_layers):
        # * pool_size determines the number of pinned CPU buffers
        # * buffer_size determines the size of pinned CPU buffers,
        #   i.e. the maximum number of out-of-mini-batch nodes

        super().__init__(num_nodes, hidden_channels, num_layers,
                         pool_size=2, buffer_size=5000)
rusty1s's avatar
rusty1s committed
30

rusty1s's avatar
rusty1s committed
31
        self.convs = ModuleList()
rusty1s's avatar
update  
rusty1s committed
32
        self.convs.append(SAGEConv(in_channels, hidden_channels))
rusty1s's avatar
rusty1s committed
33
        for _ in range(num_layers - 2):
rusty1s's avatar
update  
rusty1s committed
34
35
            self.convs.append(SAGEConv(hidden_channels, hidden_channels))
        self.convs.append(SAGEConv(hidden_channels, out_channels))
rusty1s's avatar
rusty1s committed
36

rusty1s's avatar
rusty1s committed
37
    def forward(self, x, adj_t, *args):
rusty1s's avatar
rusty1s committed
38
        for conv, history in zip(self.convs[:-1], self.histories):
rusty1s's avatar
typos  
rusty1s committed
39
            x = conv(x, adj_t).relu_()
rusty1s's avatar
rusty1s committed
40
            x = self.push_and_pull(history, x, *args)
rusty1s's avatar
typos  
rusty1s committed
41
        return self.convs[-1](x, adj_t)
rusty1s's avatar
rusty1s committed
42
43
44
45
46

perm, ptr = metis(data.adj_t, num_parts=40, log=True)
data = permute(data, perm, log=True)
loader = SubgraphLoader(data, ptr, batch_size=10, shuffle=True)

rusty1s's avatar
rusty1s committed
47
model = GNN(...)
rusty1s's avatar
rusty1s committed
48
49
for batch, *args in loader:
    out = model(batch.x, batch.adj_t, *args)
rusty1s's avatar
rusty1s committed
50
```
rusty1s's avatar
rusty1s committed
51

rusty1s's avatar
rusty1s committed
52
53
A detailed decription of `ScalableGNN` can be found [in its implementation](https://github.com/rusty1s/pyg_autoscale/blob/master/torch_geometric_autoscale/models/base.py#L13).

rusty1s's avatar
rusty1s committed
54
## Requirements
rusty1s's avatar
rusty1s committed
55

rusty1s's avatar
rusty1s committed
56
* Install [**PyTorch >= 1.7.0**](https://pytorch.org/get-started/locally/)
rusty1s's avatar
rusty1s committed
57
* Install [**PyTorch Geometric >= 1.7.0**](https://github.com/rusty1s/pytorch_geometric#installation):
rusty1s's avatar
rusty1s committed
58
59

```
rusty1s's avatar
rusty1s committed
60
61
pip install torch-scatter -f https://pytorch-geometric.com/whl/torch-${TORCH}+${CUDA}.html
pip install torch-sparse -f https://pytorch-geometric.com/whl/torch-${TORCH}+${CUDA}.html
rusty1s's avatar
rusty1s committed
62
pip install torch-geometric
rusty1s's avatar
rusty1s committed
63
64
```

rusty1s's avatar
rusty1s committed
65
66
67
68
69
70
71
where `${TORCH}` should be replaced by either `1.7.0` or `1.8.0`, and `${CUDA}` should be replaced by either `cpu`, `cu92`, `cu101`, `cu102`, `cu110` or `cu111`, depending on your PyTorch installation.

## Installation

```
pip install git+https://github.com/rusty1s/pyg_autoscale.git
```
rusty1s's avatar
rusty1s committed
72

rusty1s's avatar
rusty1s committed
73
or
rusty1s's avatar
rusty1s committed
74
75
76
77
78

```
python setup.py install
```

rusty1s's avatar
rusty1s committed
79
## Project Structure
rusty1s's avatar
rusty1s committed
80

rusty1s's avatar
typos  
rusty1s committed
81
82
* **`torch_geometric_autoscale/`** contains the source code of *PyGAS*
* **`examples/`** contains examples to demonstrate how to apply GAS in practice
rusty1s's avatar
typos  
rusty1s committed
83
84
* **`small_benchmark/`** includes experiments to evaluate GAS performance on *small-scale* graphs
* **`large_benchmark/`** includes experiments to evaluate GAS performance on *large-scale* graphs
rusty1s's avatar
rusty1s committed
85

rusty1s's avatar
typos  
rusty1s committed
86
We use [**Hydra**](https://hydra.cc/) to manage hyperparameter configurations.
rusty1s's avatar
rusty1s committed
87
88
89
90
91
92
93
94
95
96
97
98
99

## Cite

Please cite [our paper]() if you use this code in your own work:

```
@inproceedings{Fey/etal/2021,
  title={{GNNAutoScale}: Scalable and Expressive Graph Neural Networks via Historical Embeddings},
  author={Fey, M. and Lenssen, J. E. and Weichert, F. and Leskovec, J.},
  booktitle={International Conference on Machine Learning (ICML)},
  year={2021},
}
```