Letting a Node Read Its Neighbours’ Measurements
A pump’s neighbours can provide useful context. Aggregate their readings while retaining the distinction between a node and its surroundings.
13 sections · 4 questions · 2 coding challenges
The arrow keys move between sections too.
Learning How to Combine Local Neighbourhoods
BOTIE
Before adding learned transformations, let's calculate the mean of all a node's neighbours. That smaller operation lets us see exactly which readings reach each node. GraphSAGE also samples neighbours and learns how to combine their information; our first example isolates the gathering step.
Sources for this history
What Can the Nearby Pumps Tell Us?
One pump reports low pressure. Its neighbours might reveal whether the whole region is affected or just that instrument. We need a calculation that gathers measurements from connected nodes.
Neighbour aggregation collects those values with a sum, mean, or another declared rule. It is the information-sharing step on which many graph models build.
The network and scalar readings are illustrative and use matching node order.
Step 1 of 3
Start with one feature per node
The graph is a three-node chain.
Nodes and properties (3)
- 0: intake · Own reading: 2
- 1: pump · Own reading: 8
- 2: outlet · Own reading: 4
- 0: intake connected to 1: pump
- 1: pump connected to 2: outlet
Step 2 of 3
Collect adjacent readings
The middle node sees both ends.
Nodes and properties (3)
- 0: intake · Receives: 8
- 1: pump · Receives: 2 and 4
- 2: outlet · Receives: 8
- 0: intake connected to 1: pump
- 1: pump connected to 2: outlet
Step 3 of 3
Average without changing row identity
Return one neighbour summary per node.
| Receiving node | Neighbour readings | Neighbour mean |
|---|---|---|
| 0: intake | 8 | 8 |
| 1: pump | 2, 4 | (2 + 4) / 2 = 3 |
| 2: outlet | 8 | 8 |
0: intake
- Neighbour readings
- 8
- Neighbour mean
- 8
1: pump
- Neighbour readings
- 2, 4
- Neighbour mean
- (2 + 4) / 2 = 3
2: outlet
- Neighbour readings
- 8
- Neighbour mean
- 8
Aggregation gives each node a summary of its neighbourhood
Each output remains attached to a node while summarising its neighbourhood.
What can a pump learn from the readings next door?
Change one node's reading and check which neighbouring outputs respond. The calculation must retain node identities even when it replaces individual readings with local averages.
BOTIE
Mean neighbour reading for each node
- 08
- 13
- 28
Follow the operations
1. Binary adjacency matrix
0 1 0 1 0 1 0 1 0 2. Node readings
- 02
- 18
- 24
3. Matrix times vector
- 08
- 16
- 28
4. Add each row
- 01
- 12
- 21
5. Divide with an explicit zero fallback
- 08
- 13
- 28
6. Result
- 08
- 13
- 28
The zero fallback is explicit. For directed graphs, choose message orientation before multiplying.
1. Define Which Nodes Send Messages
In our undirected graph, a node receives from every adjacent node. Multiplying adjacency by a feature vector sums neighbouring values. For directed graphs, row orientation must match the intended message direction.
A message may later include edge features or a learned transform. Begin with raw scalar readings so you can check which values reached each node.
Node feature order and adjacency order must match exactly.
2. Choose Sum or Mean Deliberately
A sum changes with both neighbour values and neighbour count. A mean removes that direct degree scaling. Neither is universally better: total load and typical neighbouring pressure are different questions.
Readings = [2,8,4]
Neighbour sums = [8,6,8]
Degrees = [1,2,1]
Neighbour means = [8,3,8]An isolated node has no neighbour mean; our implementation returns zero with that policy stated.
3. Keep Own and Neighbour Features Distinct
The node’s own measurement may remain valuable even when neighbours disagree. A learned model can concatenate own features with the aggregate or add a separately transformed self contribution.
Adding self-loops before averaging is another rule, but it changes the denominator and the meaning of the summary. Do not silently substitute one for another.
This lesson excludes self from the neighbour mean. The next lesson introduces self-loops explicitly.
Average the readings attached to one node's neighbours
The adjacency row selects two neighbours from the same ordered reading array. Keep their identities during selection before reducing their readings to one average.
import numpy as np
adjacency_row = np.array([0, 1, 1])
readings = np.array([20., 4., 10.])
neighbour_readings = readings[adjacency_row.astype(bool)]
print(neighbour_readings.tolist())
print(float(neighbour_readings.mean()))[4.0, 10.0]
7.0The node's own reading of twenty is excluded by this row. Practice computes all nodes' summaries and handles the case where no neighbour is selected.
4. Avoid Washing Out Differences
Repeated averaging spreads information farther across the graph. It can also make different nodes’ representations increasingly similar, reducing the distinctions needed for prediction.
Useful context depends on the edge definition. Connected nodes do not always share labels or operating modes. Evaluate whether the chosen aggregation helps the actual task.
The workshop returns neighbour context, not a trained node classifier.
5. Neighbours Are a Set, Not a Meaningful Input Order
Renumbering the neighbours should not change their summed or averaged message. A learned operation applied to each neighbour followed by a sum or mean preserves that order independence.
A flattened list fed into an ordinary dense layer generally treats positions differently. That can be appropriate if positions have roles, but arbitrary neighbour enumeration should not create those roles. Keep edge direction and edge attributes when they carry relevant information.
6. Repeated Averages Can Remove the Difference We Needed
Averaging nearby readings provides context, but repeated averaging can make connected nodes increasingly alike. That is useful for smoothing noise and harmful when the prediction depends on a local contrast.
Retaining a separate self representation, using a limited number of layers or designing another message rule can preserve information. Those are modelling choices to evaluate, not guarantees that every graph benefits from deeper aggregation.
Watch two pump readings become identical
Each pump averages itself with the other using this supplied mixing matrix.
import numpy as np
mix = np.array([[.5,.5],[.5,.5]])
features = np.array([[0.],[10.]])
once = mix@features
twice = mix@once
print(once[:,0].tolist())
print(twice[:,0].tolist())[5.0, 5.0]
[5.0, 5.0]The original difference is gone after one step. A later layer cannot recover it from these identical features alone.
7. Connected Does Not Necessarily Mean Similar
A supply pump may connect to a demand pump whose normal behaviour is different. Averaging them as though neighbours should agree can erase useful roles. This situation is often described as heterophily when linked nodes tend to have different labels or features.
Inspect what the edges actually represent and compare with a model using each node's own features. For an isolated node, define an empty-neighbour policy and preserve its self information rather than creating an undefined mean.
Check yourself
Questions on Parts 1 to 7
Question 1 of 4
What is their mean?
Use the information below.
Middle node neighbours have readings [2,4].Try it with Botie
Build with Botie
Write and run Python