TorchLean API

NN.Spec.Layers.Gnn

Graph neural network layers (spec layer) #

We provide a couple of small, standard GNN building blocks that show up in lots of papers and PyTorch GNN libraries:

Message passing (the common core idea) #

Most GNN layers have the same shape of computation:

In this file the aggregation step is written with a matrix A : (n×n):

Agg(A, H) = A · H.

This captures many common conventions:

GCN layer (one very common choice) #

We model a GCN-style layer as:

H' = A · H · W + b

where:

PyTorch mental picture:

Why only these two right now:

def Spec.messagePassingSpec {α : Type} [Context α] {n inDim : } (A : Tensor α (Shape.dim n (Shape.dim n Shape.scalar))) (x : Tensor α (Shape.dim n (Shape.dim inDim Shape.scalar))) :

Neighbor aggregation / message passing via a graph matrix: Agg(A, X) = A · X.

This is the reusable "mix neighbors" step. The semantics are entirely determined by A (raw adjacency, normalized adjacency, weighted adjacency, etc.).

Instances For

    Backward/VJP for message_passing_spec: returns (dA, dX).

    Instances For
      structure Spec.GCNLayerSpec (n inDim outDim : ) (α : Type) :

      Parameters/data for a single GCN-style layer.

      We bundle A with the layer because many code paths treat A as a fixed input per graph, while others treat it as a parameter (e.g. learned normalization). Keeping it in the record makes both uses explicit.

      Instances For
        def Spec.gcnLayerSpec {α : Type} [Context α] {n inDim outDim : } (layer : GCNLayerSpec n inDim outDim α) (x : Tensor α (Shape.dim n (Shape.dim inDim Shape.scalar))) :

        Forward spec for a GCN-style layer: Y = A · X · W + b.

        Notes:

        • The bias b is broadcast across the n nodes (row-wise add).
        • Any normalization/self-loop convention belongs in the choice of A supplied to the layer.
        Instances For

          Gradients #

          For the simple GCN-style layer

          Y = A · X · W + b

          the reverse-mode derivatives are the standard matrix calculus ones:

          We include dA because in some setups the adjacency/normalization is also:

          def Spec.gcnLayerBackwardSpec {α : Type} [Context α] {n inDim outDim : } (layer : GCNLayerSpec n inDim outDim α) (x : Tensor α (Shape.dim n (Shape.dim inDim Shape.scalar))) (grad_output : Tensor α (Shape.dim n (Shape.dim outDim Shape.scalar))) (h_n : n 0) :

          Backward/VJP spec for gcn_layer_spec.

          Returns (dA, dW, db, dX) in that order.

          Instances For