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 node features that play a crucial role in the predictions
  made by a GNN.
  
  .. note::
  
      For an example of using :class:`GNNExplainer`, see
      `examples/explain/gnn_explainer.py <https://github.com/pyg-team/
      pytorch_geometric/blob/master/examples/explain/gnn_explainer.py>`_,
      `examples/explain/gnn_explainer_ba_shapes.py <https://github.com/
      pyg-team/pytorch_geometric/blob/master/examples/
      explain/gnn_explainer_ba_shapes.py>`_, and `examples/explain/
      gnn_explainer_link_pred.py <https://github.com/pyg-team/
      pytorch_geometric/blob/master/examples/explain/gnn_explainer_link_pred.py>`_.
  
  .. note::
  
      The :obj:`edge_size` coefficient is multiplied by the number of nodes
      in the explanation at every iteration, and the resulting value is added
      to the loss as a regularization term, with the goal of producing
      compact explanations.
      A higher value will push the algorithm towards explanations with less
      elements.
      Consider adjusting the :obj:`edge_size` coefficient according to the
      average node degree in the dataset, especially if this value is bigger
      than in the datasets used in the original paper.
  
  Args:
      epochs (int, optional): The number of epochs to train.
          (default: :obj:`100`)
      lr (float, optional): The learning rate to apply.
          (default: :obj:`0.01`)
      **kwargs (optional): Additional hyper-parameters to override default
          settings in
          :attr:`~torch_geometric.explain.algorithm.GNNExplainer.coeffs`.
code: def _loss(self, y_hat: Tensor, y: Tensor) -> Tensor:
      if self.model_config.mode == ModelMode.binary_classification:
          loss = self._loss_binary_classification(y_hat, y)
      elif (
          self.model_config.mode == ModelMode.multiclass_classification
      ):
          loss = self._loss_multiclass_classification(y_hat, y)
      elif self.model_config.mode == ModelMode.regression:
          loss = self._loss_regression(y_hat, y)
      else:
          assert False
  
      if self.hard_edge_mask is not None:
          assert self.edge_mask is not None
          m = self.edge_mask[self.hard_edge_mask].sigmoid()
          edge_reduce = getattr(torch, self.coeffs["edge_reduction"])
          loss = loss + self.coeffs["edge_size"] * edge_reduce(m)
          ent = -m * torch.log(m + self.coeffs["EPS"]) - (
              1 - m
          ) * torch.log(1 - m + self.coeffs["EPS"])
          loss = loss + self.coeffs["edge_ent"] * ent.mean()
  
      if self.hard_node_mask is not None:
          assert self.node_mask is not None
          m = self.node_mask[self.hard_node_mask].sigmoid()
          node_reduce = getattr(
              torch, self.coeffs["node_feat_reduction"]
          )
          loss = loss + self.coeffs["node_feat_size"] * node_reduce(m)
          ent = -m * torch.log(m + self.coeffs["EPS"]) - (
              1 - m
          ) * torch.log(1 - m + self.coeffs["EPS"])
          loss = loss + self.coeffs["node_feat_ent"] * ent.mean()
  
      return loss
  
imports: from math import sqrt
  from typing import Optional, Tuple, Union
  import torch
  from torch import Tensor
  from torch.nn.parameter import Parameter
  from torch_geometric.explain import ExplainerConfig, Explanation, ModelConfig
  from torch_geometric.explain.algorithm import ExplainerAlgorithm
  from torch_geometric.explain.algorithm.utils import clear_masks, set_masks
  from torch_geometric.explain.config import MaskType, ModelMode, ModelTaskLevel
label_desc: Use image node_id 6 for calling the GNNExplainer obj's underlying member method code with example usage: obj._loss(y_hat, y) and returns: loss