Skip to content

Commit

Permalink
Merge branch 'master' into kamil.andrzejewski/fixed_size_norm_layers
Browse files Browse the repository at this point in the history
  • Loading branch information
rusty1s authored Apr 9, 2023
2 parents 2373600 + 94b2880 commit c6466dd
Show file tree
Hide file tree
Showing 9 changed files with 154 additions and 65 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).

### Added

- Added instructions for ROCm build wheels ([#7143](https://github.com/pyg-team/pytorch_geometric/pull/7143))
- Added a `ComposeFilters` class to compose `pre_filter` functions in `Dataset` ([#7097](https://github.com/pyg-team/pytorch_geometric/pull/7097))
- Added a time-step aware variant of the `EllipticBitcoinDataset` called `EllipticBitcoinTemporalDataset` ([#7011](https://github.com/pyg-team/pytorch_geometric/pull/7011))
- Added `to_dgl` and `from_dgl` conversion functions ([#7053](https://github.com/pyg-team/pytorch_geometric/pull/7053))
Expand All @@ -17,6 +18,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
### Changed

- Added an optional `batch_size` argument to `LayerNorm`, `GraphNorm`, `InstanceNorm`, `GraphSizeNorm` and `PairNorm` ([#7135](https://github.com/pyg-team/pytorch_geometric/pull/7135))
- Improved code coverage ([#7093](https://github.com/pyg-team/pytorch_geometric/pull/7093))
- Fix `numpy` incompatiblity when reading files for `Planetoid` datasets ([#7141](https://github.com/pyg-team/pytorch_geometric/pull/7141))
- Added support for `Data.num_edges` for native `torch.sparse.Tensor` adjacency matrices ([#7104](https://github.com/pyg-team/pytorch_geometric/pull/7104))
- Fixed crash of heterogeneous data loaders if node or edge types are missing ([#7060](https://github.com/pyg-team/pytorch_geometric/pull/7060), [#7087](https://github.com/pyg-team/pytorch_geometric/pull/7087))
- Accelerated attention-based `MultiAggregation` ([#7077](https://github.com/pyg-team/pytorch_geometric/pull/7077))
Expand Down
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ If you want to utilize the full set of features from PyG, there exists several a
* **[`torch-cluster`](https://github.com/rusty1s/pytorch_cluster)**: Graph clustering routines
* **[`torch-spline-conv`](https://github.com/rusty1s/pytorch_spline_conv)**: [`SplineConv`](https://pytorch-geometric.readthedocs.io/en/latest/generated/torch_geometric.nn.conv.SplineConv.html) support

These packages come with their own CPU and GPU kernel implementations based on the [PyTorch C++/CUDA extension interface](https://github.com/pytorch/extension-cpp).
These packages come with their own CPU and GPU kernel implementations based on the [PyTorch C++/CUDA/hip(ROCm) extension interface](https://github.com/pytorch/extension-cpp).
For a basic usage of PyG, these dependencies are **fully optional**.
We recommend to start with a minimal installation, and install additional dependencies once you start to actually need them.

Expand Down Expand Up @@ -446,6 +446,11 @@ or install PyG **from master** via
pip install git+https://github.com/pyg-team/pytorch_geometric.git
```

### ROCm Wheels

The external [`pyg-rocm-build` repository](https://github.com/Looong01/pyg-rocm-build) provides wheels and detailed instructions on how to install PyG for ROCm.
If you have any questions about it, please open an issue [here](https://github.com/Looong01/pyg-rocm-build/issues).

## Cite

Please cite [our paper](https://arxiv.org/abs/1903.02428) (and the respective papers of the methods used) if you use this code in your own work:
Expand Down
5 changes: 4 additions & 1 deletion docs/source/install/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ If you want to utilize the full set of features from :pyg:`PyG`, there exists se
* `torch-cluster <https://github.com/rusty1s/pytorch_cluster>`__: Graph clustering routines
* `torch-spline-conv <https://github.com/rusty1s/pytorch_spline_conv>`__: :class:`~torch_geometric.nn.conv.SplineConv` support

These packages come with their own CPU and GPU kernel implementations based on the :pytorch:`null` `PyTorch C++/CUDA extension interface <https://github.com/pytorch/extension-cpp/>`_.
These packages come with their own CPU and GPU kernel implementations based on the :pytorch:`null` `PyTorch C++/CUDA/hip(ROCm) extension interface <https://github.com/pytorch/extension-cpp/>`_.
For a basic usage of :pyg:`PyG`, these dependencies are **fully optional**.
We recommend to start with a minimal installation, and install additional dependencies once you start to actually need them.

Expand Down Expand Up @@ -104,6 +104,9 @@ For ease of installation of these extensions, we provide :obj:`pip` wheels for t
**For older versions, you need to explicitly specify the latest supported version number** or install via :obj:`pip install --no-index` in order to prevent a manual installation from source.
You can look up the latest supported version number `here <https://data.pyg.org/whl>`__.

**ROCm:** The external `pyg-rocm-build repository <https://github.com/Looong01/pyg-rocm-build>`__ provides wheels and detailed instructions on how to install :pyg:`PyG` for ROCm.
If you have any questions about it, please open an issue `here <https://github.com/Looong01/pyg-rocm-build/issues>`__.

Installation from Source
~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
31 changes: 31 additions & 0 deletions test/data/test_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from torch_geometric.data.storage import BaseStorage


def test_views():
storage = BaseStorage(x=1, y=2, z=3)

assert str(storage.keys()) == "KeysView({'x': 1, 'y': 2, 'z': 3})"
assert len(storage.keys()) == 3
assert list(storage.keys()) == ['x', 'y', 'z']

assert str(storage.values()) == "ValuesView({'x': 1, 'y': 2, 'z': 3})"
assert len(storage.values()) == 3
assert list(storage.values()) == [1, 2, 3]

assert str(storage.items()) == "ItemsView({'x': 1, 'y': 2, 'z': 3})"
assert len(storage.items()) == 3
assert list(storage.items()) == [('x', 1), ('y', 2), ('z', 3)]

args = ['x', 'z', 'foo']

assert str(storage.keys(*args)) == "KeysView({'x': 1, 'z': 3})"
assert len(storage.keys(*args)) == 2
assert list(storage.keys(*args)) == ['x', 'z']

assert str(storage.values(*args)) == "ValuesView({'x': 1, 'z': 3})"
assert len(storage.values(*args)) == 2
assert list(storage.values(*args)) == [1, 3]

assert str(storage.items(*args)) == "ItemsView({'x': 1, 'z': 3})"
assert len(storage.items(*args)) == 2
assert list(storage.items(*args)) == [('x', 1), ('z', 3)]
17 changes: 12 additions & 5 deletions test/loader/test_dataloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from torch_geometric.data import Data, HeteroData
from torch_geometric.loader import DataLoader
from torch_geometric.testing import get_random_edge_index
from torch_geometric.testing import get_random_edge_index, withCUDA

with_mp = sys.platform not in ['win32']
num_workers_list = [0, 2] if with_mp else [0]
Expand All @@ -16,25 +16,32 @@
multiprocessing.set_start_method('spawn')


@withCUDA
@pytest.mark.parametrize('num_workers', num_workers_list)
def test_dataloader(num_workers):
def test_dataloader(num_workers, device):
if num_workers > 0 and device != torch.device('cpu'):
return

x = torch.Tensor([[1], [1], [1]])
edge_index = torch.tensor([[0, 1, 1, 2], [1, 0, 2, 1]])
face = torch.tensor([[0], [1], [2]])
y = 2.
z = torch.tensor(0.)
name = 'data'

data = Data(x=x, edge_index=edge_index, y=y, z=z, name=name)
assert str(data) == (
"Data(x=[3, 1], edge_index=[2, 4], y=2.0, z=0.0, name='data')")
data = Data(x=x, edge_index=edge_index, y=y, z=z, name=name).to(device)
assert str(data) == ("Data(x=[3, 1], edge_index=[2, 4], y=2.0, z=0.0, "
"name='data')")
data.face = face

loader = DataLoader([data, data, data, data], batch_size=2, shuffle=False,
num_workers=num_workers)
assert len(loader) == 2

for batch in loader:
assert batch.x.device == device
assert batch.edge_index.device == device
assert batch.z.device == device
assert batch.num_graphs == len(batch) == 2
assert batch.batch.tolist() == [0, 0, 0, 1, 1, 1]
assert batch.ptr.tolist() == [0, 3, 6]
Expand Down
17 changes: 9 additions & 8 deletions test/nn/conv/test_nn_conv.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,21 @@

import torch_geometric.typing
from torch_geometric.nn import NNConv
from torch_geometric.testing import is_full_test
from torch_geometric.testing import is_full_test, withCUDA
from torch_geometric.typing import SparseTensor
from torch_geometric.utils import to_torch_coo_tensor


def test_nn_conv():
x1 = torch.randn(4, 8)
x2 = torch.randn(2, 16)
edge_index = torch.tensor([[0, 1, 2, 3], [0, 0, 1, 1]])
value = torch.rand(edge_index.size(1), 3)
@withCUDA
def test_nn_conv(device):
x1 = torch.randn(4, 8, device=device)
x2 = torch.randn(2, 16, device=device)
edge_index = torch.tensor([[0, 1, 2, 3], [0, 0, 1, 1]], device=device)
value = torch.rand(edge_index.size(1), 3, device=device)
adj1 = to_torch_coo_tensor(edge_index, value, size=(4, 4))

nn = Seq(Lin(3, 32), ReLU(), Lin(32, 8 * 32))
conv = NNConv(8, 32, nn=nn)
conv = NNConv(8, 32, nn=nn).to(device)
assert str(conv) == (
'NNConv(8, 32, aggr=add, nn=Sequential(\n'
' (0): Linear(in_features=3, out_features=32, bias=True)\n'
Expand Down Expand Up @@ -49,7 +50,7 @@ def test_nn_conv():
# Test bipartite message passing:
adj1 = to_torch_coo_tensor(edge_index, value, size=(4, 2))

conv = NNConv((8, 16), 32, nn=nn)
conv = NNConv((8, 16), 32, nn=nn).to(device)
assert str(conv) == (
'NNConv((8, 16), 32, aggr=add, nn=Sequential(\n'
' (0): Linear(in_features=3, out_features=32, bias=True)\n'
Expand Down
46 changes: 28 additions & 18 deletions test/nn/conv/test_rgcn_conv.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,38 @@

import torch_geometric.typing
from torch_geometric.nn import FastRGCNConv, RGCNConv
from torch_geometric.testing import is_full_test
from torch_geometric.testing import is_full_test, withCUDA
from torch_geometric.typing import SparseTensor

classes = [RGCNConv, FastRGCNConv]
confs = [(None, None), (2, None), (None, 2)]


@withCUDA
@pytest.mark.parametrize('conf', confs)
def test_rgcn_conv_equality(conf):
def test_rgcn_conv_equality(conf, device):
num_bases, num_blocks = conf

x1 = torch.randn(4, 4)
edge_index = torch.tensor([[0, 1, 1, 2, 2, 3], [0, 0, 1, 0, 1, 1]])
edge_type = torch.tensor([0, 1, 1, 0, 0, 1])
x1 = torch.randn(4, 4, device=device)
edge_index = torch.tensor([
[0, 1, 1, 2, 2, 3],
[0, 0, 1, 0, 1, 1],
], device=device)
edge_type = torch.tensor([0, 1, 1, 0, 0, 1], device=device)

edge_index = torch.tensor([
[0, 1, 1, 2, 2, 3, 0, 1, 1, 2, 2, 3],
[0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1],
])
edge_type = torch.tensor([0, 1, 1, 0, 0, 1, 2, 3, 3, 2, 2, 3])
], device=device)
edge_type = torch.tensor([0, 1, 1, 0, 0, 1, 2, 3, 3, 2, 2, 3],
device=device)

torch.manual_seed(12345)
conv1 = RGCNConv(4, 32, 4, num_bases, num_blocks, aggr='sum')
conv1 = RGCNConv(4, 32, 4, num_bases, num_blocks, aggr='sum').to(device)

torch.manual_seed(12345)
conv2 = FastRGCNConv(4, 32, 4, num_bases, num_blocks, aggr='sum')
conv2 = FastRGCNConv(4, 32, 4, num_bases, num_blocks,
aggr='sum').to(device)

out1 = conv1(x1, edge_index, edge_type)
out2 = conv2(x1, edge_index, edge_type)
Expand All @@ -40,19 +46,23 @@ def test_rgcn_conv_equality(conf):
assert torch.allclose(out1, out2, atol=1e-6)


@withCUDA
@pytest.mark.parametrize('cls', classes)
@pytest.mark.parametrize('conf', confs)
def test_rgcn_conv(cls, conf):
def test_rgcn_conv(cls, conf, device):
num_bases, num_blocks = conf

x1 = torch.randn(4, 4)
x2 = torch.randn(2, 16)
idx1 = torch.arange(4)
idx2 = torch.arange(2)
edge_index = torch.tensor([[0, 1, 1, 2, 2, 3], [0, 0, 1, 0, 1, 1]])
edge_type = torch.tensor([0, 1, 1, 0, 0, 1])
x1 = torch.randn(4, 4, device=device)
x2 = torch.randn(2, 16, device=device)
idx1 = torch.arange(4, device=device)
idx2 = torch.arange(2, device=device)
edge_index = torch.tensor([
[0, 1, 1, 2, 2, 3],
[0, 0, 1, 0, 1, 1],
], device=device)
edge_type = torch.tensor([0, 1, 1, 0, 0, 1], device=device)

conv = cls(4, 32, 2, num_bases, num_blocks, aggr='sum')
conv = cls(4, 32, 2, num_bases, num_blocks, aggr='sum').to(device)
assert str(conv) == f'{cls.__name__}(4, 32, num_relations=2)'

out1 = conv(x1, edge_index, edge_type)
Expand Down Expand Up @@ -87,7 +97,7 @@ def test_rgcn_conv(cls, conf):
assert torch.allclose(jit(None, adj.t()), out2, atol=1e-6)

# Test bipartite message passing:
conv = cls((4, 16), 32, 2, num_bases, num_blocks, aggr='sum')
conv = cls((4, 16), 32, 2, num_bases, num_blocks, aggr='sum').to(device)
assert str(conv) == f'{cls.__name__}((4, 16), 32, num_relations=2)'

out1 = conv((x1, x2), edge_index, edge_type)
Expand Down
Loading

0 comments on commit c6466dd

Please sign in to comment.