Graph Learning

Experiments honest-splits

How much does a random split overestimate a bot detector?

Links: CS224W L05 (GNN training: dataset splits, transductive vs inductive, the L05 proof workshop on AUC), notebooks/project/retweet_thread.py §L05 and §L06–07 (the same detector). Atlas: evaluation; social networks.

Question

Graph benchmarks split nodes at random. In a coordination problem that means members of the same ring land on both sides of the split, and anything the model learns about one member (its targets, its partners, its label if the model uses neighbours' labels) transfers to the others for free. A platform never gets that: the campaign it must catch next month is made of accounts it has never labelled. How large is the gap between the number a paper would report and the number a deployment would see?

Hypotheses (written before running)

  1. Label-free model. For a detector that uses only features and structure (no labels of neighbours), a random node split and a ring-held-out split agree within 0.03 AUC.

  2. Label-aware model. For a detector that also uses training labels of neighbours (share of known-bot neighbours, label propagation), the random split overestimates the ring-held-out split by at least 0.10 AUC.

  3. New world = unseen rings. Training on one world and testing on another gives the label-free model about the same AUC as the ring-held-out split (within 0.03).

  4. Early detection. Testing on a new world observed only for its first 10 days (of 30) costs the label-free model at least 0.10 AUC against full observation.

  5. Link prediction. For Adamic–Adar, common neighbours and preferential attachment, a random edge split overestimates the temporal split (days 0–20 → new edges in days 20–30) by at least 0.05 AUC in every world type.

Setup

Run: uv run marimo edit experiments/honest-splits/honest_splits.py and press the run button. The notebook writes results.md and results.json.

Added after the first run (not tests): a features-only model, because the full label-free model was at the ceiling on reciprocal worlds; and a 1-hop-only label-aware model, to locate the leak.

Results (summary; full tables in results.md)

world model random ring-held-out cross-world early (day 10)
reciprocal label-free 0.996 0.991 0.995 0.894
reciprocal label-aware 1.000 0.754 0.919 0.730
co-amplify label-free 0.950 0.919 0.954 0.914
co-amplify label-aware 0.872 0.696 0.883 0.817

Hypothesis 5 held on synthetic worlds. Real networks grow by mechanisms nobody wrote down, so the gap could be larger, smaller or reversed. Five timestamped social networks from gl.datasets: CollegeMsg (messages), EU e-mail (temporal), Bitcoin OTC (trust ratings), MathOverflow (answers and comments) and Higgs Twitter (retweets only). Each pair's first interaction time decides its side of the split: pairs that first appear before the 80% quantile form the past graph, later pairs between two accounts already in the past graph are the temporal positives. The random split hides the same number of pairs drawn from all pairs. Negatives are random non-edges; three seeds; at most 5,000 positives per split.

  1. The leak is real. On every real network, the random split overestimates the temporal split by at least 0.05 AUC for common neighbours and for Adamic–Adar.

  2. Growth is rich-get-richer. For preferential attachment the gap (random − temporal) is smaller than for Adamic–Adar on every network, because new real ties attach to hubs more than they close triangles.

Run: the second button in the notebook (a few minutes; Higgs and MathOverflow are the large ones). Results go to real_results.json and a separate section of results.md.

Real-data results (summary; full table in results.md)

Random − temporal AUC (means over 3 seeds):

network common neighbours Adamic–Adar preferential attachment
CollegeMsg +0.127 +0.127 +0.079
EU e-mail (temporal) +0.048 +0.048 +0.041
Bitcoin OTC +0.042 +0.041 −0.090
MathOverflow +0.045 +0.045 −0.010
Higgs (retweets) −0.011 −0.011 −0.480

Next steps

  1. A trained GNN with label features (label trick, Wang & Leskovec 2021) under the same protocols.
  2. Train-time ring masking: drop the label features of a random half of known bots during training so the model cannot lean on them (the remedy the label trick uses).

  3. Temporal campaigns: rings that start mid-month, with a split by account creation time.

Results

Generated by honest_splits.py from config.yaml (worlds [0, 1, 2], cross-world pairs [[0, 1], [1, 2], [2, 0]]). Bot-detection AUC, means over worlds.

world model random ring-held-out cross-world early (day 10) random − ring-held-out
co-amplify features only 0.882 0.865 0.863 0.809 0.017
co-amplify label-aware 0.872 0.696 0.883 0.817 0.176
co-amplify label-aware, 1-hop only 0.938 0.864 0.962 0.902 0.074
co-amplify label-free 0.950 0.919 0.954 0.914 0.031
reciprocal features only 0.824 0.824 0.838 0.736 -0.000
reciprocal label-aware 1.000 0.754 0.919 0.730 0.246
reciprocal label-aware, 1-hop only 1.000 0.810 0.909 0.732 0.190
reciprocal label-free 0.996 0.991 0.995 0.894 0.005

Early detection (cross-world AUC by days of the test world observed):

world model day 3 day 5 day 10 day 15 day 20 day 30
co-amplify features only 0.657 0.707 0.809 0.825 0.852 0.863
co-amplify label-aware 0.727 0.737 0.817 0.822 0.870 0.883
co-amplify label-aware, 1-hop only 0.697 0.790 0.902 0.911 0.935 0.962
co-amplify label-free 0.707 0.816 0.914 0.920 0.941 0.954
reciprocal features only 0.720 0.749 0.736 0.792 0.817 0.838
reciprocal label-aware 0.582 0.602 0.730 0.805 0.854 0.919
reciprocal label-aware, 1-hop only 0.568 0.621 0.732 0.803 0.844 0.909
reciprocal label-free 0.701 0.782 0.894 0.964 0.979 0.995

Link prediction (AUC):

world heuristic random edge split temporal split random − temporal
co-amplify Adamic–Adar 0.848 0.708 +0.139
co-amplify common neighbours 0.842 0.706 +0.135
co-amplify preferential attachment 0.816 0.672 +0.144
reciprocal Adamic–Adar 0.848 0.722 +0.127
reciprocal common neighbours 0.842 0.721 +0.121
reciprocal preferential attachment 0.809 0.677 +0.132

Verdicts: H1 refuted, H2 supported, H3 refuted, H4 refuted, H5 supported.

Real-data extension

Generated by honest_splits.py (real-data extension) from config.yaml: networks ['collegemsg', 'email-eu-temporal', 'bitcoin-otc', 'mathoverflow', 'higgs-activity'], cut at the 80% quantile of first-contact times, seeds [0, 1, 2]. Link-prediction AUC, means over seeds.

network heuristic random edge split temporal split random − temporal
collegemsg Adamic–Adar 0.777 0.650 +0.127
collegemsg common neighbours 0.773 0.646 +0.127
collegemsg preferential attachment 0.887 0.808 +0.079
email-eu-temporal Adamic–Adar 0.943 0.894 +0.048
email-eu-temporal common neighbours 0.937 0.889 +0.048
email-eu-temporal preferential attachment 0.858 0.817 +0.041
bitcoin-otc Adamic–Adar 0.816 0.775 +0.041
bitcoin-otc common neighbours 0.814 0.772 +0.042
bitcoin-otc preferential attachment 0.840 0.930 -0.090
mathoverflow Adamic–Adar 0.930 0.885 +0.045
mathoverflow common neighbours 0.929 0.884 +0.045
mathoverflow preferential attachment 0.944 0.954 -0.010
higgs-activity Adamic–Adar 0.541 0.553 -0.011
higgs-activity common neighbours 0.541 0.552 -0.011
higgs-activity preferential attachment 0.447 0.927 -0.480

Share of random-split positives with a cold-start endpoint (degree 0 after hiding): collegemsg 0.03; email-eu-temporal 0.01; bitcoin-otc 0.12; mathoverflow 0.03; higgs-activity 0.55.

Verdicts: H6 refuted, H7 supported.

In the repository: experiments/honest-splits/ · README.md config.yaml honest_splits.py real_results.json results.json results.md