Aggregation Layers
The k3_node.layers.aggr module provides 26 basic, statistical, scaled, and neural aggregation operators for neighborhood messaging and graph readout.
Aggregation Base Class
k3_node.layers.aggr.Aggregation
Bases: Layer
An abstract base class for implementing custom aggregations.
reduce(x, index=None, ptr=None, dim_size=None, dim=-2, reduce='sum')
Reduces features along groups specified by index or ptr.
reset_parameters()
Resets all learnable parameters of the module.
Basic Aggregations
SumAggregation
k3_node.layers.aggr.SumAggregation
Bases: Aggregation
An aggregation operator that sums up features across a set of elements.
Example
import numpy as np
from k3_node.layers import SumAggregation
x = np.random.rand(10, 8).astype("float32") # 10 nodes with 8 features each
index = np.repeat([0, 1], 5) # aggregate nodes 0-4 into set 0 and nodes 5-9 into set 1
aggr = SumAggregation()
out = aggr(x, index=index, dim_size=2)
print(tuple(out.shape)) # (2, 8)
MeanAggregation
k3_node.layers.aggr.MeanAggregation
Bases: Aggregation
An aggregation operator that averages features across a set of elements.
Example
import numpy as np
from k3_node.layers import MeanAggregation
x = np.random.rand(10, 8).astype("float32") # 10 nodes with 8 features each
index = np.repeat([0, 1], 5) # aggregate nodes 0-4 into set 0 and nodes 5-9 into set 1
aggr = MeanAggregation()
out = aggr(x, index=index, dim_size=2)
print(tuple(out.shape)) # (2, 8)
MaxAggregation
k3_node.layers.aggr.MaxAggregation
Bases: Aggregation
An aggregation operator that takes the feature-wise maximum across a set of elements.
Example
import numpy as np
from k3_node.layers import MaxAggregation
x = np.random.rand(10, 8).astype("float32") # 10 nodes with 8 features each
index = np.repeat([0, 1], 5) # aggregate nodes 0-4 into set 0 and nodes 5-9 into set 1
aggr = MaxAggregation()
out = aggr(x, index=index, dim_size=2)
print(tuple(out.shape)) # (2, 8)
MinAggregation
k3_node.layers.aggr.MinAggregation
Bases: Aggregation
An aggregation operator that takes the feature-wise minimum across a set of elements.
Example
import numpy as np
from k3_node.layers import MinAggregation
x = np.random.rand(10, 8).astype("float32") # 10 nodes with 8 features each
index = np.repeat([0, 1], 5) # aggregate nodes 0-4 into set 0 and nodes 5-9 into set 1
aggr = MinAggregation()
out = aggr(x, index=index, dim_size=2)
print(tuple(out.shape)) # (2, 8)
MulAggregation
k3_node.layers.aggr.MulAggregation
Bases: Aggregation
An aggregation operator that multiplies features across a set of elements.
Example
import numpy as np
from k3_node.layers import MulAggregation
x = np.random.rand(10, 8).astype("float32") # 10 nodes with 8 features each
index = np.repeat([0, 1], 5) # aggregate nodes 0-4 into set 0 and nodes 5-9 into set 1
aggr = MulAggregation()
out = aggr(x, index=index, dim_size=2)
print(tuple(out.shape)) # (2, 8)
Statistical & Scaled Aggregations
SoftmaxAggregation
k3_node.layers.aggr.SoftmaxAggregation
Bases: Aggregation
The softmax aggregation operator based on a temperature term.
Example
import numpy as np
from k3_node.layers import SoftmaxAggregation
x = np.random.rand(10, 8).astype("float32") # 10 nodes with 8 features each
index = np.repeat([0, 1], 5) # aggregate nodes 0-4 into set 0 and nodes 5-9 into set 1
aggr = SoftmaxAggregation(learn=True)
out = aggr(x, index=index, dim_size=2)
print(tuple(out.shape)) # (2, 8)
PowerMeanAggregation
k3_node.layers.aggr.PowerMeanAggregation
Bases: Aggregation
The powermean aggregation operator based on a power term.
Example
import numpy as np
from k3_node.layers import PowerMeanAggregation
x = np.random.rand(10, 8).astype("float32") # 10 nodes with 8 features each
index = np.repeat([0, 1], 5) # aggregate nodes 0-4 into set 0 and nodes 5-9 into set 1
aggr = PowerMeanAggregation(learn=True)
out = aggr(x, index=index, dim_size=2)
print(tuple(out.shape)) # (2, 8)
StdAggregation
k3_node.layers.aggr.StdAggregation
Bases: Aggregation
An aggregation operator that takes the feature-wise standard deviation across a set of elements.
Example
import numpy as np
from k3_node.layers import StdAggregation
x = np.random.rand(10, 8).astype("float32") # 10 nodes with 8 features each
index = np.repeat([0, 1], 5) # aggregate nodes 0-4 into set 0 and nodes 5-9 into set 1
aggr = StdAggregation()
out = aggr(x, index=index, dim_size=2)
print(tuple(out.shape)) # (2, 8)
VarAggregation
k3_node.layers.aggr.VarAggregation
Bases: Aggregation
An aggregation operator that takes the feature-wise variance across a set of elements.
Example
import numpy as np
from k3_node.layers import VarAggregation
x = np.random.rand(10, 8).astype("float32") # 10 nodes with 8 features each
index = np.repeat([0, 1], 5) # aggregate nodes 0-4 into set 0 and nodes 5-9 into set 1
aggr = VarAggregation()
out = aggr(x, index=index, dim_size=2)
print(tuple(out.shape)) # (2, 8)
MedianAggregation
k3_node.layers.aggr.MedianAggregation
Bases: QuantileAggregation
An aggregation operator that returns the feature-wise median of a set.
Example
import numpy as np
from k3_node.layers import MedianAggregation
x = np.random.rand(10, 8).astype("float32") # 10 nodes with 8 features each
index = np.repeat([0, 1], 5) # aggregate nodes 0-4 into set 0 and nodes 5-9 into set 1
aggr = MedianAggregation()
out = aggr(x, index=index, dim_size=2)
print(tuple(out.shape)) # (2, 8)
QuantileAggregation
k3_node.layers.aggr.QuantileAggregation
Bases: Aggregation
An aggregation operator that returns the feature-wise :math:q-th
quantile of a set :math:\mathcal{X}.
Example
import numpy as np
from k3_node.layers import QuantileAggregation
x = np.random.rand(10, 8).astype("float32") # 10 nodes with 8 features each
index = np.repeat([0, 1], 5) # aggregate nodes 0-4 into set 0 and nodes 5-9 into set 1
aggr = QuantileAggregation(q=0.75)
out = aggr(x, index=index, dim_size=2)
print(tuple(out.shape)) # (2, 8)
DegreeScalerAggregation
k3_node.layers.aggr.DegreeScalerAggregation
Bases: Aggregation
Combines one or more aggregators and transforms its output with one or
more scalers as introduced in the "Principal Neighbourhood Aggregation for
Graph Nets" <https://arxiv.org/abs/2004.05718>_ paper.
Example
import numpy as np
from k3_node.layers import DegreeScalerAggregation
x = np.random.rand(10, 8).astype("float32") # 10 nodes with 8 features each
index = np.repeat([0, 1], 5) # aggregate nodes 0-4 into set 0 and nodes 5-9 into set 1
deg = np.array([0, 3, 5, 2]) # in-degree histogram of the training graphs
aggr = DegreeScalerAggregation(aggr=["mean", "max"], scaler=["identity", "amplification"], deg=deg)
out = aggr(x, index=index, dim_size=2)
print(tuple(out.shape)) # (2, 32): 2 aggregators x 2 scalers x 8 features
Neural & Multi-Aggregations
MultiAggregation
k3_node.layers.aggr.MultiAggregation
Bases: Aggregation
Performs aggregations with one or more aggregators and combines
aggregated results, as described in the "Principal Neighbourhood
Aggregation for Graph Nets" <https://arxiv.org/abs/2004.05718> and
"Adaptive Filters and Aggregator Fusion for Efficient Graph Convolutions"
<https://arxiv.org/abs/2104.01481> papers.
Example
import numpy as np
from k3_node.layers import MultiAggregation
x = np.random.rand(10, 8).astype("float32") # 10 nodes with 8 features each
index = np.repeat([0, 1], 5) # aggregate nodes 0-4 into set 0 and nodes 5-9 into set 1
aggr = MultiAggregation(aggrs=["sum", "mean", "max"])
out = aggr(x, index=index, dim_size=2)
print(tuple(out.shape)) # (2, 24)
AttentionalAggregation
k3_node.layers.aggr.AttentionalAggregation
Bases: Aggregation
The soft attention aggregation layer from the "Graph Matching Networks
for Learning the Similarity of Graph Structured Objects"
<https://arxiv.org/abs/1904.12787>_ paper.
Example
import numpy as np
import keras
from k3_node.layers import AttentionalAggregation
x = np.random.rand(10, 8).astype("float32") # 10 nodes with 8 features each
index = np.repeat([0, 1], 5) # aggregate nodes 0-4 into set 0 and nodes 5-9 into set 1
aggr = AttentionalAggregation(gate_nn=keras.layers.Dense(1), nn=keras.layers.Dense(16))
out = aggr(x, index=index, dim_size=2) # attention-weighted sum per set
print(tuple(out.shape)) # (2, 16)
Set2Set
k3_node.layers.aggr.Set2Set
Bases: Aggregation
The Set2Set aggregation operator based on iterative content-based
attention, as described in the "Order Matters: Sequence to sequence for
Sets" <https://arxiv.org/abs/1511.06391>_ paper.
Example
import numpy as np
from k3_node.layers import Set2Set
x = np.random.rand(10, 8).astype("float32") # 10 nodes with 8 features each
index = np.repeat([0, 1], 5) # aggregate nodes 0-4 into set 0 and nodes 5-9 into set 1
aggr = Set2Set(in_channels=8, processing_steps=2)
out = aggr(x, index=index, dim_size=2)
print(tuple(out.shape)) # (2, 16)
DeepSetsAggregation
k3_node.layers.aggr.DeepSetsAggregation
Bases: Aggregation
Performs Deep Sets aggregation in which the elements to aggregate are
first transformed by a Multi-Layer Perceptron (MLP)
:math:\phi_{\mathbf{\Theta}}, summed, and then transformed by another MLP
:math:\rho_{\mathbf{\Theta}}.
Example
import numpy as np
import keras
from k3_node.layers import DeepSetsAggregation
x = np.random.rand(10, 8).astype("float32") # 10 nodes with 8 features each
index = np.repeat([0, 1], 5) # aggregate nodes 0-4 into set 0 and nodes 5-9 into set 1
aggr = DeepSetsAggregation(local_nn=keras.layers.Dense(16), global_nn=keras.layers.Dense(16))
out = aggr(x, index=index, dim_size=2)
print(tuple(out.shape)) # (2, 16)
MLPAggregation
k3_node.layers.aggr.MLPAggregation
Bases: Aggregation
Performs MLP aggregation in which the elements to aggregate are flattened into a single vectorial representation, and are then processed by a Multi-Layer Perceptron (MLP).
Example
import numpy as np
from k3_node.layers import MLPAggregation
x = np.random.rand(10, 8).astype("float32") # 10 nodes with 8 features each
index = np.repeat([0, 1], 5) # aggregate nodes 0-4 into set 0 and nodes 5-9 into set 1
aggr = MLPAggregation(in_channels=8, out_channels=16, max_num_elements=5)
out = aggr(x, index=index, dim_size=2)
print(tuple(out.shape)) # (2, 16)
LSTMAggregation
k3_node.layers.aggr.LSTMAggregation
Bases: Aggregation
Performs LSTM-style aggregation in which the elements to aggregate are
interpreted as a sequence, as described in the "Inductive Representation
Learning on Large Graphs" <https://arxiv.org/abs/1706.02216>_ paper.
Example
import numpy as np
from k3_node.layers import LSTMAggregation
x = np.random.rand(10, 8).astype("float32") # 10 nodes with 8 features each
index = np.repeat([0, 1], 5) # aggregate nodes 0-4 into set 0 and nodes 5-9 into set 1
aggr = LSTMAggregation(in_channels=8, out_channels=16)
out = aggr(x, index=index, dim_size=2)
print(tuple(out.shape)) # (2, 16)
GRUAggregation
k3_node.layers.aggr.GRUAggregation
Bases: Aggregation
Performs GRU aggregation in which the elements to aggregate are
interpreted as a sequence, as described in the "Graph Neural Networks
with Adaptive Readouts" <https://arxiv.org/abs/2211.04952>_ paper.
Example
import numpy as np
from k3_node.layers import GRUAggregation
x = np.random.rand(10, 8).astype("float32") # 10 nodes with 8 features each
index = np.repeat([0, 1], 5) # aggregate nodes 0-4 into set 0 and nodes 5-9 into set 1
aggr = GRUAggregation(in_channels=8, out_channels=16)
out = aggr(x, index=index, dim_size=2)
print(tuple(out.shape)) # (2, 16)
SetTransformerAggregation
k3_node.layers.aggr.SetTransformerAggregation
Bases: Aggregation
Performs "Set Transformer" aggregation in which the elements to
aggregate are processed by multi-head attention blocks, as described in
the "Graph Neural Networks with Adaptive Readouts"
<https://arxiv.org/abs/2211.04952>_ paper.
Example
import numpy as np
from k3_node.layers import SetTransformerAggregation
x = np.random.rand(10, 8).astype("float32") # 10 nodes with 8 features each
index = np.repeat([0, 1], 5) # aggregate nodes 0-4 into set 0 and nodes 5-9 into set 1
aggr = SetTransformerAggregation(channels=8, num_seed_points=2)
out = aggr(x, index=index, dim_size=2)
print(tuple(out.shape)) # (2, 16)
GraphMultisetTransformer
k3_node.layers.aggr.GraphMultisetTransformer
Bases: Aggregation
The Graph Multiset Transformer pooling operator from the
"Accurate Learning of Graph Representations
with Graph Multiset Pooling" <https://arxiv.org/abs/2102.11533>_ paper.
Example
import numpy as np
from k3_node.layers import GraphMultisetTransformer
x = np.random.rand(10, 8).astype("float32") # 10 nodes with 8 features each
index = np.repeat([0, 1], 5) # aggregate nodes 0-4 into set 0 and nodes 5-9 into set 1
aggr = GraphMultisetTransformer(channels=8, k=2)
out = aggr(x, index=index, dim_size=2)
print(tuple(out.shape)) # (2, 8)
SortAggregation
k3_node.layers.aggr.SortAggregation
Bases: Aggregation
The pooling operator from the "An End-to-End Deep Learning
Architecture for Graph Classification"
<https://www.cse.wustl.edu/~muhan/papers/AAAI_2018_DGCNN.pdf>_ paper,
where node features are sorted in descending order based on their last
feature channel. The first :math:k nodes form the output of the layer.
Example
import numpy as np
from k3_node.layers import SortAggregation
x = np.random.rand(10, 8).astype("float32") # 10 nodes with 8 features each
index = np.repeat([0, 1], 5) # aggregate nodes 0-4 into set 0 and nodes 5-9 into set 1
aggr = SortAggregation(k=2)
out = aggr(x, index=index, dim_size=2)
print(tuple(out.shape)) # (2, 16)
VariancePreservingAggregation
k3_node.layers.aggr.VariancePreservingAggregation
Bases: Aggregation
Performs the Variance Preserving Aggregation (VPA) from the "GNN-VPA:
A Variance-Preserving Aggregation Strategy for Graph Neural Networks"
<https://arxiv.org/abs/2403.04747>_ paper.
Example
import numpy as np
from k3_node.layers import VariancePreservingAggregation
x = np.random.rand(10, 8).astype("float32") # 10 nodes with 8 features each
index = np.repeat([0, 1], 5) # aggregate nodes 0-4 into set 0 and nodes 5-9 into set 1
aggr = VariancePreservingAggregation()
out = aggr(x, index=index, dim_size=2)
print(tuple(out.shape)) # (2, 8)
PatchTransformerAggregation
k3_node.layers.aggr.PatchTransformerAggregation
Bases: Aggregation
Performs patch transformer aggregation in which the elements to aggregate are processed by multi-head attention blocks across patches.
Example
import numpy as np
from k3_node.layers import PatchTransformerAggregation
x = np.random.rand(10, 8).astype("float32") # 10 nodes with 8 features each
index = np.repeat([0, 1], 5) # aggregate nodes 0-4 into set 0 and nodes 5-9 into set 1
aggr = PatchTransformerAggregation(in_channels=8, out_channels=16, patch_size=2, hidden_channels=8)
out = aggr(x, index=index, dim_size=2)
print(tuple(out.shape)) # (2, 16)
LCMAggregation
k3_node.layers.aggr.LCMAggregation
Bases: Aggregation
The Learnable Commutative Monoid aggregation from the
"Learnable Commutative Monoids for Graph Neural Networks"
<https://arxiv.org/abs/2212.08541>_ paper.
Example
import numpy as np
from k3_node.layers import LCMAggregation
x = np.random.rand(10, 8).astype("float32") # 10 nodes with 8 features each
index = np.repeat([0, 1], 5) # aggregate nodes 0-4 into set 0 and nodes 5-9 into set 1
aggr = LCMAggregation(in_channels=8, out_channels=16)
out = aggr(x, index=index, dim_size=2)
print(tuple(out.shape)) # (2, 16)
EquilibriumAggregation
k3_node.layers.aggr.EquilibriumAggregation
Bases: Aggregation
The equilibrium aggregation layer from the "Equilibrium Aggregation:
Encoding Sets via Optimization" <https://arxiv.org/abs/2202.12795>_ paper.
Example
import numpy as np
from k3_node.layers import EquilibriumAggregation
x = np.random.rand(10, 8).astype("float32") # 10 nodes with 8 features each
index = np.repeat([0, 1], 5) # aggregate nodes 0-4 into set 0 and nodes 5-9 into set 1
aggr = EquilibriumAggregation(in_channels=8, out_channels=16, num_layers=[8])
out = aggr(x, index=index, dim_size=2)
print(tuple(out.shape)) # (2, 16)
FusedAggregation
k3_node.layers.aggr.FusedAggregation
Bases: Aggregation
Helper class to fuse computation of multiple aggregations together.
Example
import numpy as np
from k3_node.layers import FusedAggregation
x = np.random.rand(10, 8).astype("float32") # 10 nodes with 8 features each
index = np.repeat([0, 1], 5) # aggregate nodes 0-4 into set 0 and nodes 5-9 into set 1
aggr = FusedAggregation(aggrs=["sum", "mean", "max"])
outs = aggr(x, index=index, dim_size=2) # one result per aggregation, computed together
print(len(outs), tuple(outs[0].shape)) # 3 (2, 8)