A mask is a Boolean array—or a Boolean tensor in PyTorch—that selects specific data elements. In graph learning, a node mask commonly identifies which nodes belong to a training, validation, or test subset. Each position must refer to the same node across the mask, labels, and features. section 8.3 section 2.3.1
To set up a semi-supervised node-classification task:
- Create one position per node, then randomly select the indices whose labels will be available for training. One example selects 20% of nodes. section 2.3.1
- Initialize `labelled_mask` to `False` and `unlabelled_mask` to `True`. Flip both values at the selected indices. section 2.3.1
- Apply the labeled mask to both embeddings and numeric labels when constructing supervised training arrays. If embeddings come from a separate source, first put them in the graph’s node order. section 2.3.1
Listing 2.5 Preprocessing for semi-supervised problem
labels = []
for node, data in gml_graph.nodes(data=True): #1
if data['value'] == 'c':
labels.append('right')
elif data['value'] == 'l':
labels.append('left')
else:
labels.append('neutral')
labels = np.array(labels)
random.seed(52) #2
indices = list(range(len(labels))) #3
labelled_percentage = 0.2 #4
labelled_indices = random.sample(indices, \
int(labelled_percentage * len(labels))) #5
labelled_mask = np.zeros(len(labels), dtype=bool) #6
unlabelled_mask = np.ones(len(labels), dtype=bool)
labelled_mask[labelled_indices] = True #7
unlabelled_mask[labelled_indices] = False
labelled_labels = labels[labelled_mask] #8
unlabelled_labels = labels[unlabelled_mask]
label_mapping = {'left': 0, 'right': 1, 'neutral': 2} #9
numeric_labels = np.array([label_mapping[label] for label in labels])
Listing 2.5 shows the sampled indices and the two complementary NumPy masks. section 2.3.1
Listing 2.6 Preprocessing: constructing training data
X_train_gnn = gnn_embeddings[labelled_mask] #1 Y_train_gnn = numeric_labels[labelled_mask] X_n2v = np.array([embeddings[str(node)] \ for node in gml_graph.nodes()]) #2 X_train_n2v = X_n2v[labelled_mask] #3 y_train_n2v = numeric_labels[labelled_mask] #3
Listing 2.6 shows the same labeled mask selecting corresponding embeddings and labels, including the extra node-order alignment for N2V embeddings. section 2.3.1
A training mask controls which predictions contribute to loss; it need not restrict the graph passed to a GNN. A GCN still receives the full graph for its forward pass because message passing uses neighbors to update node representations. The loss is then computed only for training nodes. In a PyTorch training loop, `out[data.train_mask]` selects those predictions before comparison with their known labels. section 4.3.2 section 2.3.3
Listing 2.9 Training loop
for epoch in range(3000): #1
optimizer.zero_grad()
_, out = model(data.x, data.edge_index) #2
out_masked = out[data.train_mask] #3
loss = loss_fn(out_masked, train_labels) #4
loss.backward()
optimizer.step()
if epoch % 10 == 0: #5
print(f'Epoch {epoch}, Log Loss: {loss.item()}')
Listing 2.9 makes the distinction visible: the model processes `data.x` and `data.edge_index`, then `data.train_mask` selects predictions for loss computation. section 2.3.3






