class_docstr: The Attentive FP model for molecular representation learning from the
  `"Pushing the Boundaries of Molecular Representation for Drug Discovery
  with the Graph Attention Mechanism"
  <https://pubs.acs.org/doi/10.1021/acs.jmedchem.9b00959>`_ paper, based on
  graph attention mechanisms.
  
  Args:
      in_channels (int): Size of each input sample.
      hidden_channels (int): Hidden node feature dimensionality.
      out_channels (int): Size of each output sample.
      edge_dim (int): Edge feature dimensionality.
      num_layers (int): Number of GNN layers.
      num_timesteps (int): Number of iterative refinement steps for global
          readout.
      dropout (float, optional): Dropout probability. (default: :obj:`0.0`)
code: def __init__(
      self,
      in_channels: int,
      hidden_channels: int,
      out_channels: int,
      edge_dim: int,
      num_layers: int,
      num_timesteps: int,
      dropout: float = 0.0,
  ):
      super().__init__()
  
      self.in_channels = in_channels
      self.hidden_channels = hidden_channels
      self.out_channels = out_channels
      self.edge_dim = edge_dim
      self.num_layers = num_layers
      self.num_timesteps = num_timesteps
      self.dropout = dropout
  
      self.lin1 = Linear(in_channels, hidden_channels)
  
      self.gate_conv = GATEConv(
          hidden_channels, hidden_channels, edge_dim, dropout
      )
      self.gru = GRUCell(hidden_channels, hidden_channels)
  
      self.atom_convs = torch.nn.ModuleList()
      self.atom_grus = torch.nn.ModuleList()
      for _ in range(num_layers - 1):
          conv = GATConv(
              hidden_channels,
              hidden_channels,
              dropout=dropout,
              add_self_loops=False,
              negative_slope=0.01,
          )
          self.atom_convs.append(conv)
          self.atom_grus.append(
              GRUCell(hidden_channels, hidden_channels)
          )
  
      self.mol_conv = GATConv(
          hidden_channels,
          hidden_channels,
          dropout=dropout,
          add_self_loops=False,
          negative_slope=0.01,
      )
      self.mol_conv.explain = False  # Cannot explain global pooling.
      self.mol_gru = GRUCell(hidden_channels, hidden_channels)
  
      self.lin2 = Linear(hidden_channels, out_channels)
  
      self.reset_parameters()
  
imports: from typing import Optional
  import torch
  import torch.nn.functional
  from torch import Tensor
  from torch.nn import GRUCell, Linear, Parameter
  from torch_geometric.nn import GATConv, MessagePassing, global_add_pool
  from torch_geometric.nn.inits import glorot, zeros
  from torch_geometric.typing import Adj, OptTensor
  from torch_geometric.utils import softmax
label_desc: Use image node_id 1 to create a new AttentiveFP object from inherited base classes: torch.nn with example: obj = AttentiveFP(in_channels, hidden_channels, out_channels, edge_dim, num_layers, num_timesteps, dropout)