Skip to content

Commit 6a36a26

Browse files
authored
[WIP] Release 0.9.1 (#499)
* update release file * add python 3.11 to tests * build wheels * build wheels again * remove python 3.7 from tests * add tests for layers * remove useless data * remove useless data * ad test on batching for GNN * add test alpha=0
1 parent a5cdd5b commit 6a36a26

File tree

4 files changed

+153
-31
lines changed

4 files changed

+153
-31
lines changed

.github/workflows/build_tests.yml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
strategy:
2323
max-parallel: 4
2424
matrix:
25-
python-version: ["3.7", "3.8", "3.9", "3.10"]
25+
python-version: ["3.8", "3.9", "3.10", "3.11"]
2626

2727
steps:
2828
- uses: actions/checkout@v1
@@ -52,7 +52,7 @@ jobs:
5252
- name: Set up Python
5353
uses: actions/setup-python@v1
5454
with:
55-
python-version: 3.9
55+
python-version: "3.10"
5656
- name: Install dependencies
5757
run: |
5858
python -m pip install --upgrade pip
@@ -73,18 +73,19 @@ jobs:
7373
- name: Set up Python
7474
uses: actions/setup-python@v1
7575
with:
76-
python-version: 3.9
76+
python-version: "3.10"
7777
- name: Install dependencies
7878
run: |
7979
python -m pip install --upgrade pip
80-
pip install pytest
80+
pip install pytest pytest-cov
8181
- name: Install POT
8282
run: |
8383
pip install -e .
8484
- name: Run tests
8585
run: |
86-
python -m pytest --durations=20 -v test/ ot/ --color=yes
87-
86+
python -m pytest --durations=20 -v test/ ot/ --color=yes --cov=./ --cov-report=xml
87+
- name: Upload coverage reports to Codecov with GitHub Action
88+
uses: codecov/codecov-action@v3
8889

8990
macos:
9091
runs-on: macos-latest

.github/workflows/build_wheels.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,22 @@ jobs:
1919

2020
steps:
2121
- uses: actions/checkout@v1
22-
- name: Set up Python 3.8
22+
- name: Set up Python 3.10
2323
uses: actions/setup-python@v1
2424
with:
25-
python-version: 3.8
25+
python-version: "3.10"
2626

2727
- name: Install dependencies
2828
run: |
2929
python -m pip install --upgrade pip
3030
3131
- name: Install cibuildwheel
3232
run: |
33-
python -m pip install cibuildwheel==2.2.2
33+
python -m pip install cibuildwheel==2.14.1
3434
3535
- name: Build wheels
3636
env:
37-
CIBW_SKIP: "pp*-win* pp*-macosx* cp2* pp* cp36*" # remove pypy on mac and win (wrong version)
37+
CIBW_SKIP: "pp*-win* pp*-macosx* cp2* pp* cp36* cp*musl*" # remove pypy on mac and win (wrong version)
3838
run: |
3939
python -m cibuildwheel --output-dir wheelhouse
4040
@@ -57,15 +57,15 @@ jobs:
5757
- name: Set up Python 3.8
5858
uses: actions/setup-python@v1
5959
with:
60-
python-version: 3.8
60+
python-version: "3.10"
6161

6262
- name: Install dependencies
6363
run: |
6464
python -m pip install --upgrade pip
6565
6666
- name: Install cibuildwheel
6767
run: |
68-
python -m pip install cibuildwheel==2.2.2
68+
python -m pip install cibuildwheel==2.14.1
6969
7070
- name: Set up QEMU
7171
if: runner.os == 'Linux'

ot/gnn/_layers.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,14 +124,14 @@ def __init__(self, n_features, n_tplt=2, n_tplt_nodes=2, alpha=None, train_node_
124124
if multi_alpha:
125125
self.alpha0 = torch.Tensor([0] * self.n_tplt)
126126
else:
127-
alpha0 = torch.Tensor([0])
128-
self.alpha0 = nn.Parameter(alpha0)
127+
self.alpha0 = torch.Tensor([0])
128+
self.alpha0 = nn.Parameter(self.alpha0)
129129
else:
130130
if multi_alpha:
131131
self.alpha0 = torch.Tensor([alpha] * self.n_tplt)
132132
else:
133133
self.alpha0 = torch.Tensor([alpha])
134-
self.alpha0 = torch.logit(alpha0)
134+
self.alpha0 = torch.logit(self.alpha0)
135135

136136
def forward(self, x, edge_index, batch=None):
137137
"""
@@ -227,8 +227,8 @@ def __init__(self, n_features, n_tplt=2, n_tplt_nodes=2, train_node_weights=True
227227
self.feature_init_std = feature_init_std
228228

229229
_, tplt_features, self.q0 = TFGW_template_initialization(self.n_tplt, self.n_tplt_nodes, self.n_features, self.feature_init_mean, self.feature_init_std)
230-
self.tplt_features = nn.Parameter(tplt_features)
231230

231+
self.tplt_features = nn.Parameter(tplt_features)
232232
self.softmax = nn.Softmax(dim=1)
233233

234234
if train_node_weights:

test/test_gnn.py

Lines changed: 136 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,21 @@
1010

1111
try: # test if pytorch_geometric is installed
1212
import torch_geometric
13+
import torch
14+
from torch_geometric.nn import Linear
15+
from torch_geometric.data import Data as GraphData
16+
from torch_geometric.loader import DataLoader
17+
import torch.nn as nn
18+
from ot.gnn import TFGWPooling, TWPooling
19+
1320
except ImportError:
1421
torch_geometric = False
1522

1623

1724
@pytest.mark.skipif(not torch_geometric, reason="pytorch_geometric not installed")
18-
def test_TFGW():
25+
def test_TFGW_optim():
1926
# Test the TFGW layer by passing two graphs through the layer and doing backpropagation.
2027

21-
import torch
22-
from torch_geometric.nn import Linear
23-
from torch_geometric.data import Data as GraphData
24-
from torch_geometric.loader import DataLoader
25-
import torch.nn as nn
26-
from ot.gnn import TFGWPooling
27-
2828
class pooling_TFGW(nn.Module):
2929
"""
3030
Pooling architecture using the TFGW layer.
@@ -52,6 +52,8 @@ def forward(self, x, edge_index):
5252

5353
return x
5454

55+
torch.manual_seed(0)
56+
5557
n_templates = 3
5658
n_template_nodes = 3
5759
n_nodes = 10
@@ -86,19 +88,135 @@ def forward(self, x, edge_index):
8688
loss = criterion(out, data.y)
8789
loss.backward()
8890
optimizer.step()
91+
optimizer.zero_grad()
92+
93+
94+
@pytest.mark.skipif(not torch_geometric, reason="pytorch_geometric not installed")
95+
def test_TFGW_variants():
96+
# Test the TFGW layer by passing two graphs through the layer and doing backpropagation.
97+
98+
class GNN_pooling(nn.Module):
99+
"""
100+
Pooling architecture using the TW layer.
101+
"""
102+
103+
def __init__(self, n_features, n_templates, n_template_nodes, pooling_layer):
104+
"""
105+
Pooling architecture using the TW layer.
106+
"""
107+
super().__init__()
108+
109+
self.n_features = n_features
110+
self.n_templates = n_templates
111+
self.n_template_nodes = n_template_nodes
112+
113+
self.TFGW = pooling_layer
114+
115+
self.linear = Linear(self.n_templates, 1)
116+
117+
def forward(self, x, edge_index, batch=None):
118+
119+
x = self.TFGW(x, edge_index, batch=batch)
120+
121+
x = self.linear(x)
122+
123+
return x
124+
125+
n_templates = 3
126+
n_template_nodes = 3
127+
n_nodes = 10
128+
n_features = 3
129+
130+
torch.manual_seed(0)
131+
132+
C1 = torch.randint(0, 2, size=(n_nodes, n_nodes))
133+
edge_index1 = torch.stack(torch.where(C1 == 1))
134+
x1 = torch.rand(n_nodes, n_features)
135+
graph1 = GraphData(x=x1, edge_index=edge_index1, y=torch.tensor([0.]))
136+
batch1 = torch.tensor([1] * n_nodes)
137+
batch1[:n_nodes // 2] = 0
138+
139+
criterion = torch.nn.CrossEntropyLoss()
140+
141+
for train_node_weights in [True, False]:
142+
for alpha in [None, 0, 0.5]:
143+
for multi_alpha in [True, False]:
144+
model = GNN_pooling(n_features, n_templates, n_template_nodes,
145+
pooling_layer=TFGWPooling(n_templates, n_template_nodes, n_features, alpha=alpha, multi_alpha=multi_alpha, train_node_weights=train_node_weights))
146+
147+
# predict
148+
out1 = model(graph1.x, graph1.edge_index)
149+
loss = criterion(out1, graph1.y)
150+
loss.backward()
151+
152+
# predict on batch
153+
out1 = model(graph1.x, graph1.edge_index, batch1)
154+
155+
156+
@pytest.mark.skipif(not torch_geometric, reason="pytorch_geometric not installed")
157+
def test_TW_variants():
158+
# Test the TFGW layer by passing two graphs through the layer and doing backpropagation.
159+
160+
class GNN_pooling(nn.Module):
161+
"""
162+
Pooling architecture using the TW layer.
163+
"""
164+
165+
def __init__(self, n_features, n_templates, n_template_nodes, pooling_layer):
166+
"""
167+
Pooling architecture using the TW layer.
168+
"""
169+
super().__init__()
170+
171+
self.n_features = n_features
172+
self.n_templates = n_templates
173+
self.n_template_nodes = n_template_nodes
174+
175+
self.TFGW = pooling_layer
176+
177+
self.linear = Linear(self.n_templates, 1)
178+
179+
def forward(self, x, edge_index, batch=None):
180+
181+
x = self.TFGW(x, edge_index, batch=batch)
182+
183+
x = self.linear(x)
184+
185+
return x
186+
187+
n_templates = 3
188+
n_template_nodes = 3
189+
n_nodes = 10
190+
n_features = 3
191+
192+
torch.manual_seed(0)
193+
194+
C1 = torch.randint(0, 2, size=(n_nodes, n_nodes))
195+
edge_index1 = torch.stack(torch.where(C1 == 1))
196+
x1 = torch.rand(n_nodes, n_features)
197+
graph1 = GraphData(x=x1, edge_index=edge_index1, y=torch.tensor([0.]))
198+
batch1 = torch.tensor([1] * n_nodes)
199+
batch1[:n_nodes // 2] = 0
200+
201+
criterion = torch.nn.CrossEntropyLoss()
202+
203+
for train_node_weights in [True, False]:
204+
205+
model = GNN_pooling(n_features, n_templates, n_template_nodes,
206+
pooling_layer=TWPooling(n_templates, n_template_nodes, n_features, train_node_weights=train_node_weights))
207+
208+
out1 = model(graph1.x, graph1.edge_index)
209+
loss = criterion(out1, graph1.y)
210+
loss.backward()
211+
212+
# predict on batch
213+
out1 = model(graph1.x, graph1.edge_index, batch1)
89214

90215

91216
@pytest.mark.skipif(not torch_geometric, reason="pytorch_geometric not installed")
92217
def test_TW():
93218
# Test the TW layer by passing two graphs through the layer and doing backpropagation.
94219

95-
import torch
96-
from torch_geometric.nn import Linear
97-
from torch_geometric.data import Data as GraphData
98-
from torch_geometric.loader import DataLoader
99-
import torch.nn as nn
100-
from ot.gnn import TWPooling
101-
102220
class pooling_TW(nn.Module):
103221
"""
104222
Pooling architecture using the TW layer.
@@ -126,6 +244,8 @@ def forward(self, x, edge_index):
126244

127245
return x
128246

247+
torch.manual_seed(0)
248+
129249
n_templates = 3
130250
n_template_nodes = 3
131251
n_nodes = 10
@@ -160,3 +280,4 @@ def forward(self, x, edge_index):
160280
loss = criterion(out, data.y)
161281
loss.backward()
162282
optimizer.step()
283+
optimizer.zero_grad()

0 commit comments

Comments
 (0)