Graph Learning

Experiments recsys-amplification

Does the recommender amplify the rings, and by how much?

Links: CS224W L11 (recommender systems, LightGCN, the L11 frontier on recommenders as edge-rewiring operators), notebooks/project/retweet_thread.py §L11 (the same recommenders). Atlas: recommender systems; information ecosystems.

Question

A coordinated ring does not need to fool people directly. It is enough to fool the ranking: if the ring's retweets make its target accounts look popular, the recommender shows those accounts to real users, who then retweet them for real. How much extra exposure do the targets get from the ring, which recommenders are more exposed, does a feedback loop compound it, and how much does filtering detected accounts undo?

Hypotheses (written before running)

  1. Popularity amplifies. With a popularity recommender, the ring targets' share of recommendation slots is at least 1.2× their share in the counterfactual (the same world with every bot retweet deleted), in every world type.

  2. Personalisation dampens. The LightGCN-style propagation recommender amplifies less than popularity (smaller factor), because a bot's retweets reach a human's scores only through paths via the bot.

  3. Feedback compounds. Over 5 rounds in which users accept recommendations, the targets' excess exposure (factual minus counterfactual) grows.

  4. Filtering works. Dropping the retweets of the accounts a cross-world detector flags (top 3% of scores) removes at least 80% of the excess exposure.

Setup

Run: uv run marimo edit experiments/recsys-amplification/recsys_amplification.py and press the run button.

Added after a one-world prototype (not a test): an obscure-targets setting (target_rank = (300, 600)), because on world 0 the popularity ranking of already-popular targets did not move at all.

Results (summary; full tables in results.md)

Amplification factor = targets' share of recommendation slots with the bots' retweets / without them.

targets world popularity propagation excess removed by filtering (popularity)
popular naive 1.37 0.92 1.00
popular reciprocal 1.40 0.97 0.73
popular co-amplify 1.21 1.06 0.24
obscure naive 2.05 0.85 1.00
obscure reciprocal 2.03 0.95 1.00
obscure co-amplify 3.17 1.11 0.49

Next steps

  1. Rings whose volume grows with the platform (keep posting each round), the test of the H3 reading.
  2. A trained LightGCN (BPR loss) instead of the untrained propagation, and the hard-negative variants of L11.
  3. Exposure diversity (community mixing of what humans are shown), the metric regulators ask about.

Results

Generated by recsys_amplification.py from config.yaml (worlds [0, 1, 2], top 20, 5 feedback rounds, accept_p 0.05). Means over worlds.

targets world recommender share (factual) share (no bot retweets) factor position-weighted factor share (filtered) excess removed Recall@20 Recall@20 (no bots)
obscure co-amplify popularity 0.0553 0.0174 3.17 3.31 0.0368 0.49 0.063 0.064
obscure co-amplify propagation 0.0276 0.0250 1.11 1.19 0.0264 nan 0.086 0.087
obscure naive popularity 0.1242 0.0605 2.05 2.15 0.0606 1.00 0.068 0.066
obscure naive propagation 0.0266 0.0313 0.85 0.80 0.0314 nan 0.092 0.093
obscure reciprocal popularity 0.0309 0.0152 2.03 2.12 0.0153 1.00 0.073 0.073
obscure reciprocal propagation 0.0126 0.0132 0.95 0.91 0.0134 nan 0.096 0.097
popular co-amplify popularity 0.2289 0.1892 1.21 1.25 0.2196 0.24 0.080 0.077
popular co-amplify propagation 0.0721 0.0681 1.06 1.05 0.0678 nan 0.096 0.097
popular naive popularity 0.3029 0.2204 1.37 1.36 0.2201 1.00 0.094 0.093
popular naive propagation 0.0794 0.0862 0.92 0.91 0.0852 nan 0.104 0.105
popular reciprocal popularity 0.0750 0.0535 1.40 1.29 0.0592 0.73 0.075 0.074
popular reciprocal propagation 0.0288 0.0298 0.97 0.95 0.0297 nan 0.097 0.097

Excess share (factual − counterfactual) by feedback round:

targets world recommender round 0 round 1 round 2 round 3 round 4 round 5
obscure co-amplify popularity +0.0379 +0.0417 +0.0428 +0.0430 +0.0414 +0.0401
obscure co-amplify propagation +0.0027 +0.0027 +0.0010 -0.0004 -0.0028 -0.0038
obscure naive popularity +0.0636 +0.0608 +0.0585 +0.0575 +0.0572 +0.0560
obscure naive propagation -0.0047 -0.0055 -0.0046 -0.0047 -0.0037 -0.0041
obscure reciprocal popularity +0.0156 +0.0148 +0.0141 +0.0131 +0.0120 +0.0110
obscure reciprocal propagation -0.0006 -0.0011 -0.0009 -0.0005 -0.0005 -0.0010
popular co-amplify popularity +0.0397 +0.0405 +0.0394 +0.0367 +0.0346 +0.0302
popular co-amplify propagation +0.0039 +0.0036 +0.0027 +0.0027 +0.0029 +0.0024
popular naive popularity +0.0826 +0.0790 +0.0694 +0.0616 +0.0552 +0.0492
popular naive propagation -0.0068 -0.0068 -0.0066 -0.0058 -0.0072 -0.0079
popular reciprocal popularity +0.0215 +0.0140 +0.0083 +0.0053 +0.0031 +0.0017
popular reciprocal propagation -0.0010 -0.0013 -0.0017 -0.0021 -0.0026 -0.0034

Detector flags (top 3% of scores):

targets world precision recall
obscure co-amplify 0.35 0.43
obscure naive 0.81 1.00
obscure reciprocal 0.81 1.00
popular co-amplify 0.47 0.58
popular naive 0.81 1.00
popular reciprocal 0.75 0.92

Verdicts (popular targets, the pre-registered setting): H1 supported, H2 supported, H3 refuted, H4 refuted.

In the repository: experiments/recsys-amplification/ · README.md config.yaml recsys_amplification.py results.json results.md