Skip to content

Convolution Layers

The k3_node.layers.conv module provides over 65 spatial, spectral, relational, and point-cloud graph convolution layers.


Message Passing Base Class

k3_node.layers.conv.MessagePassing

Bases: Layer

Base class for creating Message Passing Neural Networks (MPNNs).

Parameters:

Name Type Description Default
aggr Union[str, List[str], Aggregation, None]

The aggregation scheme to use, such as "add", "sum", "mean", "min", "max", "mul", or an instance of :class:~k3_node.layers.aggr.Aggregation. (default: "add")

'add'
flow str

The direction of message passing ("source_to_target" or "target_to_source"). (default: "source_to_target")

'source_to_target'
node_dim int

The axis along which to index node features. (default: -2)

-2
decomposed_layers int

Number of decomposed layers for memory-efficient aggregation. (default: 1)

1
Example
import numpy as np
import keras
from k3_node.layers import MessagePassing

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

# A minimal custom layer: average the neighbors' features, then transform them.
class MeanConv(MessagePassing):
    def __init__(self, units, **kwargs):
        super().__init__(aggr="mean", **kwargs)
        self.dense = keras.layers.Dense(units)

    def call(self, x, edge_index):
        return self.dense(self.propagate(edge_index, x=x))

    def message(self, x_j):
        return x_j  # features of the source node of every edge


layer = MeanConv(16)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 16)

aggregate(inputs=None, index=None, ptr=None, dim_size=None, **kwargs)

Aggregates messages from neighbors as given by :obj:index.

call(inputs, edge_index=None, edge_attr=None, **kwargs)

Default call handler supporting both (x, edge_index) and legacy (inputs,) tuples.

edge_update(**kwargs)

Computes or updates edge attributes.

edge_updater(edge_index, size=None, **kwargs)

Computes or updates edge-level representations.

message(x=None, x_j=None, **kwargs)

Constructs messages from node :math:j to node :math:i.

propagate(*args, **kwargs)

The initial call to start propagating messages.

update(embeddings=None, **kwargs)

Updates node embeddings.


Core Graph Convolutions

GCNConv

k3_node.layers.conv.GCNConv

Bases: MessagePassing

The graph convolutional operator from the "Semi-supervised Classification with Graph Convolutional Networks" <https://arxiv.org/abs/1609.02907>_ paper.

.. math:: \mathbf{X}^{\prime} = \mathbf{\hat{D}}^{-1/2} \mathbf{\hat{A}} \mathbf{\hat{D}}^{-1/2} \mathbf{X} \mathbf{\Theta}

Parameters:

Name Type Description Default
in_channels int

Size of each input sample.

required
out_channels int

Size of each output sample.

required
improved bool

If set to :obj:True, the layer computes :math:\mathbf{\hat{A}} = \mathbf{A} + 2 \mathbf{I}. (default: :obj:False)

False
cached bool

If set to :obj:True, the layer will cache the computation of :math:\mathbf{\hat{D}}^{-1/2} \mathbf{\hat{A}} \mathbf{\hat{D}}^{-1/2}. (default: :obj:False)

False
add_self_loops bool

If set to :obj:False, will not add self-loops to the input graph. (default: :obj:True)

True
normalize bool

Whether to add self-loops and compute symmetric normalization coefficients on the fly. (default: :obj:True)

True
bias bool

If set to :obj:False, the layer will not learn an additive bias. (default: :obj:True)

True
Example
import numpy as np
from k3_node.layers import GCNConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = GCNConv(in_channels=8, out_channels=16)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 16)

SAGEConv

k3_node.layers.conv.SAGEConv

Bases: MessagePassing

The GraphSAGE operator from the "Inductive Representation Learning on Large Graphs" <https://arxiv.org/abs/1706.02216>_ paper.

Parameters:

Name Type Description Default
in_channels Union[int, Tuple[int, int], None]

Size of each input sample, or a tuple for bipartite graphs.

required
out_channels Optional[int]

Size of each output sample.

None
aggr Optional[Union[str, List[str], Aggregation]]

The aggregation scheme to use ("mean", "max", "lstm", etc.). (default: "mean")

'mean'
normalize bool

If set to :obj:True, output features will be :math:\ell_2-normalized. (default: :obj:False)

False
root_weight bool

If set to :obj:False, the layer will not add the transformed root node features. (default: :obj:True)

True
project bool

If set to :obj:True, the layer will apply a linear transformation followed by an activation to source node features. (default: :obj:False)

False
bias bool

If set to :obj:False, the layer will not learn an additive bias. (default: :obj:True)

True
Example
import numpy as np
from k3_node.layers import SAGEConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = SAGEConv(in_channels=8, out_channels=16)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 16)

GATConv

k3_node.layers.conv.GATConv

Bases: MessagePassing

The graph attentional operator from the "Graph Attention Networks" <https://arxiv.org/abs/1710.10903>_ paper.

Parameters:

Name Type Description Default
in_channels Union[int, Tuple[int, int]]

Size of each input sample, or a tuple for bipartite graphs.

required
out_channels int

Size of each output sample.

required
heads int

Number of multi-head-attentions. (default: 1)

1
concat bool

If set to :obj:False, the multi-head-attentions are averaged instead of concatenated. (default: True)

True
negative_slope float

LeakyReLU angle of the negative slope. (default: 0.2)

0.2
dropout float

Dropout probability of the normalized attention coefficients. (default: 0.0)

0.0
add_self_loops bool

If set to :obj:False, will not add self-loops to the input graph. (default: True)

True
edge_dim Optional[int]

Edge feature dimensionality (in case there are any). (default: :obj:None)

None
fill_value Union[float, str]

The way to generate edge features of self-loops (default: "mean")

'mean'
bias bool

If set to :obj:False, the layer will not learn an additive bias. (default: True)

True
share_weights bool

If set to :obj:True, the same matrix will be applied to the source and target node features. (default: False)

False
residual bool

If set to :obj:True, will compute residual connections. (default: False)

False
Example
import numpy as np
from k3_node.layers import GATConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = GATConv(in_channels=8, out_channels=16, heads=2)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 32)

GATv2Conv

k3_node.layers.conv.GATv2Conv

Bases: MessagePassing

The GATv2 operator from the "How Attentive are Graph Attention Networks?" <https://arxiv.org/abs/2105.14491>_ paper, which fixes the static attention problem of standard :class:~k3_node.layers.conv.GATConv.

Parameters:

Name Type Description Default
in_channels Union[int, Tuple[int, int]]

Size of each input sample, or a tuple for bipartite graphs.

required
out_channels int

Size of each output sample.

required
heads int

Number of multi-head-attentions. (default: 1)

1
concat bool

If set to :obj:False, the multi-head-attentions are averaged instead of concatenated. (default: True)

True
negative_slope float

LeakyReLU angle of the negative slope. (default: 0.2)

0.2
dropout float

Dropout probability of the normalized attention coefficients. (default: 0.0)

0.0
add_self_loops bool

If set to :obj:False, will not add self-loops to the input graph. (default: True)

True
edge_dim Optional[int]

Edge feature dimensionality (in case there are any). (default: :obj:None)

None
fill_value Union[float, str]

The way to generate edge features of self-loops (default: "mean")

'mean'
bias bool

If set to :obj:False, the layer will not learn an additive bias. (default: True)

True
share_weights bool

If set to :obj:True, the same matrix will be applied to the source and target node features. (default: False)

False
residual bool

If set to :obj:True, will compute residual connections. (default: False)

False
Example
import numpy as np
from k3_node.layers import GATv2Conv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = GATv2Conv(in_channels=8, out_channels=16, heads=2)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 32)

TransformerConv

k3_node.layers.conv.TransformerConv

Bases: MessagePassing

The graph transformer operator from the "Masked Label Prediction: Unified Meta-Learning on Graph Neural Networks" <https://arxiv.org/abs/2009.03509>_ paper.

Parameters:

Name Type Description Default
in_channels Union[int, Tuple[int, int]]

Size of each input sample, or a tuple for bipartite graphs.

required
out_channels int

Size of each output sample.

required
heads int

Number of multi-head-attentions. (default: 1)

1
concat bool

If set to :obj:False, the multi-head-attentions are averaged instead of concatenated. (default: True)

True
beta bool

If set to :obj:True, will use a gated residual connection. (default: False)

False
dropout float

Dropout probability of the normalized attention coefficients. (default: 0.0)

0.0
edge_dim Optional[int]

Edge feature dimensionality (in case there are any). (default: :obj:None)

None
bias bool

If set to :obj:False, the layer will not learn an additive bias. (default: True)

True
root_weight bool

If set to :obj:False, the layer will not add the transformed root node features. (default: True)

True
Example
import numpy as np
from k3_node.layers import TransformerConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = TransformerConv(in_channels=8, out_channels=16, heads=2)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 32)

GINConv

k3_node.layers.conv.GINConv

Bases: MessagePassing

The graph isomorphism operator from the "How Powerful are Graph Neural Networks?" <https://arxiv.org/abs/1810.00826>_ paper.

Parameters:

Name Type Description Default
nn Union[Callable, int]

A neural network :math:h_{\mathbf{\Theta}} that maps node features to new embeddings (e.g. a :class:keras.Sequential or callable). Also accepts an integer channels for backward compatibility.

required
eps float

(Initial) :math:\epsilon-value. (default: 0.0)

0.0
train_eps bool

If set to :obj:True, :math:\epsilon will be a learnable parameter. (default: False)

False
Example
import numpy as np
import keras
from k3_node.layers import GINConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

mlp = keras.Sequential([keras.layers.Dense(16, activation="relu"), keras.layers.Dense(16)])
layer = GINConv(mlp)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 16)

GINEConv

k3_node.layers.conv.GINEConv

Bases: MessagePassing

The modified :class:GINConv operator from the "Strategies for Pre-training Graph Neural Networks" <https://arxiv.org/abs/1905.12265>_ paper, which is able to incorporate edge features into aggregation.

Parameters:

Name Type Description Default
nn Callable

A neural network :math:h_{\mathbf{\Theta}}.

required
eps float

(Initial) :math:\epsilon-value. (default: 0.0)

0.0
train_eps bool

If set to :obj:True, :math:\epsilon will be a learnable parameter. (default: False)

False
edge_dim Optional[int]

Edge feature dimensionality. (default: :obj:None)

None
Example
import numpy as np
import keras
from k3_node.layers import GINEConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges
edge_attr = np.random.rand(30, 3).astype("float32")  # 3 features per edge

mlp = keras.Sequential([keras.layers.Dense(16, activation="relu"), keras.layers.Dense(16)])
layer = GINEConv(mlp, edge_dim=3)
out = layer(x, edge_index, edge_attr)
print(tuple(out.shape))  # (10, 16)

ChebConv

k3_node.layers.conv.ChebConv

Bases: MessagePassing

The Chebyshev spectral graph convolutional operator from the "Convolutional Neural Networks on Graphs with Fast Localized Spectral Filtering" <https://arxiv.org/abs/1606.09375>_ paper.

Parameters:

Name Type Description Default
in_channels int

Size of each input sample.

required
out_channels int

Size of each output sample.

required
K int

Chebyshev filter size :math:K.

required
normalization Optional[str]

The normalization scheme for the graph Laplacian ("sym", "rw" or :obj:None). (default: "sym")

'sym'
bias bool

If set to :obj:False, the layer will not learn an additive bias. (default: "True")

True
Example
import numpy as np
from k3_node.layers import ChebConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = ChebConv(in_channels=8, out_channels=16, K=2)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 16)

AGNNConv

k3_node.layers.conv.AGNNConv

Bases: MessagePassing

The graph attentional propagation layer from the "Attention-based Graph Neural Network for Semi-Supervised Learning" <https://arxiv.org/abs/1803.03735>_ paper.

Example
import numpy as np
from k3_node.layers import AGNNConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = AGNNConv(requires_grad=True)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 8)

TAGConv

k3_node.layers.conv.TAGConv

Bases: MessagePassing

The topology adaptive graph convolutional operator from the "Topology Adaptive Graph Convolutional Networks" <https://arxiv.org/abs/1710.10370>_ paper.

Parameters:

Name Type Description Default
in_channels int

Size of each input sample.

required
out_channels int

Size of each output sample.

required
K int

Number of hops :math:K. (default: 3)

3
bias bool

If set to :obj:False, the layer will not learn an additive bias. (default: True)

True
normalize bool

Whether to apply symmetric normalization. (default: True)

True
Example
import numpy as np
from k3_node.layers import TAGConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = TAGConv(in_channels=8, out_channels=16, K=2)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 16)

ARMAConv

k3_node.layers.conv.ARMAConv

Bases: MessagePassing

The ARMA graph convolutional operator from the "Graph Neural Networks with Convolutional ARMA Filters" <https://arxiv.org/abs/1901.01343>_ paper.

Example
import numpy as np
from k3_node.layers import ARMAConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = ARMAConv(in_channels=8, out_channels=16, num_stacks=1, num_layers=1)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 16)

SGConv

k3_node.layers.conv.SGConv

Bases: MessagePassing

The simple graph convolutional operator from the "Simplifying Graph Convolutional Networks" <https://arxiv.org/abs/1902.07153>_ paper.

Parameters:

Name Type Description Default
in_channels int

Size of each input sample.

required
out_channels int

Size of each output sample.

required
K int

Number of hops :math:K. (default: 1)

1
cached bool

If set to :obj:True, the layer will cache the computation of :math:\mathbf{\hat{D}}^{-1/2} \mathbf{\hat{A}} \mathbf{\hat{D}}^{-1/2}. (default: False)

False
add_self_loops bool

If set to :obj:False, will not add self-loops. (default: True)

True
bias bool

If set to :obj:False, the layer will not learn an additive bias. (default: True)

True
Example
import numpy as np
from k3_node.layers import SGConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = SGConv(in_channels=8, out_channels=16, K=2)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 16)

SSGConv

k3_node.layers.conv.SSGConv

Bases: MessagePassing

The simple spectral graph convolutional operator from the "Simple Spectral Graph Convolution" <https://arxiv.org/abs/2109.07191>_ paper.

Parameters:

Name Type Description Default
in_channels int

Size of each input sample.

required
out_channels int

Size of each output sample.

required
alpha float

Teleport probability :math:\alpha.

required
K int

Number of hops :math:K. (default: 1)

1
cached bool

If set to :obj:True, the layer will cache normalization coefficients. (default: False)

False
add_self_loops bool

If set to :obj:False, will not add self-loops. (default: True)

True
bias bool

If set to :obj:False, the layer will not learn an additive bias. (default: True)

True
Example
import numpy as np
from k3_node.layers import SSGConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = SSGConv(in_channels=8, out_channels=16, alpha=0.1, K=2)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 16)

APPNP

k3_node.layers.conv.APPNP

Bases: MessagePassing

The approximate personalized propagation of neural predictions (APPNP) operator from the "Predict then Propagate: Combining Neural Networks with Personalized PageRank for Classification on Graphs" <https://arxiv.org/abs/1810.05997>_ paper.

Parameters:

Name Type Description Default
K int

Number of iterations :math:K.

required
alpha float

Teleport probability :math:\alpha.

required
dropout float

Dropout probability of edges or features during propagation. (default: 0.0)

0.0
cached bool

If set to :obj:True, the layer will cache the computation of normalization coefficients. (default: False)

False
add_self_loops bool

If set to :obj:False, will not add self-loops. (default: True)

True
normalize bool

Whether to apply symmetric normalization. (default: True)

True
Example
import numpy as np
from k3_node.layers import APPNP

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = APPNP(K=2, alpha=0.1)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 8)

APPNPConv

k3_node.layers.conv.APPNPConv

Bases: Conv

`k3_node.layers.APPNPConv`
Implementation of Approximate Personalized Propagation of Neural Predictions

Args:
    channels: The number of output channels.
    alpha: The teleport probability.
    propagations: The number of propagation steps.
    mlp_hidden: A list of hidden channels for the MLP.
    mlp_activation: The activation function to use in the MLP.
    dropout_rate: The dropout rate for the MLP.
    activation: The activation function to use in the layer.
    use_bias: Whether to add a bias to the linear transformation.
    kernel_initializer: Initializer for the `kernel` weights matrix.
    bias_initializer: Initializer for the bias vector.
    kernel_regularizer: Regularizer for the `kernel` weights matrix.
    bias_regularizer: Regularizer for the bias vector.
    activity_regularizer: Regularizer for the output.
    kernel_constraint: Constraint for the `kernel` weights matrix.
    bias_constraint: Constraint for the bias vector.
    **kwargs: Additional keyword arguments.
Example
import numpy as np
from k3_node.layers import APPNPConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = APPNPConv(channels=16, alpha=0.1, propagations=2)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 16)

PNAConv

k3_node.layers.conv.PNAConv

Bases: MessagePassing

The Principal Neighbourhood Aggregation graph convolutional operator from the "Principal Neighbourhood Aggregation for Graph Nets" <https://arxiv.org/abs/2004.05718>_ paper.

Example
import numpy as np
from k3_node.layers import PNAConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

deg = np.array([0, 2, 4, 3, 1])  # in-degree histogram of the training graphs
layer = PNAConv(in_channels=8, out_channels=16, aggregators=["mean", "max", "min", "std"],
                scalers=["identity", "amplification"], deg=deg)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 16)

get_degree_histogram(graphs) staticmethod

Returns the histogram of in-degrees over graphs (a dataset, a list of graphs or a loader), which PNA uses to normalize its degree scalers: deg[d] is the number of nodes with d incoming edges.

GENConv

k3_node.layers.conv.GENConv

Bases: MessagePassing

The generalized graph convolution operator from the "DeeperGCN: All You Need to Train Deeper GCNs" <https://arxiv.org/abs/2006.07739>_ paper.

Example
import numpy as np
from k3_node.layers import GENConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges
edge_attr = np.random.rand(30, 3).astype("float32")  # 3 features per edge

layer = GENConv(in_channels=8, out_channels=16, edge_dim=3)
out = layer(x, edge_index, edge_attr)
print(tuple(out.shape))  # (10, 16)

GatedGraphConv

k3_node.layers.conv.GatedGraphConv

Bases: MessagePassing

k3_node.layers.GatedGraphConv

Implementation of Gated Graph Convolution (GGC) layer

Parameters:

Name Type Description Default
channels

The number of output channels.

None
n_layers

The number of GGC layers to stack.

None
activation

Activation function to use.

None
use_bias

Whether to add a bias to the linear transformation.

True
kernel_initializer

Initializer for the kernel weights matrix.

'glorot_uniform'
bias_initializer

Initializer for the bias vector.

'zeros'
kernel_regularizer

Regularizer for the kernel weights matrix.

None
bias_regularizer

Regularizer for the bias vector.

None
activity_regularizer

Regularizer for the output.

None
kernel_constraint

Constraint for the kernel weights matrix.

None
bias_constraint

Constraint for the bias vector.

None
**kwargs

Additional arguments to pass to the MessagePassing superclass.

{}
Example
import numpy as np
from k3_node.layers import GatedGraphConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = GatedGraphConv(out_channels=16, num_layers=2)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 16)

ResGatedGraphConv

k3_node.layers.conv.ResGatedGraphConv

Bases: MessagePassing

The residual gated graph convolutional operator from the "Residual Gated Graph ConvNets" <https://arxiv.org/abs/1711.07553>_ paper.

Parameters:

Name Type Description Default
in_channels Union[int, Tuple[int, int]]

Size of each input sample, or a tuple for bipartite graphs.

required
out_channels int

Size of each output sample.

required
act Union[str, Callable]

Activation function :math:\sigma for gating. (default: "sigmoid")

'sigmoid'
edge_dim Optional[int]

Edge feature dimensionality. (default: :obj:None)

None
root_weight bool

If set to :obj:False, will not add transformed root features. (default: True)

True
bias bool

If set to :obj:False, will not learn an additive bias. (default: True)

True
Example
import numpy as np
from k3_node.layers import ResGatedGraphConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = ResGatedGraphConv(in_channels=8, out_channels=16)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 16)

SimpleConv

k3_node.layers.conv.SimpleConv

Bases: MessagePassing

A simple, parameter-free message passing operator.

Parameters:

Name Type Description Default
aggr Union[str, List[str], Aggregation, None]

The aggregation scheme to use ("sum", "mean", "min", "max", "mul"). (default: "sum")

'sum'
combine_root Optional[str]

The way to combine root node features with the aggregated output ("sum", "cat", "self_loop", or :obj:None). (default: :obj:None)

None
Example
import numpy as np
from k3_node.layers import SimpleConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = SimpleConv(aggr="mean")
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 8)

GraphConv

k3_node.layers.conv.GraphConv

Bases: MessagePassing

The graph neural network operator from the "Weisfeiler and Leman Go Neural: Higher-order Graph Neural Networks" <https://arxiv.org/abs/1810.02244>_ paper.

Parameters:

Name Type Description Default
in_channels Union[int, Tuple[int, int]]

Size of each input sample, or a tuple for bipartite graphs.

required
out_channels int

Size of each output sample.

required
aggr str

The aggregation scheme to use ("add", "mean", "max"). (default: "add")

'add'
bias bool

If set to :obj:False, the layer will not learn an additive bias. (default: "True")

True
Example
import numpy as np
from k3_node.layers import GraphConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = GraphConv(in_channels=8, out_channels=16)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 16)

MFConv

k3_node.layers.conv.MFConv

Bases: MessagePassing

The molecular fingerprint graph convolutional operator from the "Convolutional Networks on Graphs for Learning Molecular Fingerprints" <https://arxiv.org/abs/1509.09292>_ paper.

Parameters:

Name Type Description Default
in_channels Union[int, Tuple[int, int]]

Size of each input sample, or a tuple for bipartite graphs.

required
out_channels int

Size of each output sample.

required
max_degree int

The maximum degree of any node. (default: 10)

10
bias bool

If set to :obj:False, the layer will not learn an additive bias. (default: True)

True
Example
import numpy as np
from k3_node.layers import MFConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = MFConv(in_channels=8, out_channels=16)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 16)

Relational & Directed Convolutions

RGCNConv

k3_node.layers.conv.RGCNConv

Bases: MessagePassing

The relational graph convolutional operator from the "Modeling Relational Data with Graph Convolutional Networks" <https://arxiv.org/abs/1703.06103>_ paper.

Example
import numpy as np
from k3_node.layers import RGCNConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges
edge_type = np.random.randint(0, 3, size=(30,))  # relation type of each edge

layer = RGCNConv(in_channels=8, out_channels=16, num_relations=3)
out = layer(x, edge_index, edge_type)
print(tuple(out.shape))  # (10, 16)

FastRGCNConv

k3_node.layers.conv.FastRGCNConv

Bases: RGCNConv

See :class:RGCNConv.

Example
import numpy as np
from k3_node.layers import FastRGCNConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges
edge_type = np.random.randint(0, 3, size=(30,))  # relation type of each edge

layer = FastRGCNConv(in_channels=8, out_channels=16, num_relations=3)
out = layer(x, edge_index, edge_type)
print(tuple(out.shape))  # (10, 16)

RGATConv

k3_node.layers.conv.RGATConv

Bases: MessagePassing

The relational graph attentional operator from the "Relational Graph Attention Networks" <https://arxiv.org/abs/1904.05811>_ paper.

Example
import numpy as np
from k3_node.layers import RGATConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges
edge_type = np.random.randint(0, 3, size=(30,))  # relation type of each edge

layer = RGATConv(in_channels=8, out_channels=16, num_relations=3)
out = layer(x, edge_index, edge_type)
print(tuple(out.shape))  # (10, 16)

SignedConv

k3_node.layers.conv.SignedConv

Bases: MessagePassing

The signed graph convolutional operator from the "Signed Graph Convolutional Network" <https://arxiv.org/abs/1808.06354>_ paper.

Example
import numpy as np
from k3_node.layers import SignedConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

pos_edge_index = edge_index[:, :15]  # positive (e.g. "trust") edges
neg_edge_index = edge_index[:, 15:]  # negative (e.g. "distrust") edges
layer = SignedConv(in_channels=8, out_channels=16, first_aggr=True)
out = layer(x, pos_edge_index, neg_edge_index)
print(tuple(out.shape))  # (10, 32): positive and negative embeddings, concatenated

DirGNNConv

k3_node.layers.conv.DirGNNConv

Bases: Layer

A directed graph neural network operator from the "Directed Graph Neural Networks" <https://arxiv.org/abs/2301.07663>_ paper.

Example
import numpy as np
from k3_node.layers import DirGNNConv, GCNConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

# Runs the wrapped convolution on incoming and outgoing edges separately
layer = DirGNNConv(GCNConv(in_channels=8, out_channels=16))
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 16)

AntiSymmetricConv

k3_node.layers.conv.AntiSymmetricConv

Bases: Layer

The anti-symmetric graph convolutional operator from the "Anti-Symmetric DGN: a Continuous approach to Deep Graph Neural Networks" <https://arxiv.org/abs/2202.13085>_ paper.

Example
import numpy as np
from k3_node.layers import AntiSymmetricConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = AntiSymmetricConv(in_channels=8)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 8)

Advanced & Scaled Graph Convolutions

FiLMConv

k3_node.layers.conv.FiLMConv

Bases: MessagePassing

The FiLM graph convolutional operator from the "GNN-FiLM: Graph Neural Networks with Feature-wise Linear Modulation" <https://arxiv.org/abs/1906.12192>_ paper.

Example
import numpy as np
from k3_node.layers import FiLMConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = FiLMConv(in_channels=8, out_channels=16)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 16)

SuperGATConv

k3_node.layers.conv.SuperGATConv

Bases: MessagePassing

The self-supervised graph attentional operator from the "How to Find Your Friendly Neighborhood: Graph Attention Design with Self-Supervision" <https://openreview.net/forum?id=Wi5KUNlqWty>_ paper.

Parameters:

Name Type Description Default
attention_type str

"MX" (mixed GO/DP) or "SD" (scaled dot-product).

'MX'
neg_sample_ratio float

Negative (random) pairs per positive edge in the attention loss.

0.5
edge_sample_ratio float

Fraction of edges used as positives in the attention loss.

1.0
attention_loss_weight float

If positive, the self-supervised attention loss is added to the model loss (model.losses) with this weight while training, so fit optimizes it automatically. PyG's example uses 4.0. (default: 0.0)

0.0
Example
import numpy as np
from k3_node.layers import SuperGATConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = SuperGATConv(in_channels=8, out_channels=16, heads=2)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 32)

get_attention_loss()

The self-supervised attention loss of the last training call (as in PyG).

EGConv

k3_node.layers.conv.EGConv

Bases: MessagePassing

The Efficient Graph Convolution from the "Adaptive Filters and Aggregator Fusion for Efficient Graph Convolutions" <https://arxiv.org/abs/2104.01481>_ paper.

Example
import numpy as np
from k3_node.layers import EGConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = EGConv(in_channels=8, out_channels=16, num_heads=2)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 16)

MixHopConv

k3_node.layers.conv.MixHopConv

Bases: MessagePassing

The MixHop graph convolutional operator from the "Higher-Order Graph Convolutional Networks via MixHop" <https://arxiv.org/abs/1905.00067>_ paper.

Example
import numpy as np
from k3_node.layers import MixHopConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = MixHopConv(in_channels=8, out_channels=16, powers=[0, 1, 2])
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 48)

PDNConv

k3_node.layers.conv.PDNConv

Bases: MessagePassing

The pathfinder discovery network convolutional operator from the "Pathfinder Discovery Networks for Neural Message Passing" <https://arxiv.org/abs/2010.12878>_ paper.

Example
import numpy as np
from k3_node.layers import PDNConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges
edge_attr = np.random.rand(30, 3).astype("float32")  # 3 features per edge

layer = PDNConv(in_channels=8, out_channels=16, edge_dim=3, hidden_channels=16)
out = layer(x, edge_index, edge_attr)
print(tuple(out.shape))  # (10, 16)

FAConv

k3_node.layers.conv.FAConv

Bases: MessagePassing

The Frequency Adaptive Graph Convolution operator from the "Beyond Low-Frequency Information in Graph Convolutional Networks" <https://arxiv.org/abs/2101.00797>_ paper.

Example
import numpy as np
from k3_node.layers import FAConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

x_0 = x  # initial node representations
layer = FAConv(channels=8, eps=0.1)
out = layer(x, x_0, edge_index)
print(tuple(out.shape))  # (10, 8)

PANConv

k3_node.layers.conv.PANConv

Bases: MessagePassing

The path integral based convolution operator from the "Path Integral Based Convolution and Pooling for Graph Neural Networks" <https://arxiv.org/abs/2004.14805>_ paper.

Example
import numpy as np
from k3_node.layers import PANConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = PANConv(in_channels=8, out_channels=16, filter_size=2)
out, weights = layer(x, edge_index)  # also returns the learned path weights
print(tuple(out.shape))  # (10, 16)

LEConv

k3_node.layers.conv.LEConv

Bases: MessagePassing

The local extremum graph convolutional operator from the "ASAP: Adaptive Structure Aware Pooling for Learning Hierarchical Graph Representations" <https://arxiv.org/abs/1911.07979>_ paper.

Parameters:

Name Type Description Default
in_channels Union[int, Tuple[int, int]]

Size of each input sample, or a tuple for bipartite graphs.

required
out_channels int

Size of each output sample.

required
bias bool

If set to :obj:False, the layer will not learn an additive bias. (default: True)

True
Example
import numpy as np
from k3_node.layers import LEConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = LEConv(in_channels=8, out_channels=16)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 16)

ClusterGCNConv

k3_node.layers.conv.ClusterGCNConv

Bases: MessagePassing

The ClusterGCN graph convolutional operator from the "Cluster-GCN: An Efficient Algorithm for Training Deep and Large Graph Convolutional Networks" <https://arxiv.org/abs/1905.07953>_ paper.

Parameters:

Name Type Description Default
in_channels int

Size of each input sample.

required
out_channels int

Size of each output sample.

required
diag_lambda float

Diagonal enhancement coefficient :math:\lambda. (default: 0.0)

0.0
add_self_loops bool

If set to :obj:False, will not add self-loops. (default: True)

True
bias bool

If set to :obj:False, the layer will not learn an additive bias. (default: True)

True
Example
import numpy as np
from k3_node.layers import ClusterGCNConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = ClusterGCNConv(in_channels=8, out_channels=16)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 16)

GCN2Conv

k3_node.layers.conv.GCN2Conv

Bases: MessagePassing

The graph convolutional operator from the "Simple and Deep Graph Convolutional Networks" <https://arxiv.org/abs/2007.02133>_ paper.

Parameters:

Name Type Description Default
channels int

Size of each input and output sample.

required
alpha float

The strength of the initial residual connection :math:\alpha.

required
theta Optional[float]

The hyperparameter for the identity mapping :math:\theta. (default: :obj:None)

None
layer Optional[int]

The layer index :math:l. (default: :obj:None)

None
shared_weights bool

If set to :obj:True, will use the same weights for :math:\mathbf{X} and :math:\mathbf{X}_0. (default: :obj:True)

True
cached bool

If set to :obj:True, will cache the computation of normalization coefficients. (default: False)

False
add_self_loops bool

If set to :obj:False, will not add self-loops. (default: True)

True
normalize bool

Whether to apply symmetric normalization. (default: True)

True
Example
import numpy as np
from k3_node.layers import GCN2Conv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

x_0 = x  # initial node representations (from the first layer)
layer = GCN2Conv(channels=8, alpha=0.1, theta=0.5, layer=1)
out = layer(x, x_0, edge_index)
print(tuple(out.shape))  # (10, 8)

LGConv

k3_node.layers.conv.LGConv

Bases: MessagePassing

The LightGCN operator from the "LightGCN: Simplifying and Powering Graph Convolution Network for Recommendation" <https://arxiv.org/abs/2002.02126>_ paper.

Parameters:

Name Type Description Default
normalize bool

Whether to apply symmetric normalization. (default: True)

True
Example
import numpy as np
from k3_node.layers import LGConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = LGConv()
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 8)

NNConv

k3_node.layers.conv.NNConv

Bases: MessagePassing

The continuous kernel-based convolutional operator from the "Neural Message Passing for Quantum Chemistry" <https://arxiv.org/abs/1704.01212>_ paper.

Parameters:

Name Type Description Default
in_channels Union[int, Tuple[int, int]]

Size of each input sample, or a tuple for bipartite graphs.

required
out_channels int

Size of each output sample.

required
nn Callable

A neural network :math:h_{\mathbf{\Theta}} that maps edge features to shape :obj:[-1, in_channels * out_channels].

required
aggr str

The aggregation scheme to use ("add", "mean", "max"). (default: "add")

'add'
root_weight bool

If set to :obj:False, the layer will not add the transformed root node features. (default: True)

True
bias bool

If set to :obj:False, the layer will not learn an additive bias. (default: True)

True
Example
import numpy as np
import keras
from k3_node.layers import NNConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges
edge_attr = np.random.rand(30, 3).astype("float32")  # 3 features per edge

# `nn` maps each edge's features to an [in_channels * out_channels] weight matrix
layer = NNConv(in_channels=8, out_channels=16, nn=keras.layers.Dense(8 * 16))
out = layer(x, edge_index, edge_attr)
print(tuple(out.shape))  # (10, 16)

CGConv

k3_node.layers.conv.CGConv

Bases: MessagePassing

The Crystal Graph Convolutional operator from the "Crystal Graph Convolutional Neural Networks for an Accurate and Interpretable Prediction of Material Properties" <https://arxiv.org/abs/1710.10324>_ paper.

Parameters:

Name Type Description Default
channels Union[int, Tuple[int, int]]

Size of each input sample, or a tuple for bipartite graphs.

required
dim int

Edge feature dimensionality. (default: 0)

0
aggr str

The aggregation scheme to use ("add", "mean", "max"). (default: "add")

'add'
batch_norm bool

If set to :obj:True, will apply batch normalization. (default: False)

False
bias bool

If set to :obj:False, the layer will not learn an additive bias. (default: True)

True
Example
import numpy as np
from k3_node.layers import CGConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges
edge_attr = np.random.rand(30, 3).astype("float32")  # 3 features per edge

layer = CGConv(channels=8, dim=3)
out = layer(x, edge_index, edge_attr)
print(tuple(out.shape))  # (10, 8)

EdgeConv

k3_node.layers.conv.EdgeConv

Bases: MessagePassing

The edge convolutional operator from the "Dynamic Graph CNN for Learning on Point Clouds" <https://arxiv.org/abs/1801.07829>_ paper.

Parameters:

Name Type Description Default
nn Callable

A neural network :math:h_{\mathbf{\Theta}} that maps pair-wise node features to new edge representations.

required
aggr str

The aggregation scheme to use ("max", "mean", "sum"). (default: "max")

'max'
Example
import numpy as np
import keras
from k3_node.layers import EdgeConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

nn = keras.Sequential([keras.layers.Dense(16, activation="relu"), keras.layers.Dense(16)])
layer = EdgeConv(nn)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 16)

DynamicEdgeConv

k3_node.layers.conv.DynamicEdgeConv

Bases: EdgeConv

The dynamic edge convolutional operator from the "Dynamic Graph CNN for Learning on Point Clouds" <https://arxiv.org/abs/1801.07829>_ paper, which dynamically constructs a graph using :math:k-NN at each layer.

Parameters:

Name Type Description Default
nn Callable

A neural network :math:h_{\mathbf{\Theta}}.

required
k int

Number of nearest neighbors. (default: 6)

6
aggr str

The aggregation scheme to use ("max", "mean", "sum"). (default: "max")

'max'
num_workers int

Number of workers (ignored in Keras backend).

1
Example
import numpy as np
import keras
from k3_node.layers import DynamicEdgeConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

nn = keras.Sequential([keras.layers.Dense(16, activation="relu"), keras.layers.Dense(16)])
layer = DynamicEdgeConv(nn, k=3)
out = layer(x)  # k-NN graph is built from x
print(tuple(out.shape))  # (10, 16)

GeneralConv

k3_node.layers.conv.GeneralConv

Bases: MessagePassing

A general GNN layer adapted from the "Design Space for Graph Neural Networks" <https://arxiv.org/abs/2011.08843>_ paper.

Example
import numpy as np
from k3_node.layers import GeneralConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges
edge_attr = np.random.rand(30, 3).astype("float32")  # 3 features per edge

layer = GeneralConv(in_channels=8, out_channels=16, in_edge_channels=3)
out = layer(x, edge_index, edge_attr)
print(tuple(out.shape))  # (10, 16)

Heterogeneous & Hypergraph Convolutions

HeteroConv

k3_node.layers.conv.HeteroConv

Bases: Layer

A generic wrapper for computing graph convolution on heterogeneous graphs.

Parameters:

Name Type Description Default
convs Dict[Tuple[str, str, str], Layer]

A dictionary holding a bipartite GNN layer for each individual edge type.

required
aggr str

The aggregation scheme to use for grouping node embeddings generated by different relations (:obj:"sum", :obj:"mean", :obj:"min", :obj:"max", :obj:"cat", :obj:None). (default: :obj:"sum")

'sum'
Example
import numpy as np
from k3_node.layers import HeteroConv, SAGEConv

x_dict = {
    "author": np.random.rand(3, 8).astype("float32"),
    "paper": np.random.rand(4, 8).astype("float32"),
}
edge_index_dict = {
    ("author", "writes", "paper"): np.array([[0, 1, 2], [1, 2, 3]]),
    ("paper", "written_by", "author"): np.array([[1, 2, 3], [0, 1, 2]]),
}

# One convolution per edge type; results for the same node type are summed
layer = HeteroConv({
    ("author", "writes", "paper"): SAGEConv((8, 8), 16),
    ("paper", "written_by", "author"): SAGEConv((8, 8), 16),
}, aggr="sum")
out_dict = layer(x_dict, edge_index_dict)
print(tuple(out_dict["author"].shape), tuple(out_dict["paper"].shape))  # (3, 16) (4, 16)

HGTConv

k3_node.layers.conv.HGTConv

Bases: MessagePassing

The Heterogeneous Graph Transformer (HGT) operator from the "Heterogeneous Graph Transformer" <https://arxiv.org/abs/2003.01332>_ paper.

Parameters:

Name Type Description Default
in_channels int or Dict[str, int]

Size of each input sample of every node type.

required
out_channels int

Size of each output sample.

required
metadata Tuple[List[str], List[Tuple[str, str, str]]]

Node types and edge types.

required
heads int

Number of multi-head-attentions. (default: :obj:1)

1
Example
import numpy as np
from k3_node.layers import HGTConv

x_dict = {
    "author": np.random.rand(3, 8).astype("float32"),
    "paper": np.random.rand(4, 8).astype("float32"),
}
edge_index_dict = {
    ("author", "writes", "paper"): np.array([[0, 1, 2], [1, 2, 3]]),
    ("paper", "written_by", "author"): np.array([[1, 2, 3], [0, 1, 2]]),
}
metadata = (list(x_dict), list(edge_index_dict))  # (node types, edge types)

layer = HGTConv(in_channels={"author": 8, "paper": 8}, out_channels=16, metadata=metadata, heads=2)
out_dict = layer(x_dict, edge_index_dict)
print(tuple(out_dict["author"].shape), tuple(out_dict["paper"].shape))  # (3, 16) (4, 16)

HANConv

k3_node.layers.conv.HANConv

Bases: MessagePassing

The Heterogeneous Graph Attention Operator from the "Heterogeneous Graph Attention Network" <https://arxiv.org/abs/1903.07293>_ paper.

Parameters:

Name Type Description Default
in_channels int or Dict[str, int]

Size of each input sample of every node type.

required
out_channels int

Size of each output sample.

required
metadata Tuple[List[str], List[Tuple[str, str, str]]]

Node types and edge types.

required
heads int

Number of multi-head-attentions. (default: :obj:1)

1
negative_slope float

LeakyReLU angle of the negative slope. (default: :obj:0.2)

0.2
Example
import numpy as np
from k3_node.layers import HANConv

x_dict = {
    "author": np.random.rand(3, 8).astype("float32"),
    "paper": np.random.rand(4, 8).astype("float32"),
}
edge_index_dict = {
    ("author", "writes", "paper"): np.array([[0, 1, 2], [1, 2, 3]]),
    ("paper", "written_by", "author"): np.array([[1, 2, 3], [0, 1, 2]]),
}
metadata = (list(x_dict), list(edge_index_dict))  # (node types, edge types)

layer = HANConv(in_channels={"author": 8, "paper": 8}, out_channels=16, metadata=metadata, heads=2)
out_dict = layer(x_dict, edge_index_dict)
print(tuple(out_dict["author"].shape), tuple(out_dict["paper"].shape))  # (3, 16) (4, 16)

HEATConv

k3_node.layers.conv.HEATConv

Bases: MessagePassing

The heterogeneous edge-enhanced graph attentional operator from the "Heterogeneous Edge-Enhanced Graph Attention Network For Multi-Agent Trajectory Prediction" <https://arxiv.org/abs/2106.07161>_ paper.

Parameters:

Name Type Description Default
in_channels int

Size of each input sample.

required
out_channels int

Size of each output sample.

required
num_node_types int

The number of node types.

required
num_edge_types int

The number of edge types.

required
edge_type_emb_dim int

The embedding size of edge types.

required
edge_dim int

Edge feature dimensionality.

required
edge_attr_emb_dim int

The embedding size of edge features.

required
heads int

Number of multi-head-attentions. (default: :obj:1)

1
concat bool

Whether to concatenate multi-head attention. (default: :obj:True)

True
negative_slope float

LeakyReLU angle. (default: :obj:0.2)

0.2
root_weight bool

Whether to add root node features. (default: :obj:True)

True
bias bool

Whether to learn an additive bias. (default: :obj:True)

True
Example
import numpy as np
from k3_node.layers import HEATConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

node_type = np.random.randint(0, 2, size=(10,))
edge_type = np.random.randint(0, 3, size=(30,))
edge_attr = np.random.rand(30, 5).astype("float32")
layer = HEATConv(in_channels=8, out_channels=16, num_node_types=2, num_edge_types=3,
                 edge_type_emb_dim=4, edge_dim=5, edge_attr_emb_dim=6, heads=2)
out = layer(x, edge_index, node_type, edge_type, edge_attr)
print(tuple(out.shape))  # (10, 32)

HypergraphConv

k3_node.layers.conv.HypergraphConv

Bases: MessagePassing

The hypergraph convolutional operator from the "Hypergraph Convolution and Hypergraph Attention" <https://arxiv.org/abs/1901.08150>_ paper.

Parameters:

Name Type Description Default
in_channels int

Size of each input sample.

required
out_channels int

Size of each output sample.

required
use_attention bool

Whether to use hypergraph attention. (default: :obj:False)

False
attention_mode str

Attention mode (:obj:"node" or :obj:"edge"). (default: :obj:"node")

'node'
heads int

Number of multi-head-attentions. (default: :obj:1)

1
concat bool

Whether to concatenate heads. (default: :obj:True)

True
negative_slope float

LeakyReLU angle. (default: :obj:0.2)

0.2
bias bool

Whether to learn an additive bias. (default: :obj:True)

True
Example
import numpy as np
from k3_node.layers import HypergraphConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

# Row 0: node index, row 1: hyperedge index (nodes 0-5 form two hyperedges)
hyperedge_index = np.array([[0, 1, 2, 3, 4, 5], [0, 0, 0, 1, 1, 1]])
layer = HypergraphConv(in_channels=8, out_channels=16)
out = layer(x, hyperedge_index)
print(tuple(out.shape))  # (10, 16)

DNAConv

k3_node.layers.conv.DNAConv

Bases: MessagePassing

The dynamic neighborhood aggregation operator from the "Just Jump: Towards Dynamic Neighborhood Aggregation in Graph Neural Networks" <https://arxiv.org/abs/1904.04849>_ paper.

Parameters:

Name Type Description Default
channels int

Size of each input/output sample.

required
heads int

Number of multi-head-attentions. (default: :obj:1)

1
groups int

Number of groups for linear projections. (default: :obj:1)

1
dropout float

Dropout probability. (default: :obj:0.0)

0.0
cached bool

Whether to cache GCN normalization. (default: :obj:False)

False
normalize bool

Whether to apply symmetric normalization. (default: :obj:True)

True
add_self_loops bool

Whether to add self-loops. (default: :obj:True)

True
bias bool

Whether to learn an additive bias. (default: :obj:True)

True
Example
import numpy as np
from k3_node.layers import DNAConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

# DNAConv attends over the representations of all previous layers: [num_nodes, num_layers, channels]
x_all = np.random.rand(10, 3, 8).astype("float32")
layer = DNAConv(channels=8, heads=2, groups=2)
out = layer(x_all, edge_index)
print(tuple(out.shape))  # (10, 8)

WLConv

k3_node.layers.conv.WLConv

Bases: Layer

The Weisfeiler Lehman (WL) operator from the "A Reduction of a Graph to a Canonical Form and an Algebra Arising During this Reduction" <https://www.iti.zcu.cz/wl2018/pdf/wl_paper_translation.pdf>_ paper.

Parameters:

Name Type Description Default
**kwargs

Additional layer arguments.

{}
Example
import numpy as np
from k3_node.layers import WLConv

colors = np.array([0, 1, 0, 1])  # discrete node colors (labels)
edge_index = np.array([[0, 1, 2, 3], [1, 2, 3, 0]])
layer = WLConv()
new_colors = layer(colors, edge_index)  # one Weisfeiler-Lehman refinement step
print(tuple(new_colors.shape))  # (4,)
print(tuple(layer.histogram(new_colors).shape))  # (1, 2): color histogram per graph

GPSConv

k3_node.layers.conv.GPSConv

Bases: Layer

The general, powerful, scalable (GPS) graph transformer layer from the "Recipe for a General, Powerful, Scalable Graph Transformer" <https://arxiv.org/abs/2205.12454>_ paper.

Parameters:

Name Type Description Default
channels int

Size of each input sample.

required
conv Layer

The local message passing layer.

None
heads int

Number of multi-head-attentions. (default: :obj:1)

1
dropout float

Dropout probability. (default: :obj:0.0)

0.0
act str

Activation function. (default: :obj:"relu")

'relu'
norm str

Normalization function. (default: :obj:"batch_norm")

'batch_norm'

Call arguments: x, edge_index, batch (the graph of every node) and batch_size (the number of graphs; pass it when training compiled so that shapes are static), plus any arguments of the local conv such as edge_attr.

Example
import numpy as np
from k3_node.layers import GPSConv, GCNConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

batch = np.repeat([0, 1], 5)  # two graphs with 5 nodes each
layer = GPSConv(channels=8, conv=GCNConv(8, 8), heads=2)
out = layer(x, edge_index, batch=batch)
print(tuple(out.shape))  # (10, 8)

Point Cloud & Geometric Convolutions

PointNetConv

k3_node.layers.conv.PointNetConv

Bases: MessagePassing

The PointNet set abstraction layer from the "PointNet++: Deep Hierarchical Feature Learning on Point Sets in a Metric Space" <https://arxiv.org/abs/1706.02413>_ paper.

Example
import numpy as np
import keras
from k3_node.layers import PointNetConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges
pos = np.random.rand(10, 3).astype("float32")  # 3D node positions

local_nn = keras.Sequential([keras.layers.Dense(16, activation="relu"), keras.layers.Dense(16)])
layer = PointNetConv(local_nn=local_nn)
out = layer(x, pos, edge_index)
print(tuple(out.shape))  # (10, 16)

PointConv

k3_node.layers.conv.PointConv = PointNetConv module-attribute

PointTransformerConv

k3_node.layers.conv.PointTransformerConv

Bases: MessagePassing

The Point Transformer layer from the "Point Transformer" <https://arxiv.org/abs/2012.09164>_ paper.

Example
import numpy as np
from k3_node.layers import PointTransformerConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges
pos = np.random.rand(10, 3).astype("float32")  # 3D node positions

layer = PointTransformerConv(in_channels=8, out_channels=16)
out = layer(x, pos, edge_index)
print(tuple(out.shape))  # (10, 16)

PointGNNConv

k3_node.layers.conv.PointGNNConv

Bases: MessagePassing

The PointGNN graph convolutional operator from the "Point-GNN: Graph Neural Network for 3D Object Detection in a Point Cloud" <https://arxiv.org/abs/2003.01251>_ paper.

Example
import numpy as np
import keras
from k3_node.layers import PointGNNConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges
pos = np.random.rand(10, 3).astype("float32")  # 3D node positions

layer = PointGNNConv(
    mlp_h=keras.layers.Dense(3),  # predicts a position offset per node
    mlp_f=keras.layers.Dense(16),  # edge feature network
    mlp_g=keras.layers.Dense(8),  # node update network (output size = input features)
)
out = layer(x, pos, edge_index)
print(tuple(out.shape))  # (10, 8)

PPFConv

k3_node.layers.conv.PPFConv

Bases: MessagePassing

The PPFNet graph convolutional operator from the "PPFNet: Global Context Aware Local Features for Robust 3D Point Matching" <https://arxiv.org/abs/1802.02669>_ paper.

Example
import numpy as np
import keras
from k3_node.layers import PPFConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges
pos = np.random.rand(10, 3).astype("float32")  # 3D node positions
normal = np.random.rand(10, 3).astype("float32")  # surface normals

local_nn = keras.Sequential([keras.layers.Dense(16, activation="relu"), keras.layers.Dense(16)])
layer = PPFConv(local_nn=local_nn)
out = layer(x, pos, normal, edge_index)
print(tuple(out.shape))  # (10, 16)

FeaStConv

k3_node.layers.conv.FeaStConv

Bases: MessagePassing

The (fault-tolerant) feature-steered graph convolution operator from the "FeaStNet: Feature-Steered Graph Convolutions for 3D Shape Analysis" <https://arxiv.org/abs/1706.05206>_ paper.

Example
import numpy as np
from k3_node.layers import FeaStConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = FeaStConv(in_channels=8, out_channels=16, heads=2)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 16)

GMMConv

k3_node.layers.conv.GMMConv

Bases: MessagePassing

The gaussian mixture model convolutional operator from the "Geometric Deep Learning on Graphs and Manifolds using Mixture Model CNNs" <https://arxiv.org/abs/1611.08402>_ paper.

Example
import numpy as np
from k3_node.layers import GMMConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges
edge_attr = np.random.rand(30, 3).astype("float32")  # 3 features per edge

layer = GMMConv(in_channels=8, out_channels=16, dim=3, kernel_size=2)
out = layer(x, edge_index, edge_attr)
print(tuple(out.shape))  # (10, 16)

GravNetConv

k3_node.layers.conv.GravNetConv

Bases: MessagePassing

The GravNet operator from the "Learning Representations of Irregular Particle-Detector Geometry with Distance-Weighted Graph Networks" <https://arxiv.org/abs/1902.07987>_ paper.

Example
import numpy as np
from k3_node.layers import GravNetConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

# Neighbors are found by k-NN in a learned space, so no edge_index is needed
layer = GravNetConv(in_channels=8, out_channels=16, space_dimensions=3, propagate_dimensions=4, k=3)
out = layer(x)
print(tuple(out.shape))  # (10, 16)

MeshCNNConv

k3_node.layers.conv.MeshCNNConv

Bases: MessagePassing

The MeshCNN convolutional operator from the "MeshCNN: A Network With An Edge" <https://arxiv.org/abs/1809.05910>_ paper.

Parameters:

Name Type Description Default
in_channels int

Size of each input sample.

required
out_channels int

Size of each output sample.

required
kernels List[Layer]

A list of 5 neural network layers that transform edge representations. (default: :obj:None)

None
Example
import numpy as np
from k3_node.layers import MeshCNNConv

# In MeshCNN the "nodes" are mesh edges; each mesh edge has exactly 4 neighboring edges,
# listed in a fixed order in edge_index (4 incoming entries per mesh edge).
x = np.random.rand(4, 8).astype("float32")  # features of 4 mesh edges
edge_index = np.array([
    [1, 2, 3, 0, 0, 2, 3, 1, 0, 1, 3, 2, 0, 1, 2, 3],  # neighboring mesh edge
    [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],  # mesh edge being updated
])
layer = MeshCNNConv(in_channels=8, out_channels=16)
out = layer(x, edge_index)
print(tuple(out.shape))  # (4, 16)

XConv

k3_node.layers.conv.XConv

Bases: Layer

The convolutional operator on :math:\mathcal{X}-transformed points from the "PointCNN: Convolution On X-Transformed Points" <https://arxiv.org/abs/1801.07791>_ paper.

Parameters:

Name Type Description Default
in_channels int

Size of each input sample.

required
out_channels int

Size of each output sample.

required
dim int

Point cloud dimensionality.

required
kernel_size int

Size of the convolving kernel.

required
hidden_channels int

Dimensionality of lifted points.

None
dilation int

Dilation factor. (default: :obj:1)

1
bias bool

Whether to learn an additive bias. (default: :obj:True)

True
num_workers int

Kept for PyG compatibility.

1
Example
import numpy as np
from k3_node.layers import XConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges
pos = np.random.rand(10, 3).astype("float32")  # 3D node positions

layer = XConv(in_channels=8, out_channels=16, dim=3, kernel_size=2)
out = layer(x, pos)  # neighborhoods are built from `pos`
print(tuple(out.shape))  # (10, 16)

SplineConv

k3_node.layers.conv.SplineConv

Bases: MessagePassing

The spline-based convolutional operator from the "SplineCNN: Fast Geometric Deep Learning with Continuous B-Spline Kernels" <https://arxiv.org/abs/1711.08920>_ paper.

Parameters:

Name Type Description Default
in_channels int or tuple

Size of each input sample.

required
out_channels int

Size of each output sample.

required
dim int

Pseudo-coordinate dimensionality.

required
kernel_size int or List[int]

Size of the convolving kernel.

required
is_open_spline bool or List[bool]

If set to :obj:False, uses closed B-spline basis. (default: :obj:True)

True
degree int

B-spline basis degree. (default: :obj:1)

1
aggr str

The aggregation scheme to use (:obj:"mean", :obj:"add", :obj:"max"). (default: :obj:"mean")

'mean'
root_weight bool

Whether to add transformed root node features. (default: :obj:True)

True
bias bool

Whether to learn an additive bias. (default: :obj:True)

True
Example
import numpy as np
from k3_node.layers import SplineConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges
pseudo = np.random.rand(30, 2).astype("float32")  # pseudo-coordinates in [0, 1]

layer = SplineConv(in_channels=8, out_channels=16, dim=2, kernel_size=3)
out = layer(x, edge_index, pseudo)
print(tuple(out.shape))  # (10, 16)

Spektral-Compatible Convolutions

CrystalConv

k3_node.layers.conv.CrystalConv

Bases: MessagePassing

k3_node.layers.CrystalConv Implementation of Crystal Graph Convolutional Neural Networks (CGCNN) layer

Parameters:

Name Type Description Default
channels

The number of channels/units (optional).

None
edge_dim

The dimensionality of edge features (optional).

None
aggregate

Aggregation function to use (one of 'sum', 'mean', 'max').

'sum'
activation

Activation function to use.

None
use_bias

Whether to add a bias to the linear transformation.

True
kernel_initializer

Initializer for the kernel weights matrix.

'glorot_uniform'
bias_initializer

Initializer for the bias vector.

'zeros'
kernel_regularizer

Regularizer for the kernel weights matrix.

None
bias_regularizer

Regularizer for the bias vector.

None
activity_regularizer

Regularizer for the output.

None
kernel_constraint

Constraint for the kernel weights matrix.

None
bias_constraint

Constraint for the bias vector.

None
**kwargs

Additional arguments to pass to the MessagePassing superclass.

{}
Example
import numpy as np
from k3_node.layers import CrystalConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges
edge_attr = np.random.rand(30, 3).astype("float32")  # 3 features per edge

layer = CrystalConv(channels=8, edge_dim=3)
out = layer(x, edge_index, edge_attr)
print(tuple(out.shape))  # (10, 8)

DiffusionConv

k3_node.layers.conv.DiffusionConv

Bases: Conv

k3_node.layers.DiffusionConv Implementation of Diffusion Convolutional Neural Networks (DCNN) layer

Parameters:

Name Type Description Default
channels

The number of output channels.

required
K

The number of diffusion steps.

6
activation

Activation function to use.

'tanh'
kernel_initializer

Initializer for the kernel weights matrix.

'glorot_uniform'
kernel_regularizer

Regularizer for the kernel weights matrix.

None
kernel_constraint

Constraint for the kernel weights matrix.

None
**kwargs

Additional arguments to pass to the Conv superclass.

{}
Example
import numpy as np
from k3_node.layers import DiffusionConv

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = DiffusionConv(channels=8, out_channels=16, K=2)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 16)

GraphConvolution

k3_node.layers.conv.GraphConvolution

Bases: Layer

k3_node.layers.GraphConvolution Implementation of Graph Convolution (GCN) layer

Parameters:

Name Type Description Default
units

Positive integer, dimensionality of the output space.

required
activation

Activation function to use.

None
use_bias

Whether to add a bias to the linear transformation.

True
final_layer

Deprecated, use tf.gather or GatherIndices instead.

None
input_dim

Deprecated, use keras.layers.Input with input_shape instead.

None
kernel_initializer

Initializer for the kernel weights matrix.

'glorot_uniform'
kernel_regularizer

Regularizer for the kernel weights matrix.

None
kernel_constraint

Constraint for the kernel weights matrix.

None
bias_initializer

Initializer for the bias vector.

'zeros'
bias_regularizer

Regularizer for the bias vector.

None
bias_constraint

Constraint for the bias vector.

None
**kwargs

Additional arguments to pass to the Layer superclass.

{}
Example
import numpy as np
from k3_node.layers import GraphConvolution

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = GraphConvolution(units=16, activation="relu")
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 16)

GraphAttention

k3_node.layers.conv.GraphAttention

Bases: Layer

k3_node.layers.GraphAttention Implementation of Graph Attention (GAT) layer

Parameters:

Name Type Description Default
units

Positive integer, dimensionality of the output space.

required
attn_heads

Positive integer, number of attention heads.

1
attn_heads_reduction

{'concat', 'average'} Method for reducing attention heads.

'concat'
in_dropout_rate

Dropout rate applied to the input (node features).

0.0
attn_dropout_rate

Dropout rate applied to attention coefficients.

0.0
activation

Activation function to use.

'relu'
use_bias

Whether to add a bias to the linear transformation.

True
final_layer

Deprecated, use tf.gather or GatherIndices instead.

None
saliency_map_support

Whether to support saliency map calculations.

False
kernel_initializer

Initializer for the kernel weights matrix.

'glorot_uniform'
kernel_regularizer

Regularizer for the kernel weights matrix.

None
kernel_constraint

Constraint for the kernel weights matrix.

None
bias_initializer

Initializer for the bias vector.

'zeros'
bias_regularizer

Regularizer for the bias vector.

None
bias_constraint

Constraint for the bias vector.

None
attn_kernel_initializer

Initializer for the attention kernel weights matrix.

'glorot_uniform'
attn_kernel_regularizer

Regularizer for the attention kernel weights matrix.

None
attn_kernel_constraint

Constraint for the attention kernel weights matrix.

None
**kwargs

Additional arguments to pass to the Layer superclass.

{}
Example
import numpy as np
from k3_node.layers import GraphAttention

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = GraphAttention(units=16, attn_heads=2)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 2)

PPNPPropagation

k3_node.layers.conv.PPNPPropagation

Bases: Layer

k3_node.layers.PPNPPropagation Implementation of PPNP layer

Parameters:

Name Type Description Default
units

Positive integer, dimensionality of the output space.

None
final_layer

Deprecated.

None
input_dim

Deprecated.

None
**kwargs

Additional arguments to pass to the Layer superclass.

{}
Example
import numpy as np
from k3_node.layers import PPNPPropagation

x = np.random.rand(10, 8).astype("float32")  # 10 nodes with 8 features each
edge_index = np.random.randint(0, 10, size=(2, 30))  # 30 random edges

layer = PPNPPropagation(units=16)
out = layer(x, edge_index)
print(tuple(out.shape))  # (10, 16)