Source code for graph_explain.methods.baseline.random_baseline

from __future__ import annotations

from typing import Any

import torch

from ...core.explanation import Explanation
from ...core.registry import register
from ..base import ExplanationAlgorithm


[docs] @register("random", "random_baseline", "rand") class RandomBaseline(ExplanationAlgorithm): """Random: seed-able uniform random importance baseline. Assigns random importances in [0, 1] to nodes, edges and features with no link to the model; useful as a null-scenario reference in comparative benchmarks. """ graph_level = True def __init__(self, seed: int | None = 0, **kwargs): self.seed = seed def explain( self, backend: Any, model: Any, data: Any, index: int | torch.Tensor | None = None, target_class: int | None = None, **kwargs, ) -> Explanation: x = backend.node_features(data) edge_index = backend.edge_index(data) num_nodes = int(x.size(0)) num_edges = int(edge_index.size(1)) if self.seed is not None: torch.manual_seed(self.seed) node_importance = torch.rand(num_nodes).cpu() edge_importance = torch.rand(num_edges).cpu() feature_importance = torch.rand_like(x).cpu() nodes = self._to_node_ids(index, num_nodes) root = int(nodes[0]) with torch.no_grad(): logits = backend.forward(model, x, edge_index) target = target_class if logits.dim() == 2: if target is None: target = int(logits[root].argmax().item()) target = max(0, min(int(target), logits.size(1) - 1)) pred = logits[root].detach().cpu() else: target = None pred = logits.detach().cpu() return Explanation( node_importance=node_importance, edge_importance=edge_importance, feature_importance=feature_importance, prediction_original=pred, prediction_explanation=None, node_idx=root, target_class=target, ) @staticmethod def _to_node_ids(index, num_nodes: int) -> torch.Tensor: if index is None: return torch.zeros(1, dtype=torch.long) if isinstance(index, int): return torch.tensor([index], dtype=torch.long) idx = torch.as_tensor(index, dtype=torch.long) return idx.reshape(-1) if idx.numel() else torch.zeros(1, dtype=torch.long)