README.md 4.41 KB
Newer Older
rusty1s's avatar
rusty1s committed
1
2
3
4
5
6
7
[pypi-image]: https://badge.fury.io/py/torch-cluster.svg
[pypi-url]: https://pypi.python.org/pypi/torch-cluster
[build-image]: https://travis-ci.org/rusty1s/pytorch_cluster.svg?branch=master
[build-url]: https://travis-ci.org/rusty1s/pytorch_cluster
[coverage-image]: https://codecov.io/gh/rusty1s/pytorch_cluster/branch/master/graph/badge.svg
[coverage-url]: https://codecov.io/github/rusty1s/pytorch_cluster?branch=master

rusty1s's avatar
rusty1s committed
8
# PyTorch Cluster
rusty1s's avatar
rusty1s committed
9

rusty1s's avatar
rusty1s committed
10
11
12
13
[![PyPI Version][pypi-image]][pypi-url]
[![Build Status][build-image]][build-url]
[![Code Coverage][coverage-image]][coverage-url]

rusty1s's avatar
rusty1s committed
14
15
--------------------------------------------------------------------------------

rusty1s's avatar
rusty1s committed
16
This package consists of a small extension library of highly optimized graph cluster algorithms for the use in [PyTorch](http://pytorch.org/).
rusty1s's avatar
typo  
rusty1s committed
17
The package consists of the following clustering algorithms:
rusty1s's avatar
rusty1s committed
18

rusty1s's avatar
credit  
rusty1s committed
19
* **[Graclus](#graclus)** from Dhillon *et al.*: [Weighted Graph Cuts without Eigenvectors: A Multilevel Approach](http://www.cs.utexas.edu/users/inderjit/public_papers/multilevel_pami.pdf) (PAMI 2007)
rusty1s's avatar
rusty1s committed
20
* **[Voxel Grid Pooling](#voxelgrid)** from, *e.g.*, Simonovsky and Komodakis: [Dynamic Edge-Conditioned Filters in Convolutional Neural Networks on Graphs](https://arxiv.org/abs/1704.02901) (CVPR 2017)
rusty1s's avatar
rusty1s committed
21
22
* **[Iterative Farthest Point Sampling](#farthestpointsampling)** from, *e.g.* Qi *et al.*: [PointNet++: Deep Hierarchical Feature Learning on Point Sets in a Metric Space](https://arxiv.org/abs/1706.02413) (NIPS 2017)
* **[k-NN](#knn-graph)** and **[Radius](#radius-graph)** graph generation
rusty1s's avatar
rusty1s committed
23
24
25
26
27

All included operations work on varying data types and are implemented both for CPU and GPU.

## Installation

rusty1s's avatar
rusty1s committed
28
Ensure that at least PyTorch 1.0.0 is installed and verify that `cuda/bin` and `cuda/include` are in your `$PATH` and `$CPATH` respectively, *e.g.*:
rusty1s's avatar
rusty1s committed
29
30
31
32
33
34
35
36
37

```
$ python -c "import torch; print(torch.__version__)"
>>> 0.4.1

$ echo $PATH
>>> /usr/local/cuda/bin:...

$ echo $CPATH
rusty1s's avatar
rusty1s committed
38
>>> /usr/local/cuda/include:...
rusty1s's avatar
rusty1s committed
39
40
```

rusty1s's avatar
rusty1s committed
41
42
43
Then run:

```
rusty1s's avatar
rusty1s committed
44
pip install torch-cluster
rusty1s's avatar
rusty1s committed
45
46
```

rusty1s's avatar
rusty1s committed
47
If you are running into any installation problems, please create an [issue](https://github.com/rusty1s/pytorch_cluster/issues).
rusty1s's avatar
rusty1s committed
48
Be sure to import `torch` first before using this package to resolve symbols the dynamic linker must see.
rusty1s's avatar
rusty1s committed
49

rusty1s's avatar
rusty1s committed
50
51
52
## Graclus

A greedy clustering algorithm of picking an unmarked vertex and matching it with one its unmarked neighbors (that maximizes its edge weight).
rusty1s's avatar
credit  
rusty1s committed
53
The GPU algorithm is adapted from Fagginger Auer and Bisseling: [A GPU Algorithm for Greedy Graph Matching](http://www.staff.science.uu.nl/~bisse101/Articles/match12.pdf) (LNCS 2012)
rusty1s's avatar
rusty1s committed
54
55
56
57
58

```python
import torch
from torch_cluster import graclus_cluster

rusty1s's avatar
rusty1s committed
59
60
row = torch.tensor([0, 1, 1, 2])
col = torch.tensor([1, 0, 2, 1])
rusty1s's avatar
new api  
rusty1s committed
61
weight = torch.Tensor([1, 1, 1, 1])  # Optional edge weights.
rusty1s's avatar
rusty1s committed
62
63
64
65
66
67

cluster = graclus_cluster(row, col, weight)
```

```
print(cluster)
rusty1s's avatar
rusty1s committed
68
tensor([0, 0, 1])
rusty1s's avatar
rusty1s committed
69
70
```

rusty1s's avatar
rusty1s committed
71
72
73
## VoxelGrid

A clustering algorithm, which overlays a regular grid of user-defined size over a point cloud and clusters all points within a voxel.
rusty1s's avatar
rusty1s committed
74
75
76
77
78

```python
import torch
from torch_cluster import grid_cluster

rusty1s's avatar
new api  
rusty1s committed
79
80
pos = torch.Tensor([[0, 0], [11, 9], [2, 8], [2, 2], [8, 3]])
size = torch.Tensor([5, 5])
rusty1s's avatar
rusty1s committed
81
82
83
84
85
86

cluster = grid_cluster(pos, size)
```

```
print(cluster)
rusty1s's avatar
rusty1s committed
87
tensor([0, 5, 3, 0, 1])
rusty1s's avatar
rusty1s committed
88
```
rusty1s's avatar
rusty1s committed
89

rusty1s's avatar
rusty1s committed
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
## FarthestPointSampling

A sampling algorith, which iteratively samples the most distant point (in metric distance) with regard to the rest points.

```python
import torch
from torch_cluster import fps

x = torch.Tensor([[-1, -1], [-1, 1], [1, -1], [1, 1]])
batch = torch.tensor([0, 0, 0, 0])
sample = fps(x, batch, ratio=0.5, random_start=False)
```

```
print(sample)
tensor([0, 3])
```

## kNN-Graph

Computes graph edges to the nearest *k* points in metric space.

```python
import torch
from torch_cluster import knn_graph

x = torch.Tensor([[-1, -1], [-1, 1], [1, -1], [1, 1]])
batch = torch.tensor([0, 0, 0, 0])
edge_index = knn_graph(x, k=2, batch=batch, loop=False)
```

```
print(edge_index)
tensor([[0, 0, 1, 1, 2, 2, 3, 3],
        [1, 2, 0, 2, 0, 3, 1, 2]])
```

## Radius-Graph

Computes graph edges to all points within a given distance in metric space.

```python
import torch
from torch_cluster import radius_graph

x = torch.Tensor([[-1, -1], [-1, 1], [1, -1], [1, 1]])
batch = torch.tensor([0, 0, 0, 0])
edge_index = radius_graph(x, r=1.5, batch=batch, loop=False)
```

```
print(edge_index)
tensor([[0, 0, 1, 1, 2, 2, 3, 3],
        [1, 2, 0, 2, 0, 3, 1, 2]])
```

rusty1s's avatar
rusty1s committed
146
147
148
149
150
## Running tests

```
python setup.py test
```