class_docstr: The GNN-Explainer model from the `"GNNExplainer: Generating
  Explanations for Graph Neural Networks"
  <https://arxiv.org/abs/1903.03894>`_ paper for identifying compact subgraph
  structures and small subsets node features that play a crucial role in a
  GNN’s node-predictions.
  .. note:: For an example, see `benchmarks/xgraph
      <https://github.com/divelab/DIG/tree/dig/benchmarks/xgraph>`_.
  Args:
      model (torch.nn.Module): The GNN module to explain.
      epochs (int, optional): The number of epochs to train.
          (default: :obj:`100`)
      lr (float, optional): The learning rate to apply.
          (default: :obj:`0.01`)
      explain_graph (bool, optional): Whether to explain graph classification model
          (default: :obj:`False`)
      indirect_graph_symmetric_weights (bool, optional): If `True`, then the explainer
          will first realize whether this graph input has indirect edges, 
          then makes its edge weights symmetric. (default: :obj:`False`)
class_docstr_tok: ["The","GNN-Explainer","model","from","the","`","``","GNNExplainer",":","Generating","Explanations","for","Graph","Neural","Networks","''","<","https",":","\/\/arxiv.org\/abs\/1903.03894",">","`","_","paper","for","identifying","compact","subgraph","structures","and","small","subsets","node","features","that","play","a","crucial","role","in","a","GNN","\u2019","s","node-predictions",".","..","note",":",":","For","an","example",",","see","`","benchmarks\/xgraph","<","https",":","\/\/github.com\/divelab\/DIG\/tree\/dig\/benchmarks\/xgraph",">","`","_",".","Args",":","model","(","torch.nn.Module",")",":","The","GNN","module","to","explain",".","epochs","(","int",",","optional",")",":","The","number","of","epochs","to","train",".","(","default",":",":","obj",":","`","100","`",")","lr","(","float",",","optional",")",":","The","learning","rate","to","apply",".","(","default",":",":","obj",":","`","0.01","`",")","explain_graph","(","bool",",","optional",")",":","Whether","to","explain","graph","classification","model","(","default",":",":","obj",":","`","False","`",")","indirect_graph_symmetric_weights","(","bool",",","optional",")",":","If","`","True","`",",","then","the","explainer","will","first","realize","whether","this","graph","input","has","indirect","edges",",","then","makes","its","edge","weights","symmetric",".","(","default",":",":","obj",":","`","False","`",")"]
docstr: Run the explainer for a specific graph instance.
  Args:
      x (torch.Tensor): The graph instance's input node features.
      edge_index (torch.Tensor): The graph instance's edge index.
      mask_features (bool, optional): Whether to use feature mask. Not recommended.
          (Default: :obj:`False`)
      target_label (torch.Tensor, optional): if given then apply optimization only on this label
      **kwargs (dict):
          :obj:`node_idx` （int, list, tuple, torch.Tensor): The index of node that is pending to be explained.
          (for node classification)
          :obj:`sparsity` (float): The Sparsity we need to control to transform a
          soft mask to a hard mask. (Default: :obj:`0.7`)
          :obj:`num_classes` (int): The number of task's classes.
  :rtype: (None, list, list)
  .. note::
      (None, edge_masks, related_predictions):
      edge_masks is a list of edge-level explanation for each class;
      related_predictions is a list of dictionary for each class
      where each dictionary includes 4 type predicted probabilities.
docstr_tok: ["Run","the","explainer","for","a","specific","graph","instance",".","Args",":","x","(","torch.Tensor",")",":","The","graph","instance","'s","input","node","features",".","edge_index","(","torch.Tensor",")",":","The","graph","instance","'s","edge","index",".","mask_features","(","bool",",","optional",")",":","Whether","to","use","feature","mask",".","Not","recommended",".","(","Default",":",":","obj",":","`","False","`",")","target_label","(","torch.Tensor",",","optional",")",":","if","given","then","apply","optimization","only","on","this","label","*","*","kwargs","(","dict",")",":",":","obj",":","`","node_idx","`","\uff08int",",","list",",","tuple",",","torch.Tensor",")",":","The","index","of","node","that","is","pending","to","be","explained",".","(","for","node","classification",")",":","obj",":","`","sparsity","`","(","float",")",":","The","Sparsity","we","need","to","control","to","transform","a","soft","mask","to","a","hard","mask",".","(","Default",":",":","obj",":","`","0.7","`",")",":","obj",":","`","num_classes","`","(","int",")",":","The","number","of","task","'s","classes",".",":","rtype",":","(","None",",","list",",","list",")","..","note",":",":","(","None",",","edge_masks",",","related_predictions",")",":","edge_masks","is","a","list","of","edge-level","explanation","for","each","class",";","related_predictions","is","a","list","of","dictionary","for","each","class","where","each","dictionary","includes","4","type","predicted","probabilities","."]
code: def forward(
      self,
      x,
      edge_index,
      mask_features=False,
      target_label=None,
      **kwargs,
  ):
      r"""
      Run the explainer for a specific graph instance.
      Args:
          x (torch.Tensor): The graph instance's input node features.
          edge_index (torch.Tensor): The graph instance's edge index.
          mask_features (bool, optional): Whether to use feature mask. Not recommended.
              (Default: :obj:`False`)
          target_label (torch.Tensor, optional): if given then apply optimization only on this label
          **kwargs (dict):
              :obj:`node_idx` （int, list, tuple, torch.Tensor): The index of node that is pending to be explained.
              (for node classification)
              :obj:`sparsity` (float): The Sparsity we need to control to transform a
              soft mask to a hard mask. (Default: :obj:`0.7`)
              :obj:`num_classes` (int): The number of task's classes.
      :rtype: (None, list, list)
      .. note::
          (None, edge_masks, related_predictions):
          edge_masks is a list of edge-level explanation for each class;
          related_predictions is a list of dictionary for each class
          where each dictionary includes 4 type predicted probabilities.
      """
      super().forward(x=x, edge_index=edge_index, **kwargs)
      self.model.eval()
  
      self_loop_edge_index, _ = add_remaining_self_loops(
          edge_index, num_nodes=self.num_nodes
      )
  
      # Only operate on a k-hop subgraph around `node_idx`.
      # Get subgraph and relabel the node, mapping is the relabeled given node_idx.
      if not self.explain_graph:
          self.node_idx = node_idx = kwargs.get("node_idx")
          assert (
              node_idx is not None
          ), "An node explanation needs kwarg node_idx, but got None."
          if isinstance(node_idx, torch.Tensor) and not node_idx.dim():
              node_idx = node_idx.to(self.device).flatten()
          elif isinstance(node_idx, (int, list, tuple)):
              node_idx = torch.tensor(
                  [node_idx], device=self.device, dtype=torch.int64
              ).flatten()
          else:
              raise TypeError(
                  f"node_idx should be in types of int, list, tuple, "
                  f"or torch.Tensor, but got {type(node_idx)}"
              )
          self.subset, _, _, self.hard_edge_mask = subgraph(
              node_idx,
              self.__num_hops__,
              self_loop_edge_index,
              relabel_nodes=True,
              num_nodes=None,
              flow=self.__flow__(),
          )
          self.new_node_idx = torch.where(self.subset == node_idx)[0]
  
      if kwargs.get("edge_masks"):
          edge_masks = kwargs.pop("edge_masks")
          self.__set_masks__(x, self_loop_edge_index)
  
      else:
          # Assume the mask we will predict
          labels = tuple(i for i in range(kwargs.get("num_classes")))
          ex_labels = tuple(
              torch.tensor([label]).to(self.device) for label in labels
          )
  
          # Calculate mask
          edge_masks = []
          for ex_label in ex_labels:
              if (
                  target_label is None
                  or ex_label.item() == target_label.item()
              ):
                  self.__clear_masks__()
                  self.__set_masks__(x, self_loop_edge_index)
                  edge_mask = self.gnn_explainer_alg(
                      x, edge_index, ex_label
                  ).sigmoid()
  
                  if self._symmetric_edge_mask_indirect_graph:
                      edge_mask = symmetric_edge_mask_indirect_graph(
                          self_loop_edge_index, edge_mask
                      )
  
                  edge_masks.append(edge_mask)
  
      hard_edge_masks = [
          self.control_sparsity(
              mask, sparsity=kwargs.get("sparsity")
          ).sigmoid()
          for mask in edge_masks
      ]
  
      with torch.no_grad():
          related_preds = self.eval_related_pred(
              x, edge_index, hard_edge_masks, **kwargs
          )
  
      self.__clear_masks__()
  
      return edge_masks, hard_edge_masks, related_preds
  
file_path: DIG/dig/xgraph/method/gnnexplainer.py
imports: import torch
  from torch import Tensor
  from torch_geometric.utils.loop import add_remaining_self_loops
  from dig.version import debug
  from ..models.utils import subgraph
  from .utils import symmetric_edge_mask_indirect_graph
  from torch.nn.functional import cross_entropy
  from .base_explainer import ExplainerBase
  from typing import Union
label_desc: Use image node_id 4 for calling the GNNExplainer obj's underlying member method code with example usage: obj.forward(x, edge_index, mask_features, target_label) and returns: edge_masks,  hard_edge_masks,  related_preds