user@devops:~$ cat README.md
GraphSAGE + GAT -- link prediction from scratch
# Description
GraphSAGE (Hamilton 2017) and GAT (Velickovic 2018) implemented from scratch in PyTorch, no PyTorch Geometric. Part 1: 4x80-node SBM, p_in=0.10, p_out=0.012, 1,732 edges (71.9% intra), 16-d features (8 community signal + 8 noise), seed 42. Part 2: 70/10/20 edge split (train 1,213 / val 173 / test 346) and 1:1 negative sampling; the model only sees the residual graph (mean degree 7.58). Part 3: topological heuristics on A_train -- Common Neighbors AUC 0.5267, Adamic-Adar 0.5273, Preferential Attachment 0.5100. Part 4: feature MLP 1,600 params (no graph) AUC 0.7251; 2-layer mean GraphSAGE 3,200 params, early-stop epoch 18, test AUC 0.7407 / AP 0.7196 / Hits@10 0.399. Part 5: GAT 4 heads x 8d + 1 head x 32d, 1,664 params, dense masked attention, early-stop epoch 14, test AUC 0.7213. Part 6: Hits@K with 80 negatives per positive. Finding: hiding 30% of edges erases common neighbors so CN/AA collapse; community signal in X already gives the MLP 0.725 and SAGE message passing adds +1.6 pp (+21 pp vs Adamic-Adar). GAT does not beat SAGE on this small homophilous graph. CPU 21.2s. 7 visualizations.
# Key features
$ SBM 4 communities x 80 nodes, 1,732 edges, 71.9% intra-block, 16-d features
$ 70/10/20 edge holdout: the encoder only sees the residual graph (degree 7.58)
$ Heuristics: Common Neighbors 0.527, Adamic-Adar 0.527, Pref. Attachment 0.510
$ Feature MLP (no graph) 1,600 params, AUC 0.725 -- community lives in X
$ GraphSAGE mean aggregator 3,200 params, AUC 0.741 / AP 0.720 / Hits@10 0.399
$ Multi-head GAT (4x8 -> 1x32) 1,664 params, dense masked attention, AUC 0.721
$ Finding: with 30% edges hidden CN/AA fall to chance; SAGE +21 pp vs Adamic-Adar
$ 7 visualizations: overview, blocks, curves, ROC/PR, t-SNE, attention, metrics
# Gallery
# Technologies used