ho22joshua commited on
Commit
dec4918
·
1 Parent(s): 6a17a0a

fix: enable validated ONNX export

Browse files
Files changed (3) hide show
  1. pyproject.toml +2 -0
  2. src/gnn4colliders/export/onnx.py +20 -15
  3. uv.lock +4 -0
pyproject.toml CHANGED
@@ -36,6 +36,8 @@ dev = [
36
  "pytest-cov>=5",
37
  "ruff>=0.6",
38
  "twine>=6,<7",
 
 
39
  ]
40
 
41
  [tool.setuptools.packages.find]
 
36
  "pytest-cov>=5",
37
  "ruff>=0.6",
38
  "twine>=6,<7",
39
+ "onnx>=1.16,<2",
40
+ "onnxruntime>=1.18,<2",
41
  ]
42
 
43
  [tool.setuptools.packages.find]
src/gnn4colliders/export/onnx.py CHANGED
@@ -106,23 +106,30 @@ def inputs_from_graph_batch(batch: Any) -> RootGNNExportInputs:
106
  def _mean_by_group(
107
  values: torch.Tensor, groups: torch.Tensor, count: int
108
  ) -> torch.Tensor:
109
- result = values.new_zeros((count, values.shape[1]))
110
- if values.shape[0]:
111
- result = result.index_add(0, groups, values)
112
- sizes = values.new_zeros((count, 1)).index_add(
113
- 0, groups, values.new_ones((values.shape[0], 1))
114
- )
115
- result = result / sizes.clamp_min(1)
116
- return result
117
 
118
 
119
  def _sum_by_group(
120
  values: torch.Tensor, groups: torch.Tensor, count: int
121
  ) -> torch.Tensor:
122
- result = values.new_zeros((count, values.shape[1]))
123
- if values.shape[0]:
124
- result = result.index_add(0, groups, values)
125
- return result
 
 
 
 
 
 
 
 
 
 
 
126
 
127
 
128
  class RootGNNExportAdapter(nn.Module):
@@ -169,9 +176,7 @@ class RootGNNExportAdapter(nn.Module):
169
  1,
170
  )
171
  )
172
- node_messages = node_h.new_zeros(node_h.shape).index_add(
173
- 0, edge_dst, edge_h
174
- )
175
  node_h = self.backbone.node_update(
176
  torch.cat((node_h, node_messages, global_h[node_batch]), 1)
177
  )
 
106
  def _mean_by_group(
107
  values: torch.Tensor, groups: torch.Tensor, count: int
108
  ) -> torch.Tensor:
109
+ membership = _group_membership(groups, count, values)
110
+ result = membership @ values
111
+ sizes = membership.sum(dim=1, keepdim=True)
112
+ return result / sizes.clamp_min(1)
 
 
 
 
113
 
114
 
115
  def _sum_by_group(
116
  values: torch.Tensor, groups: torch.Tensor, count: int
117
  ) -> torch.Tensor:
118
+ return _group_membership(groups, count, values) @ values
119
+
120
+
121
+ def _group_membership(
122
+ groups: torch.Tensor, count: int, values: torch.Tensor
123
+ ) -> torch.Tensor:
124
+ """Return a dense group-membership matrix for export-safe reduction.
125
+
126
+ ``index_add`` is efficient in native PyTorch but exports to ONNX scatter
127
+ operations whose behavior for duplicate indices is not reliable. A
128
+ boolean membership matrix has unambiguous reduction semantics for the
129
+ repeated node/edge group IDs used by batched graphs.
130
+ """
131
+ labels = torch.arange(count, device=groups.device).unsqueeze(1)
132
+ return (labels == groups.unsqueeze(0)).to(dtype=values.dtype)
133
 
134
 
135
  class RootGNNExportAdapter(nn.Module):
 
176
  1,
177
  )
178
  )
179
+ node_messages = _sum_by_group(edge_h, edge_dst, node_h.shape[0])
 
 
180
  node_h = self.backbone.node_update(
181
  torch.cat((node_h, node_messages, global_h[node_batch]), 1)
182
  )
uv.lock CHANGED
@@ -239,6 +239,8 @@ root-gnn = [
239
  [package.dev-dependencies]
240
  dev = [
241
  { name = "matplotlib", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
 
 
242
  { name = "pytest", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
243
  { name = "pytest-cov", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
244
  { name = "ruff", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
@@ -262,6 +264,8 @@ provides-extras = ["root-gnn", "onnx"]
262
  [package.metadata.requires-dev]
263
  dev = [
264
  { name = "matplotlib", specifier = ">=3.8,<4" },
 
 
265
  { name = "pytest", specifier = ">=8" },
266
  { name = "pytest-cov", specifier = ">=5" },
267
  { name = "ruff", specifier = ">=0.6" },
 
239
  [package.dev-dependencies]
240
  dev = [
241
  { name = "matplotlib", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
242
+ { name = "onnx", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
243
+ { name = "onnxruntime", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
244
  { name = "pytest", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
245
  { name = "pytest-cov", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
246
  { name = "ruff", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
 
264
  [package.metadata.requires-dev]
265
  dev = [
266
  { name = "matplotlib", specifier = ">=3.8,<4" },
267
+ { name = "onnx", specifier = ">=1.16,<2" },
268
+ { name = "onnxruntime", specifier = ">=1.18,<2" },
269
  { name = "pytest", specifier = ">=8" },
270
  { name = "pytest-cov", specifier = ">=5" },
271
  { name = "ruff", specifier = ">=0.6" },