Skill Tracer
Skills › Scientific Agent Skills › torch-geometric › explainability.md

explainability.md

227 lines · skills/torch-geometric/references/explainability.md at 5f2bc03

Open on GitHub
1# GNN Explainability — Full Reference
2
3PyG provides `torch_geometric.explain` for interpreting GNN predictions. The module includes a unified `Explainer` interface, several explanation algorithms, visualization, and evaluation metrics.
4

GNN Explainability — Full Reference

PyG provides torch_geometric.explain for interpreting GNN predictions. The module includes a unified Explainer interface, several explanation algorithms, visualization, and evaluation metrics.

Raw lines 1 to 4
5## The Explainer Interface
6
7The `Explainer` class is the central entry point. Configure it with:
81. An explanation **algorithm** (GNNExplainer, PGExplainer, CaptumExplainer, etc.)
92. An **explanation type** (`"model"` — explain model predictions, or `"phenomenon"` — explain dataset patterns)
103. **Mask types** — which parts of the input to explain (nodes, edges, features)
114. **Post-processing** — how to threshold masks (top-k, hard, etc.)
13```python
14from torch_geometric.explain import Explainer, GNNExplainer
16explainer = Explainer(
17 model=model,
18 algorithm=GNNExplainer(epochs=200),
19 explanation_type='model', # 'model' or 'phenomenon'
20 node_mask_type='attributes', # 'object', 'common_attributes', 'attributes', or None
21 edge_mask_type='object', # 'object' or None
22 model_config=dict(
23 mode='multiclass_classification', # 'binary_classification', 'multiclass_classification', 'regression'
24 task_level='node', # 'node', 'edge', 'graph'
25 return_type='raw', # Raw logits; match the actual model output
26 ),
28```
30**Mask types explained:**
31- `'object'`: One value per node (`[N, 1]`) or per edge (`[E]`).
32- `'attributes'`: One mask value per node and feature, shape `[N, F]`.
33- `'common_attributes'`: One feature mask shared across all nodes, shape `[1, F]`.
34- `None`: Don't generate this mask type

The Explainer Interface

The Explainer class is the central entry point. Configure it with:

  1. An explanation algorithm (GNNExplainer, PGExplainer, CaptumExplainer, etc.)
  2. An explanation type ("model" — explain model predictions, or "phenomenon" — explain dataset patterns)
  3. Mask types — which parts of the input to explain (nodes, edges, features)
  4. Post-processing — how to threshold masks (top-k, hard, etc.)
from torch_geometric.explain import Explainer, GNNExplainer

explainer = Explainer(
    model=model,
    algorithm=GNNExplainer(epochs=200),
    explanation_type='model',          # 'model' or 'phenomenon'
    node_mask_type='attributes',       # 'object', 'common_attributes', 'attributes', or None
    edge_mask_type='object',           # 'object' or None
    model_config=dict(
        mode='multiclass_classification',  # 'binary_classification', 'multiclass_classification', 'regression'
        task_level='node',                  # 'node', 'edge', 'graph'
        return_type='raw',                  # Raw logits; match the actual model output
    ),
)

Mask types explained:

  • 'object': One value per node ([N, 1]) or per edge ([E]).
  • 'attributes': One mask value per node and feature, shape [N, F].
  • 'common_attributes': One feature mask shared across all nodes, shape [1, F].
  • None: Don't generate this mask type
Raw lines 5 to 35
36## Generating Explanations

Generating Explanations

Raw lines 36 to 37
38### Node classification
40```python
41# Explain prediction for node at index 10
42explanation = explainer(data.x, data.edge_index, index=10)
44print(explanation.node_mask) # [num_nodes, num_features] — importance per feature per node
45print(explanation.edge_mask) # [num_edges] — importance per edge
46```

Node classification

# Explain prediction for node at index 10
explanation = explainer(data.x, data.edge_index, index=10)

print(explanation.node_mask)   # [num_nodes, num_features] — importance per feature per node
print(explanation.edge_mask)   # [num_edges] — importance per edge
Raw lines 38 to 47
48### Graph classification
50```python
51explainer = Explainer(
52 model=model,
53 algorithm=GNNExplainer(epochs=200),
54 explanation_type='model',
55 edge_mask_type='object',
56 model_config=dict(
57 mode='multiclass_classification',
58 task_level='graph',
59 return_type='raw',
60 ),
63explanation = explainer(data.x, data.edge_index, batch=data.batch, index=0)
64```
66Pass every additional argument required by the model (e.g. graph assignment `batch`, edge weights or supervision edges). For an individual unbatched graph, construct a zero-valued node-to-graph assignment if the model requires it.

Graph classification

explainer = Explainer(
    model=model,
    algorithm=GNNExplainer(epochs=200),
    explanation_type='model',
    edge_mask_type='object',
    model_config=dict(
        mode='multiclass_classification',
        task_level='graph',
        return_type='raw',
    ),
)

explanation = explainer(data.x, data.edge_index, batch=data.batch, index=0)

Pass every additional argument required by the model (e.g. graph assignment batch, edge weights or supervision edges). For an individual unbatched graph, construct a zero-valued node-to-graph assignment if the model requires it.

Raw lines 48 to 67
68## Visualization
70```python
71# Visualize which features are most important (bar chart)
72explanation.visualize_feature_importance(path='feature_importance.png', top_k=10)
73# Needs a node feature mask and matplotlib.
75# Visualize the important subgraph
76explanation.visualize_graph(path='graph.png', backend='networkx')
77# Requires an edge mask plus matplotlib/networkx. path=None displays, not saves.
78```

Visualization

# Visualize which features are most important (bar chart)
explanation.visualize_feature_importance(path='feature_importance.png', top_k=10)
# Needs a node feature mask and matplotlib.

# Visualize the important subgraph
explanation.visualize_graph(path='graph.png', backend='networkx')
# Requires an edge mask plus matplotlib/networkx. path=None displays, not saves.
Raw lines 68 to 79
80## Available Algorithms

Available Algorithms

Raw lines 80 to 81
82### GNNExplainer
84Learns soft masks via optimization. Works for node and graph-level tasks. The most widely used algorithm.
86```python
87from torch_geometric.explain import GNNExplainer
89algorithm = GNNExplainer(epochs=200, lr=0.01)
90```

GNNExplainer

Learns soft masks via optimization. Works for node and graph-level tasks. The most widely used algorithm.

from torch_geometric.explain import GNNExplainer

algorithm = GNNExplainer(epochs=200, lr=0.01)
Raw lines 82 to 91
92### PGExplainer
94A parametric (trained) explainer — learns a neural network that generates edge masks. Must be trained before use; generalization to new graphs still needs evaluation. Only supports edge masks (no node masks).
96```python
97from torch_geometric.explain import PGExplainer
99explainer = Explainer(
100 model=model,
101 algorithm=PGExplainer(epochs=30, lr=0.003),
102 explanation_type='phenomenon', # PGExplainer explains phenomena
103 edge_mask_type='object',
104 model_config=dict(
105 mode='regression',
106 task_level='graph',
107 return_type='raw',
108 ),
109 threshold_config=dict(threshold_type='topk', value=10),
112# Keep the trained prediction model fixed in evaluation behavior.
113model.eval()
114# Train the explainer first, using only permitted training targets.
115for epoch in range(30):
116 for batch in loader:
117 loss = explainer.algorithm.train(
118 epoch, model, batch.x, batch.edge_index, target=batch.y, batch=batch.batch
119 )
121# Then explain
122explanation = explainer(data.x, data.edge_index, target=data.y,
123 batch=data.batch, index=0)
124```
126`phenomenon` requires `target=` both during training and explanation. This graph-regression recipe assumes model output and `data.y` have the same shape (for example `[num_graphs, 1]`). Node PGExplainer training also requires a single `index` per call.

PGExplainer

A parametric (trained) explainer — learns a neural network that generates edge masks. Must be trained before use; generalization to new graphs still needs evaluation. Only supports edge masks (no node masks).

from torch_geometric.explain import PGExplainer

explainer = Explainer(
    model=model,
    algorithm=PGExplainer(epochs=30, lr=0.003),
    explanation_type='phenomenon',     # PGExplainer explains phenomena
    edge_mask_type='object',
    model_config=dict(
        mode='regression',
        task_level='graph',
        return_type='raw',
    ),
    threshold_config=dict(threshold_type='topk', value=10),
)

# Keep the trained prediction model fixed in evaluation behavior.
model.eval()
# Train the explainer first, using only permitted training targets.
for epoch in range(30):
    for batch in loader:
        loss = explainer.algorithm.train(
            epoch, model, batch.x, batch.edge_index, target=batch.y, batch=batch.batch
        )

# Then explain
explanation = explainer(data.x, data.edge_index, target=data.y,
                        batch=data.batch, index=0)

phenomenon requires target= both during training and explanation. This graph-regression recipe assumes model output and data.y have the same shape (for example [num_graphs, 1]). Node PGExplainer training also requires a single index per call.

Raw lines 92 to 127
128### CaptumExplainer
130Wraps the [Captum](https://captum.ai/) library, giving access to gradient-based attribution methods. Works with both homogeneous and heterogeneous graphs.
132```python
133from torch_geometric.explain import CaptumExplainer
135# Supports: 'IntegratedGradients', 'Saliency', 'Deconvolution',
136# 'ShapleyValueSampling', 'GuidedBackprop', etc.
137algorithm = CaptumExplainer('IntegratedGradients')
138```
140Requires `uv pip install captum==0.9.0` for the reviewed runtime. Avoid blindly installing the PyG `full` extra: its released metadata still pins older Captum.

CaptumExplainer

Wraps the Captum library, giving access to gradient-based attribution methods. Works with both homogeneous and heterogeneous graphs.

from torch_geometric.explain import CaptumExplainer

# Supports: 'IntegratedGradients', 'Saliency', 'Deconvolution',
#           'ShapleyValueSampling', 'GuidedBackprop', etc.
algorithm = CaptumExplainer('IntegratedGradients')

Requires uv pip install captum==0.9.0 for the reviewed runtime. Avoid blindly installing the PyG full extra: its released metadata still pins older Captum.

Raw lines 128 to 141
142### AttentionExplainer
144Uses supported layers' captured attention coefficients as edge masks, with no explainer training. Support is operator-specific; the tested example uses `GATConv`. A layer having an attention mechanism (e.g. `TransformerConv`) does not alone establish hook compatibility. Attention weights are not causal evidence.
146```python
147from torch_geometric.explain import AttentionExplainer
149algorithm = AttentionExplainer()
150```

AttentionExplainer

Uses supported layers' captured attention coefficients as edge masks, with no explainer training. Support is operator-specific; the tested example uses GATConv. A layer having an attention mechanism (e.g. TransformerConv) does not alone establish hook compatibility. Attention weights are not causal evidence.

from torch_geometric.explain import AttentionExplainer

algorithm = AttentionExplainer()
Raw lines 142 to 151
152## Heterogeneous Graph Explanations
154For heterogeneous models, compatible algorithms return `HeteroExplanation` with per-type masks. Wrap dict-returning models so the explainer gets one tensor for the node type being explained; `index` then refers to rows of that type:
156```python
157from torch_geometric.explain import Explainer, CaptumExplainer
159class PaperOutput(torch.nn.Module):
160 def __init__(self, model):
161 super().__init__()
162 self.model = model
163 def forward(self, x_dict, edge_index_dict):
164 return self.model(x_dict, edge_index_dict)['paper']
166explainer = Explainer(
167 model=PaperOutput(hetero_model),
168 algorithm=CaptumExplainer('IntegratedGradients'),
169 explanation_type='model',
170 node_mask_type='attributes',
171 edge_mask_type='object',
172 model_config=dict(
173 mode='multiclass_classification',
174 task_level='node',
175 return_type='raw', # Wrapped model returns paper logits.
176 ),
179hetero_explanation = explainer(
180 data.x_dict,
181 data.edge_index_dict,
182 index=1, # Explain one target at a time for Captum.
185# Access per-type masks
186hetero_explanation.node_mask_dict # {'paper': tensor, 'author': tensor, ...}
187hetero_explanation.edge_mask_dict # {('paper','cites','paper'): tensor, ...}
188```

Heterogeneous Graph Explanations

For heterogeneous models, compatible algorithms return HeteroExplanation with per-type masks. Wrap dict-returning models so the explainer gets one tensor for the node type being explained; index then refers to rows of that type:

from torch_geometric.explain import Explainer, CaptumExplainer

class PaperOutput(torch.nn.Module):
    def __init__(self, model):
        super().__init__()
        self.model = model
    def forward(self, x_dict, edge_index_dict):
        return self.model(x_dict, edge_index_dict)['paper']

explainer = Explainer(
    model=PaperOutput(hetero_model),
    algorithm=CaptumExplainer('IntegratedGradients'),
    explanation_type='model',
    node_mask_type='attributes',
    edge_mask_type='object',
    model_config=dict(
        mode='multiclass_classification',
        task_level='node',
        return_type='raw',  # Wrapped model returns paper logits.
    ),
)

hetero_explanation = explainer(
    data.x_dict,
    data.edge_index_dict,
    index=1,  # Explain one target at a time for Captum.
)

# Access per-type masks
hetero_explanation.node_mask_dict    # {'paper': tensor, 'author': tensor, ...}
hetero_explanation.edge_mask_dict    # {('paper','cites','paper'): tensor, ...}
Raw lines 152 to 189
190## Evaluation Metrics
192```python
193from torch_geometric.explain import unfaithfulness, fidelity, characterization_score
195# Unfaithfulness compares model prediction distributions after masking.
196# Lower means closer under this masking experiment.
197score = unfaithfulness(explainer, explanation)
199# Fidelity: measures explanation quality via positive/negative fidelity
200pos_fidelity, neg_fidelity = fidelity(explainer, explanation)
202# Characterization score: combined metric
203char_score = characterization_score(pos_fidelity, neg_fidelity)
204```

Evaluation Metrics

from torch_geometric.explain import unfaithfulness, fidelity, characterization_score

# Unfaithfulness compares model prediction distributions after masking.
# Lower means closer under this masking experiment.
score = unfaithfulness(explainer, explanation)

# Fidelity: measures explanation quality via positive/negative fidelity
pos_fidelity, neg_fidelity = fidelity(explainer, explanation)

# Characterization score: combined metric
char_score = characterization_score(pos_fidelity, neg_fidelity)
Raw lines 190 to 205
206## Post-Processing Masks
208Control how raw mask values are converted to final explanations:
210```python
211explainer = Explainer(
212 ...,
213 threshold_config=dict(
214 threshold_type='topk', # 'topk', 'topk_hard', or 'hard'
215 value=10, # Top-10 edges for 'topk', threshold value for 'hard'
216 ),
218```
220- `'topk'`: Keep only top-k highest-scored elements
221- `'hard'`: Binary threshold — elements above `value` are kept
222- `'topk_hard'`: Binarize the retained top-k entries.
223- Omit `threshold_config` to return continuous masks.
225Mask scores and fidelity metrics characterize a model under a chosen baseline/perturbation, not molecular mechanisms or causality. Check stability across seeds and correlated features, and report whether masking creates off-distribution graphs. Fit explainers on training data and reserve evaluation explanations for held-out analysis. Heterogeneous metrics/visualizers need separate support checks.
227Sources: [explain interface](https://pytorch-geometric.readthedocs.io/en/latest/modules/explain.html), [PGExplainer](https://pytorch-geometric.readthedocs.io/en/latest/generated/torch_geometric.explain.algorithm.PGExplainer.html), [CaptumExplainer](https://pytorch-geometric.readthedocs.io/en/latest/generated/torch_geometric.explain.algorithm.CaptumExplainer.html).

Post-Processing Masks

Control how raw mask values are converted to final explanations:

explainer = Explainer(
    ...,
    threshold_config=dict(
        threshold_type='topk',    # 'topk', 'topk_hard', or 'hard'
        value=10,                  # Top-10 edges for 'topk', threshold value for 'hard'
    ),
)
  • 'topk': Keep only top-k highest-scored elements
  • 'hard': Binary threshold — elements above value are kept
  • 'topk_hard': Binarize the retained top-k entries.
  • Omit threshold_config to return continuous masks.

Mask scores and fidelity metrics characterize a model under a chosen baseline/perturbation, not molecular mechanisms or causality. Check stability across seeds and correlated features, and report whether masking creates off-distribution graphs. Fit explainers on training data and reserve evaluation explanations for held-out analysis. Heterogeneous metrics/visualizers need separate support checks.

Sources: explain interface, PGExplainer, CaptumExplainer.

Raw lines 206 to 227