Graph Learning

Experiments motif-signatures

Which small patterns give rings away, and can a few known accounts find the rest?

Links: CS224W L20 (classic graph ML at scale: label propagation), L21 (subgraphs and motifs, null models), notebooks/project/retweet_thread.py §L20–21 (label propagation and motif Z-scores on the same world). Atlas: motifs; coordinated inauthentic behaviour.

Question

The project notebook found reciprocal dyads and mutual triangles over-represented, mostly inside rings. But rings can be built without reciprocity (co-amplification), and real coordination research uses a different family of patterns: co-retweet and synchronised co-retweet networks (two accounts repeatedly amplifying the same posts, possibly within minutes; Pacheco et al. 2021, Weber & Neumann 2021). Which per-account pattern separates which kind of ring, does timing add anything once bots retweet with human-like delays, and which graph should label propagation run on?

Hypotheses (written before running)

  1. Reciprocity motifs are ring-specific. For reciprocal rings, reciprocal dyads and mutual triangles are the best single patterns (AUC ≥ 0.9); for co-amplification rings they are at most 0.6.

  2. Co-retweet motifs catch co-amplification. For co-amplification rings, the best single pattern is a co-retweet pattern (repeated co-retweets of the same posts with one partner, at any time or synchronised), with AUC ≥ 0.8.

  3. Timing helps only naive bots. Synchronised co-retweets (within 1 hour) beat the same pattern without a time window in naive worlds, but not in stealthy worlds (reciprocal and co-amplification), where bot delays are human-like.

  4. Propagate on the right graph. Label propagation from 3 known ring members and 30 known humans works better on the graph built from the world's best pattern than on the plain undirected retweet graph, in every world type.

Setup

Run: uv run marimo edit experiments/motif-signatures/motif_signatures.py and press the run button.

Results (summary; full tables in results.md)

pattern (AUC as an unsupervised ring score) naive reciprocal co-amplify
mutual triangles 1.000 0.808 0.474
reciprocal dyads 0.984 0.728 0.417
co-retweet: most posts shared with one partner 1.000 0.728 0.810
synchronised (1 h): most posts shared with one partner 1.000 0.286 0.469
all patterns, logistic regression 1.000 0.999 0.996

Next steps

  1. A cascade-preserving null for synchrony: re-simulate the independent cascade on the observed follow graph.
  2. Temporal motifs in the sense of Paranjape et al. (2017): δ-temporal motif counts per account.
  3. Weighted propagation on U + λ·C (plain reach plus co-retweet homophily), sweeping λ.

Results

Generated by motif_signatures.py from config.yaml (worlds [0, 1, 2]). Means over worlds.

Single-pattern AUC (unsupervised score):

pattern family naive reciprocal co-amplify
in-degree degree 0.553 0.400 0.480
out-degree degree 0.351 0.465 0.341
reciprocal dyads reciprocity 0.984 0.728 0.417
mutual triangles reciprocity 1.000 0.808 0.474
transitive triads transitivity 0.788 0.539 0.224
co-retweet: max with one partner co-retweet 1.000 0.728 0.810
co-retweet: partners ≥ 3 co-retweet 0.399 0.239 0.410
sync 1 h: max with one partner sync 1 h 1.000 0.286 0.469
sync 1 h: partners ≥ 3 sync 1 h 1.000 0.406 0.460
sync 6 h: max with one partner sync 6 h 1.000 0.436 0.595
sync 6 h: partners ≥ 3 sync 6 h 0.634 0.368 0.513
all patterns (logistic regression, CV) 1.000 0.999 0.996

Label propagation (3 known ring members, 30 known humans), AUC:

graph naive reciprocal co-amplify
undirected 0.981 0.905 0.584
mutual 0.899 0.775 0.574
co-retweet 0.754 0.947 0.719
sync 1 h 0.922 0.932 0.717
sync 6 h 0.877 0.961 0.762

Synchronised co-retweet pairs (≥ 3 posts within 1 h) vs a time-shuffled null:

world observed null inside rings
co-amplify 178 93.3 ± 7.1 2
naive 375 261.3 ± 10.7 135
reciprocal 208 112.9 ± 7.2 0

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

In the repository: experiments/motif-signatures/ · README.md config.yaml motif_signatures.py results.json results.md