Message passing lets a graph neural network (GNN) use relationships, not just isolated features. Each node receives information from its neighbors and uses it to update its representation. The resulting embeddings can support node classification, link prediction, and graph-level prediction. It is most useful when connections between data points carry information; it offers less advantage for standalone entries with little meaningful relational structure. section 1.5.3 section 1.6
A message-passing layer follows a short pipeline:
- Collect messages from each node’s immediate neighbors, using available node or edge features. section 1.5.3
- Aggregate the messages into one neighborhood vector with an invariant operation such as sum, mean, or max. section 1.5.3
- Transform the aggregated information with a neural network, then update the node’s features or embedding. The update can combine neighborhood information with the node’s own features. section 1.5.3 section 2.2.1
One layer incorporates information from nearby nodes; successive layers let information travel across more hops. The output of each layer is another set of features or embeddings. Graph convolutional networks (GCNs) and GraphSAGE use different ways to carry out these operations, while graph attention networks learn how strongly to weight messages during aggregation. section 1.5.3 section 3.4.2
Implementing a two-layer pass
A PyTorch Geometric model can apply `GCNConv` to node features `x` and graph connections `edge_index`, follow it with `torch.relu` and dropout, then apply a second `GCNConv`. Even before training, a pass produces preliminary node embeddings; optimization can tailor them to a prediction task. GraphSAGE offers another pattern: aggregate sampled neighbors, combine their embeddings with the central node’s, then transform and normalize the result. section 2.2.1 section 3.4.6
Listing 2.4 Our SimpleGNN class
class SimpleGNN_embeddings(torch.nn.Module):
def __init__(self, num_features, hidden_channels): #1
super(SimpleGNN, self).__init__()
self.conv1 = GCNConv(num_features, \
hidden_channels) #2
self.conv2 = GCNConv(hidden_channels,\
hidden_channels) #3
def forward(self, x, edge_index): #4
x = self.conv1(x, edge_index) #5
x = torch.relu(x) #6
x = torch.dropout(x, p=0.5, train=self.training) #7
x = self.conv2(x, edge_index) #8
return x #9
The model listing shows two `GCNConv` message-passing layers and the `x, edge_index` inputs they use. section 2.2.1
Keep the graph context available during training: a node’s prediction may depend on neighbors outside the training mask, so masking the loss does not mean passing only masked nodes through the model. More layers also are not automatically better; a shallow GCN may help avoid over-smoothing. section 4.3.2








