Learning From a Node and Its Neighbours Together
A graph convolution combines node features, self-connections, degree scaling, and learned weights. Work through these pieces before calling the result a layer.
15 sections · 5 questions · 3 coding challenges
The arrow keys move between sections too.
A Simple Shared Layer on a Graph
BOTIE
The construction here reproduces one forward layer with supplied weights. Training would require a loss on labelled nodes and an explicit split protocol; the forward calculation alone has not learned a classifier.
Sources for this history
How Can the Network Learn Which Shared Measurements Matter?
Neighbour means gave Botie context, but a useful prediction may need to combine several features and retain the node’s own reading. Different connections also belong to nodes with different degrees.
A common graph-convolution layer first mixes features through a degree-normalised adjacency matrix, then applies shared learned weights and an activation. Each piece has a separate role.
The feature weights are supplied; this example calculates a layer without training it.
Step 1 of 3
Include self explicitly
The two connected nodes now each have two incoming contributions.
| Receiving node | Node 0 | Node 1 |
|---|---|---|
| Node 0 | 1 | 1 |
| Node 1 | 1 | 1 |
Node 0
- Node 0
- 1
- Node 1
- 1
Node 1
- Node 0
- 1
- Node 1
- 1
Step 2 of 3
Scale both ends of each connection
Equal degrees here give one-half weight per contribution.
| Receiving node | From node 0 | From node 1 |
|---|---|---|
| Node 0 | 0.5 | 0.5 |
| Node 1 | 0.5 | 0.5 |
Node 0
- From node 0
- 0.5
- From node 1
- 0.5
Node 1
- From node 0
- 0.5
- From node 1
- 0.5
Step 3 of 3
Transform the mixed feature
Both nodes receive the average before the shared weight and ReLU.
Node readings: 2 and 4 Mixed feature = (0.5 × 2) + (0.5 × 4) = 3 Output at each node = 3 × 2 = 6
A graph layer mixes across nodes and across features
Graph mixing and learned feature mixing operate on different axes.
Which change comes from neighbours, and which from feature weights?
Graph mixing chooses whose information a node receives. Feature mixing chooses how that information is combined. Follow the two operations separately on the supplied network.
BOTIE
Transformed features for each node
| 6 |
| 6 |
Follow the operations
1. Undirected adjacency, zero diagonal
0 1 1 0 2. Add self-connections
1 1 1 1 3. Scale by both endpoint degrees
0.5 0.5 0.5 0.5 4. Node feature rows
2 4 5. Matrix multiplication
3 3 6. Shared feature weights
2 7. Matrix multiplication
6 6 8. Keep positive values
6 6 9. Result
6 6
This is one forward layer with supplied weights. Symmetric scaling assumes a non-negative undirected graph.
1. Add Self-Loops as a Modelling Choice
Start with an undirected non-negative adjacency matrix and add an identity matrix. This lets each node send its own feature into the aggregation. Compute degrees after adding those self-loops.
If the original matrix already contains self-weights, decide whether adding another identity is intended. Our inputs have zero diagonals.
Self-loops are part of the propagation rule, not an accidental data duplication.
2. Normalise at Both Ends
A connection joins nodes that may have very different numbers of neighbours. Symmetric normalization scales its weight using both endpoint degrees, dividing by the square root of their product. Dividing only by the receiving node's degree would give a different operation.
On an irregular graph, the symmetrically normalized rows may not sum to one. We are using this matrix to propagate features, so we should not automatically interpret its entries as transition probabilities.
A_tilde = A + I
S[i,j] = A_tilde[i,j] / sqrt(degree[i] × degree[j])Adding self-loops ensures positive degree for every node in this non-negative graph.
3. Mix, Transform, and Activate
Let X contain node features and W contain shared learned feature weights. Multiply S by X to gather graph context, then multiply by W to transform feature channels. Apply an elementwise activation such as ReLU.
The graph dimension and feature dimension are different axes. W mixes features, while S mixes nodes. Both operations must respect their shapes.
H = ReLU(S @ X @ W)One layer reaches immediate neighbours; stacking layers extends the receptive neighbourhood.
Separate neighbourhood mixing from the learned feature change
With two connected nodes and self-loops, each node receives equal contributions from both. A supplied negative feature weight then changes the mixed value before ReLU.
import numpy as np
mixing = np.array([[0.5, 0.5], [0.5, 0.5]])
features = np.array([[1.], [5.]])
weight = np.array([[-1.]])
mixed = mixing @ features
weighted = mixed @ weight
print(mixed.tolist())
print(weighted.tolist())
print(np.maximum(weighted, 0).tolist())[[3.0], [3.0]]
[[-3.0], [-3.0]]
[[0.0], [0.0]]The graph first shares information, the weight changes its feature contribution, and the activation clips negative outputs. Practice constructs the normalised mixing matrix as well.
4. Keep Evaluation Boundaries Honest
A transductive protocol may expose the full graph and unlabelled test-node features during training while withholding their labels. An inductive protocol evaluates on unseen nodes or graphs. State which task you are testing.
Prevent held-out labels or future edges from entering feature construction. More layers do not automatically help: excessive mixing can make node representations too similar.
The workshop uses a valid undirected graph and supplied weights to inspect one forward pass.
5. One Layer Reaches One Neighbourhood
One message-passing layer lets a node use its immediate neighbours. A second layer can bring information from neighbours of those neighbours because their first-layer representations already contain context.
The receptive field therefore grows with depth, but the number of distinguishable signals does not necessarily grow with it. Repeated mixing can wash out differences, and a narrow representation may compress many distant messages into very few coordinates.
6. Separate Graph Mixing from Feature Learning
The normalised adjacency determines which nodes exchange information and how it is scaled. The weight matrix determines how feature coordinates are combined. These are different axes of the calculation.
Check the graph operator on an unequal-degree example before adding learned features. Self-loops and degree normalisation should use the same augmented adjacency.
Normalise a three-node chain
The graph is undirected. We add one self-loop to every node before computing degrees.
import numpy as np
A = np.array([[0.,1.,0.],[1.,0.,1.],[0.,1.,0.]])
augmented = A + np.eye(3)
degree = augmented.sum(axis=1)
S = augmented/np.sqrt(degree[:,None]*degree[None,:])
print(np.round(S, 4).tolist())
print(bool(np.allclose(S, S.T)))[[0.5, 0.4082, 0.0], [0.4082, 0.3333, 0.4082], [0.0, 0.4082, 0.5]]
TrueSymmetric normalisation remains symmetric, but its rows are not required to sum to one. It is not the same operator as a random-walk transition matrix.
Check yourself
Questions on the Graph Mixing Operator
Question 1 of 1
Which property should we expect here?
Use this setup.
A is an undirected adjacency. Self-loops are added, then S = D^(-1/2)(A+I)D^(-1/2), using degrees from A+I.7. A Whole-Network Prediction Needs a Readout
Node embeddings give one representation per node. To predict a property of an entire pipe network, combine them into a graph representation. A sum retains a dependence on graph size; a mean removes that direct count effect.
Choose the readout to match the target. Total capacity and average condition need different information. Keep separate graphs separate during batching so nodes from one installation do not exchange messages with another.
8. Define What the Test Nodes Are Allowed to Reveal
In a transductive task, the graph and unlabelled test-node features may be available during fitting while their labels are held out. In an inductive task, the method must handle previously unseen nodes or graphs under a stated information boundary.
Neither protocol is automatically dishonest, but they answer different questions. Do not report a transductive result as evidence of transfer to an unseen installation. For link prediction, remove held-out edges before building the message-passing graph.
Check yourself
Questions on Parts 1 to 8
Question 1 of 4
What are the resulting degrees?
Use the information below.
A=[[0,1],[1,0]]. Add identity before calculating degrees.Try it with Botie
Build with Botie
Write and run Python