Three synthetic tissue fields, cells coloured by their ground-truth roleA 600-micrometre strip through three positive fields. Faint dots are stroma and macrophages; mid-grey are decoy T cells, causally inert by construction; darker are unengaged tumour cells, which count as evidence against the label; the coloured cells are the drivers — engaged tumour cells and the T cells enabling them. Every role is recorded when the sample is generated, before any model sees it.

Benchmarking graph neural network attribution on synthetic tissue graphs

Graph attribution methods are evaluated on real tissue, where the cells that actually drive the outcome are unknown, so faithfulness gets asserted rather than measured. This builds tissue where the driver cells are recorded at generation time as a signed attribution vector, with 93 acceptance tests guarding the generator against shortcuts and cell overlap. Against that ground truth most standard methods score no better than random, and one scores below it. Pooled, a marker heuristic that never consults the model appears to match the best learned method, but the two label classes pose structurally different problems, and split by class integrated gradients wins.

The problem

Give a graph neural network a slice of tumour tissue, one node per cell, and it will predict a tissue-level outcome. The question everyone asks next is which cells drove the prediction, and there is a standard toolkit for answering it: GNNExplainer, attention rollout, integrated gradients. Papers use these outputs to make biological claims.

The difficulty is that these methods are evaluated on real tissue, where the cells that actually drive the outcome are unknown. A method highlights some cells, the cells look plausible, and the explanation is accepted. Faithfulness gets asserted rather than measured, because on real data there is nothing to measure it against. The claim is not so much unverified as unfalsifiable.

Building tissue where the answer is known

The way out is to give up on real tissue and construct a setting where the answer is written down in advance. Cells get a type, a six-channel marker vector and a position, placed under rules I control. The label is then defined as an explicit function of that cell table: a sample is positive when the fraction of tumour cells with a cytotoxic T cell within 30 µm exceeds a threshold.

Because the rule is mine, every cell that participates can be recorded at generation time. That recording is the whole point of the exercise, and it is more than a list of important cells.

Recorded per sampleWhat it is
constructive driversengaged tumour cells and the T cells enabling them
counterfactual setan irredundant set whose removal flips the label, verified by leave-one-out
decoysT cells with identical markers sitting away from any tumour, causally inert
signed relevance+1 for evidence, −1 for counter-evidence, 0 for irrelevant

The signed vector matters more than it looks. The score is a ratio, so unengaged tumour cells sit in the denominator and removing one raises the score. They are evidence against the positive class, and a method that assigns them negative attribution is being correct. An earlier version of the protocol scored attributions against a binary mask and would have marked exactly that behaviour wrong.

Six panels of synthetic tissue. The top row shows positive samples and the bottom row negative ones. Engaged tumour cells and the T cells enabling them are marked in red and dark blue, unengaged tumour cells in orange, decoy T cells in pale blue, with macrophages and stroma in grey.
Fig 1. Six generated samples, positives on top. The engaged region is where T cells sit on tumour; everything else is background or decoy.

What the generator has to guarantee

A synthetic benchmark is only worth as much as its generator, and mine was wrong twice before it was right. The first version was 93 % solvable without looking at a single tumour cell: local T cell density alone reached AUC 0.928, because I had placed one enabling T cell per engaged tumour cell, which oversupplied them fourfold and left a density signature a model could read directly. Any faithfulness number computed on that data would have been measuring a shortcut.

The second problem was physical. Cells were drawn as independent points with no minimum separation, so 2.23 % of them overlapped and about 7.7 % of driver cells had a partner closer than 2 µm. No attribution method, graph or pixel, can separate two cells occupying the same point, so that put an irreducible floor under the headline metric before any method was tested.

Both were caught by acceptance tests written before the implementation, and the fixes are matched aggregate density between driver and decoy T cells, and hard-core placement with an 8 µm minimum separation. The suite now runs 93 tests across five gated phases, including shortcut probes that must sit at chance and a check that the label recomputes exactly from the serialised record.

The models

Cells become nodes carrying only their marker vectors, connected by a radius graph with the distance as an edge feature. Cell type is never a feature; it has to be inferred from markers, which is what makes the probing question below meaningful. I trained GIN and GATv2 at four ratios of graph radius to label radius, plus a CNN on a rendered image of the same field as a non-graph baseline sharing the same splits.

Every model reaches test AUC around 0.999. That matters for a reason that is easy to skip: you cannot meaningfully ask what a broken classifier was attending to. If attribution fails here, it fails against a model that solved the task.

What the representation already encodes

Before scoring any explanation, it is worth asking what the trained network actually represents. Linear probes on the frozen encoder answer that, but only if they are read against the right floor. The informative comparison is not against chance, it is against the same architecture with random weights.

Linear probe scores on trained versus randomly initialised encoders Whether a tumour cell is engaged is decodable at AUC 1.000 from both a trained and an untrained encoder. Driver status likewise, 0.999 against 0.998. Only the graph-level score shows a real gap, 0.924 trained against 0.768 untrained. 1.000 trained 1.000 untrained is_engaged (tumour cells) 0.998 trained 0.996 untrained is_driver 0.924 trained 0.768 untrained graph score (the task) linear probe score on a frozen encoder
Fig 2. Node-level driver properties come free from message passing. Only the readout is learned.

The driver property is linearly decodable at AUC 1.000 from a randomly initialised network. At this radius, asking whether a tumour cell has a T cell within the label distance is a one-hop aggregate, and any message-passing layer computes it whether trained or not. Training adds nothing at the node level and shows up only in the graph-level readout.

This reframes everything downstream. If a method recovers the driver cells, that may reflect structure present in any network over this graph rather than anything the model learned. The randomisation control stops being a formality and becomes the result.

How attribution gets scored

Each method returns one signed score per cell, computed with respect to the positive-class logit. Those get scored four ways: average precision against the counterfactual set, rank correlation against the signed relevance vector, the share of attribution landing on inert decoys, and deletion and insertion curves computed on logits rather than probabilities.

Alongside the learned methods run six baselines, and these are not decoration. One is a marker heuristic asking only whether a cell looks like a tumour cell. Another is distance to the nearest T cell. If a learned method cannot beat these, that is the finding.

Results

Average precision at recovering the driver cells, by method Random guessing scores 0.058. GNNExplainer scores 0.047, below guessing. Saliency 0.087, attention rollout 0.090, integrated gradients 0.147 for the zero baseline and 0.159 for the dataset-mean one. A marker heuristic that never consults the model scores 0.169, the highest of these pooled scores. marker heuristic (no model) 0.169 integrated gradients (mean) 0.159 integrated gradients (zero) 0.147 attention rollout 0.090 saliency 0.087 random guess 0.058 GNNExplainer 0.047 average precision at finding the driver cells
Fig 3. Higher is better. The dashed line is random guessing.

GNNExplainer, the most widely used of these tools, lands at 0.047 against a random baseline of 0.058. It is worse than guessing, and stays worse across every optimisation budget I tested. Attention rollout reaches 0.090. The best graph method is integrated gradients, at 0.159 for the dataset-mean variant and 0.147 for the zero-baseline one.

The awkward line is the highlighted one. A heuristic that projects the marker vector onto the tumour mean and consults no model at all scores 0.169, above every graph explanation method tested.

That reading does not survive splitting the two label classes, and the split is the more useful result. A positive sample flips by removing the T cells that engage tumour, a negative one by removing unengaged tumour cells until the ratio crosses the threshold, so the two classes pose structurally different targets: 92% of the variance in a pooled paired difference lies between them rather than within, and averaging the two hides two large opposite effects. Integrated gradients beats the heuristic by 0.302 average precision on positive samples and loses by 0.237 on negatives; weighted to the test split’s own class balance it wins overall, by 0.018. On the positive class, the one where the ground truth is a genuine minimal sufficient cause, the heuristic scores about a third of chance.

methodAPrandomisation ρ
across both modes
decoy mass
integrated gradients (mean)0.159−0.39 to +0.600.156
attention rollout0.090+0.17 to +0.990.224
saliency0.087−0.21 to +0.600.214
GNNExplainer0.047+0.37 to +0.860.149
random baseline0.058—0.156

Where the attribution mass goes

Average precision says whether a method ranks the right cells highly. It says nothing about where the rest of the mass ends up. The decoys exist for that: T cells with markers identical to the enabling ones, placed away from any tumour, contributing nothing to the label.

Share of attribution landing on causally inert decoy cells Local CTL density places 42.3 percent of its attribution on decoys, the highest of any method. Integrated gradients on the CNN 26.2, attention rollout 22.4, saliency 21.4. Random sits at 15.6 percent. Tumour-likeness is lowest at 5.6 percent. tumour-likeness 0.056 distance to nearest CTL 0.086 GNNExplainer 0.149 integrated gradients 0.156 random 0.156 saliency 0.214 attention rollout 0.224 integrated gradients (CNN) 0.262 local CTL density 0.423 share of attribution landing on inert decoy cells
Fig 4. Lower is better. The dashed line is the random baseline; anything above it is drawn to decoys more than chance would be.

Local T cell density, included precisely as a shortcut detector, puts 42 % of its mass on decoys. Attention rollout and the CNN sit well above the random line too. Integrated gradients and GNNExplainer are near chance, which for GNNExplainer is less reassuring than it sounds given it was not finding the drivers either.

The controls that decide whether any of this counts

Randomise the network’s weights and run the methods again. If the output barely changes, the method was never reading the model. This is a cheap test and it is the one that matters most here, because Fig 2 established that the graph alone carries the driver structure.

Rank correlation between each method's attributions and its attributions on a randomised network At r_graph over r_label equal to 2. Under cascading randomisation attention rollout on GATv2 reaches 0.993 and GNNExplainer 0.796 on GATv2 and 0.375 on GIN, all at or near the 0.5 void threshold. Under full randomisation integrated gradients stays near zero on both architectures, the only family that clearly survives. full randomisation n/a 0 0.5 1 cascading randomisation n/a 0 0.5 1 attention rollout GNNExplainer int. gradients (zero) int. gradients (mean) saliency GIN GATv2 rank correlation with attributions from a randomised network · dashed line is the 0.5 void threshold
Fig 5. Higher is worse: a method whose output survives randomising the weights was not reading the model. Attention rollout is GATv2-only.

Attention rollout returns attributions 0.957 to 0.993 rank-correlated with its own output on a randomised network under the cascading variant. GNNExplainer sits at 0.37 to 0.86 depending on architecture and radius, near-total on GATv2 and weaker on GIN at the densest graph. Integrated gradients is the only method that survives full randomisation cleanly.

Two further controls point the same way. Methods applied to encoders trained on shuffled labels still reach AP up to 0.343 against the true driver sets, higher than any method manages on a correctly trained model. And several score better from an untrained network than a trained one. An explanation that improves when you delete the model’s training is not explaining the model.

A result that generalises past this testbed

GNNExplainer randomisation correlation against optimisation budget Correlation with a randomised network falls from 0.852 at 30 epochs to 0.554 at 100, 0.366 at 200 and 0.283 at 400, then 0.340 at 800. The common default of 100 epochs sits partway down the slope. 0.2 0.4 0.6 0.8 30 100 200 400 800 common default optimisation epochs, log scale
Fig 6. The same control returns a different verdict depending on how long you run it.

The randomisation number is not a fixed property of GNNExplainer. It depends on how long the mask is optimised, moving from 0.85 at 30 epochs to 0.28 by 400. At 30 epochs the mask has barely left its random initialisation, and two under-optimised masks correlate with each other for reasons that have nothing to do with the model.

The common default is 100 epochs, partway down that slope, where the number has not converged. Anyone reporting this control should state the budget they ran it at. I have not seen that done.

Does any of it move if you retrain?

Average precision by method across three training seeds GNNExplainer stays between 0.028 and 0.068 across all six model-seed combinations, at or below the random baseline of 0.058 in five of them. Attention rollout runs 0.064 to 0.123, saliency 0.057 to 0.145, and integrated gradients 0.135 to 0.283. The ordering of methods is stable; the absolute numbers move by up to a factor of two. 0.0 0.1 0.2 0.3 random = 0.058 GNNExplainer attention rollout saliency int. gradients (mean) GIN GATv2 average precision at finding the driver cells · three training seeds per architecture
Fig 7. Three training seeds per architecture. The dashed line is random guessing.

Retraining each architecture from three seeds moves the absolute numbers by up to a factor of two — integrated gradients runs 0.135 to 0.283 — but not the ordering, and not the verdict on any method. GNNExplainer never clears the random line on GATv2 at any seed, and its randomisation correlation stays in a tight band: 0.83 to 0.89 on GATv2, 0.29 to 0.37 on GIN. The spread is wide enough that a single-seed comparison between two mid-table methods would not mean much, which is worth saying plainly given how often one is reported.

What I got wrong

Besides the two generator defects, I got the GNNExplainer verdict wrong twice in opposite directions. I first called it void on a correlation of 0.93, discovered that figure was an artefact of running only 30 epochs, and retracted. Then I over-corrected, generalising to “not void” from a single measurement at the most favourable setting in the grid. The settled answer, across the full grid at a converged budget, is 0.37 to 0.86: it does largely fail, but not at the number I first published.

Both corrections are in the repository rather than tidied away. The sequence 0.93 to 0.29 to 0.38–0.86 is more informative than any single number from it.

The larger error was in the headline. I reported that nothing learned beat the best model-free baseline, which was an artefact of averaging over two label classes whose ground truths are structurally different, drawn from a sample I had not stratified by label. Ninety-two per cent of the variance I was treating as noise was that class split. Conditioned on class the conclusion reverses, and the pooled version is withdrawn.

Scope

This is synthetic tissue and one family of labels. It does not show that these methods fail on real data, and a method that misses my driver cells could still point somewhere biologically useful. Driver sets here are also spatially contiguous, which hands any method with a smoothness prior an unearned advantage; a blob baseline scores 0.099 on that alone.

I built a second label family with sparse drivers to test whether the findings survive a harder task. No model could learn it: both architectures sit at chance while a direct count of the motif separates the classes perfectly. Counting a triangle motif is provably outside what these architectures can represent, so the harder question stays open, and the attempt produced a boundary condition instead. Faithfulness benchmarks are limited by model expressiveness, not only by label design.

What does hold is narrower and still worth saying. When the answer is checkable, most of these methods did not recover it, the most widely used one scored below chance, and the control that exposes this costs minutes to run. Code, figures and the gated test suite are in the repository.