MixHop on Cora
Author: K3-Node Team
Backend: Multi-Backend
Dataset: Cora (Planetoid)
Description: Classify papers in the Cora citation network by topic.
MixHop on Cora
Classify papers in the Cora citation network by topic. MixHop (Abu-El-Haija et al., 2019) mixes neighbors at several distances in one layer: each layer concatenates the features of the node itself, its neighbors, and its 2-hop neighbors. Training uses SGD with a learning rate that drops 100x every 40 epochs.
Same model as PyG's examples/mixhop.py.
Install K3-Node, then choose a backend: "tensorflow", "torch" or "jax"
Load the data
data holds one graph: node features x, edges edge_index, labels y, and masks marking the training, validation and test nodes.
import keras
from keras import ops
from k3_node.datasets import Planetoid
from k3_node.loader import FullGraphDataset
dataset = Planetoid("data/Planetoid", name="Cora")
data = dataset[0]
print(data)
Define the model
from k3_node.layers import BatchNorm, MixHopConv
class MixHop(keras.Model):
def __init__(self, in_channels, out_channels):
super().__init__()
self.convs = [MixHopConv(in_channels, 60, powers=[0, 1, 2]),
MixHopConv(3 * 60, 60, powers=[0, 1, 2]),
MixHopConv(3 * 60, 60, powers=[0, 1, 2])]
self.norms = [BatchNorm(3 * 60) for _ in range(3)]
self.input_dropout = keras.layers.Dropout(0.7)
self.dropout = keras.layers.Dropout(0.9)
self.lin = keras.layers.Dense(out_channels)
def call(self, data, training=False):
x = self.input_dropout(data.x, training=training)
for conv, norm in zip(self.convs, self.norms):
x = norm(conv(x, data.edge_index), training=training)
x = self.dropout(x, training=training)
return self.lin(x)
model = MixHop(dataset.num_features, dataset.num_classes)
Train
FullGraphDataset feeds the whole graph to Keras; mask selects which nodes count in the loss and the accuracy.
model.compile(
optimizer=keras.optimizers.SGD(
learning_rate=keras.optimizers.schedules.ExponentialDecay(
0.5, decay_steps=40, decay_rate=0.01, staircase=True), # x0.01 every 40 epochs
weight_decay=0.005,
),
loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
weighted_metrics=["accuracy"],
)
model.fit(
FullGraphDataset(data, mask="train_mask"),
validation_data=FullGraphDataset(data, mask="val_mask"),
epochs=100,
verbose=2,
)