gsnn.gsnn.interpret.OcclusionExplainer

class gsnn.gsnn.interpret.OcclusionExplainer(model, data, ignore_cuda=False, batch_size=32)[source]

Bases: object

Edge/node occlusion explainer for single observations.

Computes per-edge or per-node attributions for a prediction f(x)[target_idx] by systematically removing each element and measuring the change in prediction.

For edge-level attributions:

Occ_e = f(x; mask_baseline) - f(x; mask_e_removed)

For node-level attributions:

Occ_n = f(x; mask_baseline) - f(x; mask_n_removed)

where mask_baseline uses all elements present and mask_element_removed removes only the specified element (sets mask[element] = 0).

  • Occ > 0 element contributes positively to the prediction

  • Occ < 0 element inhibits the prediction (removing it increases output)

  • Occ 0 element has no impact on the prediction

The occlusion approach provides a direct, model-agnostic measure of element importance by directly measuring the effect of completely removing each element.

Parameters:
  • model (torch.nn.Module) – Trained GSNN model (copied and frozen internally).

  • data (torch_geometric.data.Data) – Graph data object; only used for element names.

  • ignore_cuda (bool, optional (default=False)) – Force the explainer to run on CPU even if CUDA is available.

  • batch_size (int, optional (default=32)) – Number of element occlusions to process in parallel.

Example

>>> explainer = OcclusionExplainer(model, data, batch_size=64)
>>> # Edge-level attributions
>>> edge_df = explainer.explain(x, target_idx=0, target='edge')
>>> edge_df.nlargest(5, 'score')
source target   score
in0    func0    0.42
func0  func3    0.40
func3  out0     0.38
>>> # Node-level attributions
>>> node_df = explainer.explain(x, target_idx=0, target='node')
>>> node_df.nlargest(5, 'score')
>>> # Occlude only a subset of edges
>>> edge_mask = np.array([True, False, True, False, True])  # Only occlude edges 0, 2, 4
>>> edge_df = explainer.explain(x, target_idx=0, target='edge', element_mask=edge_mask)
>>> # Edges 1 and 3 will have None scores
__init__(model, data, ignore_cuda=False, batch_size=32)[source]

Create a new OcclusionExplainer instance.

Methods

__init__(model, data[, ignore_cuda, batch_size])

Create a new OcclusionExplainer instance.

explain(x, target_idx[, element_mask, ...])

Compute edge or node occlusion attributions for f(x)[target_idx].

explain(x, target_idx, element_mask=None, target='edge', reduction='mean', model_kwargs=None)[source]

Compute edge or node occlusion attributions for f(x)[target_idx].

Parameters:
  • x (torch.Tensor (shape: [N_in], [1, N_in], or [B, N_in] for batch)) – Input feature tensor. Will be moved to appropriate device.

  • target_idx (int) – Output dimension to explain.

  • element_mask (torch.Tensor or np.ndarray, optional (shape: [E] or [N])) – Boolean mask indicating which elements to compute occlusion for. If None, all elements are considered. If provided, only elements where element_mask[i] is True will have occlusion scores computed.

  • target (str, optional (default='edge')) – Whether to return ‘edge’ or ‘node’ level attributions.

  • reduction (str, optional (default='mean')) – How to aggregate attributions across batch samples: - ‘mean’: average attributions across samples (default) - ‘sum’: sum attributions across samples - ‘none’: return all per-sample attributions (adds ‘sample_idx’ column)

  • model_kwargs (dict, optional (default=None)) – Extra keyword arguments forwarded to every self.model(...) call (e.g. {'x_fn': x_fn} for models trained with node_activity=True). Tensor values must have leading dim equal to x.shape[0] (or 1 to broadcast); they will be tiled to match the per-element-occluded grid. edge_mask / node_mask are reserved.

Returns:

If target=’edge’: columns [‘source’, ‘target’, ‘score’] for edge attributions. If target=’node’: columns [‘node’, ‘score’] for node attributions. If reduction=’none’: additional ‘sample_idx’ column for batch dimension. Elements not in element_mask will have None scores.

Return type:

pd.DataFrame