class_docstr: The modified :class:`GINConv` operator from the `"Strategies for
  Pre-training Graph Neural Networks" <https://arxiv.org/abs/1905.12265>`_
  paper.
  
  .. math::
      \mathbf{x}^{\prime}_i = h_{\mathbf{\Theta}} \left( (1 + \epsilon) \cdot
      \mathbf{x}_i + \sum_{j \in \mathcal{N}(i)} \mathrm{ReLU}
      ( \mathbf{x}_j + \mathbf{e}_{j,i} ) \right)
  
  that is able to incorporate edge features :math:`\mathbf{e}_{j,i}` into
  the aggregation procedure.
  
  Args:
      nn (torch.nn.Module): A neural network :math:`h_{\mathbf{\Theta}}` that
          maps node features :obj:`x` of shape :obj:`[-1, in_channels]` to
          shape :obj:`[-1, out_channels]`, *e.g.*, defined by
          :class:`torch.nn.Sequential`.
      eps (float, optional): (Initial) :math:`\epsilon`-value.
          (default: :obj:`0.`)
      train_eps (bool, optional): If set to :obj:`True`, :math:`\epsilon`
          will be a trainable parameter. (default: :obj:`False`)
      edge_dim (int, optional): Edge feature dimensionality. If set to
          :obj:`None`, node and edge feature dimensionality is expected to
          match. Other-wise, edge features are linearly transformed to match
          node feature dimensionality. (default: :obj:`None`)
      **kwargs (optional): Additional arguments of
          :class:`torch_geometric.nn.conv.MessagePassing`.
  
  Shapes:
      - **input:**
        node features :math:`(|\mathcal{V}|, F_{in})` or
        :math:`((|\mathcal{V_s}|, F_{s}), (|\mathcal{V_t}|, F_{t}))`
        if bipartite,
        edge indices :math:`(2, |\mathcal{E}|)`,
        edge features :math:`(|\mathcal{E}|, D)` *(optional)*
      - **output:** node features :math:`(|\mathcal{V}|, F_{out})` or
        :math:`(|\mathcal{V}_t|, F_{out})` if bipartite
code: def __init__(
      self,
      nn: torch.nn.Module,
      eps: float = 0.0,
      train_eps: bool = False,
      edge_dim: Optional[int] = None,
      **kwargs,
  ):
      kwargs.setdefault("aggr", "add")
      super().__init__(**kwargs)
      self.nn = nn
      self.initial_eps = eps
      if train_eps:
          self.eps = torch.nn.Parameter(torch.empty(1))
      else:
          self.register_buffer("eps", torch.empty(1))
      if edge_dim is not None:
          if isinstance(self.nn, torch.nn.Sequential):
              nn = self.nn[0]
          if hasattr(nn, "in_features"):
              in_channels = nn.in_features
          elif hasattr(nn, "in_channels"):
              in_channels = nn.in_channels
          else:
              raise ValueError(
                  "Could not infer input channels from `nn`."
              )
          self.lin = Linear(edge_dim, in_channels)
  
      else:
          self.lin = None
      self.reset_parameters()
  
imports: from typing import Callable, Optional, Union
  import torch
  from torch import Tensor
  from torch_geometric.nn.conv import MessagePassing
  from torch_geometric.nn.dense.linear import Linear
  from torch_geometric.nn.inits import reset
  from torch_geometric.typing import Adj, OptPairTensor, OptTensor, Size, SparseTensor
  from torch_geometric.utils import spmm
label_desc: Use image node_id 1 to create a new GINEConv object from inherited base classes: MessagePassing with example: obj = GINEConv(nn, eps, train_eps, edge_dim)