class_docstr: A stack of Graph Attention (GAT) layers with aggregation of multiple attention heads,
  Eqs 5-6 of the GAT paper https://arxiv.org/abs/1710.10903
  
  To use this class as a Keras model, the features and preprocessed adjacency matrix
  should be supplied using:
  
  - the :class:`.FullBatchNodeGenerator` class for node inference
  - the :class:`.ClusterNodeGenerator` class for scalable/inductive node inference using the Cluster-GCN training procedure (https://arxiv.org/abs/1905.07953)
  - the :class:`.FullBatchLinkGenerator` class for link inference
  
  To have the appropriate preprocessing the generator object should be instantiated
  with the `method='gat'` argument.
  
  Examples:
      Creating a GAT node classification model from an existing :class:`.StellarGraph` object `G`::
  
          generator = FullBatchNodeGenerator(G, method="gat")
          gat = GAT(
                  layer_sizes=[8, 4],
                  activations=["elu","softmax"],
                  attn_heads=8,
                  generator=generator,
                  in_dropout=0.5,
                  attn_dropout=0.5,
              )
          x_inp, predictions = gat.in_out_tensors()
  
  Notes:
    - The inputs are tensors with a batch dimension of 1. These are provided by the         :class:`.FullBatchNodeGenerator` object.
  
    - This does not add self loops to the adjacency matrix, you should preprocess
      the adjacency matrix to add self-loops, using the ``method='gat'`` argument
      of the :class:`.FullBatchNodeGenerator`.
  
    - The nodes provided to the :meth:`.FullBatchNodeGenerator.flow` method are
      used by the final layer to select the predictions for those nodes in order.
      However, the intermediate layers before the final layer order the nodes
      in the same way as the adjacency matrix.
  
  .. seealso::
  
     Examples using GAT:
  
     - `node classification <https://stellargraph.readthedocs.io/en/stable/demos/node-classification/gat-node-classification.html>`__
     - `unsupervised representation learning with Deep Graph Infomax <https://stellargraph.readthedocs.io/en/stable/demos/embeddings/deep-graph-infomax-embeddings.html>`__
     - `interpreting GAT predictions <https://stellargraph.readthedocs.io/en/stable/demos/interpretability/gat-node-link-importance.html>`__
     - `ensemble model for node classification <https://stellargraph.readthedocs.io/en/stable/demos/ensembles/ensemble-node-classification-example.html>`__
  
     Appropriate data generators: :class:`.FullBatchNodeGenerator`, :class:`.FullBatchLinkGenerator`, :class:`.ClusterNodeGenerator`.
  
     Related models:
  
     - Other full-batch models: see the documentation of :class:`.FullBatchNodeGenerator` for a full list
     - :class:`.DeepGraphInfomax` for unsupervised training
  
     :class:`.GraphAttention` and :class:`.GraphAttentionSparse` are the base layers out of which a GAT model is built.
  
  Args:
      layer_sizes (list of int): list of output sizes of GAT layers in the stack. The length of this list defines
          the number of GraphAttention layers in the stack.
      generator (FullBatchNodeGenerator): an instance of FullBatchNodeGenerator class constructed on the graph of interest
      attn_heads (int or list of int): number of attention heads in GraphAttention layers. The options are:
  
          - a single integer: the passed value of ``attn_heads`` will be applied to all GraphAttention layers in the stack, except the last layer (for which the number of attn_heads will be set to 1).
          - a list of integers: elements of the list define the number of attention heads in the corresponding layers in the stack.
  
      attn_heads_reduction (list of str or None): reductions applied to output features of each attention head,
          for all layers in the stack. Valid entries in the list are: ``concat``, ``average``.
          If None is passed, the default reductions are applied: ``concat`` reduction to all layers in the stack
          except the final layer, ``average`` reduction to the last layer (Eqs. 5-6 of the GAT paper).
      bias (bool): toggles an optional bias in GAT layers
      in_dropout (float): dropout rate applied to input features of each GAT layer
      attn_dropout (float): dropout rate applied to attention maps
      normalize (str or None): normalization applied to the final output features of the GAT layers stack. Default is None.
      activations (list of str): list of activations applied to each layer's output; defaults to ``['elu', ..., 'elu']``.
      saliency_map_support (bool): If calculating saliency maps using the tools in
          stellargraph.interpretability.saliency_maps this should be True. Otherwise this should be False (default).
      multiplicity (int, optional): The number of nodes to process at a time. This is 1 for a node
          inference and 2 for link inference (currently no others are supported).
      num_nodes (int, optional): The number of nodes in the given graph.
      num_features (int, optional): The dimensions of the node features used as input to the model.
      kernel_initializer (str or func, optional): The initialiser to use for the weights of each layer.
      kernel_regularizer (str or func, optional): The regulariser to use for the weights of each layer.
      kernel_constraint (str or func, optional): The constraint to use for the weights of each layer.
      bias_initializer (str or func, optional): The initialiser to use for the bias of each layer.
      bias_regularizer (str or func, optional): The regulariser to use for the bias of each layer.
      bias_constraint (str or func, optional): The constraint to use for the bias of each layer.
      attn_kernel_initializer (str or func, optional): The initialiser to use for the attention weights.
      attn_kernel_regularizer (str or func, optional): The regulariser to use for the attention weights.
      attn_kernel_constraint (str or func, optional): The constraint to use for the attention bias.
  
  .. note::
      The values for ``multiplicity``, ``num_nodes``, and ``num_features`` are obtained from the
      provided ``generator`` by default. The additional keyword arguments for these parameters
      provide an alternative way to specify them if a generator cannot be supplied.
class_docstr_tok: ["A","stack","of","Graph","Attention","(","GAT",")","layers","with","aggregation","of","multiple","attention","heads",",","Eqs","5-6","of","the","GAT","paper","https",":","\/\/arxiv.org\/abs\/1710.10903","To","use","this","class","as","a","Keras","model",",","the","features","and","preprocessed","adjacency","matrix","should","be","supplied","using",":","-","the",":","class",":","`",".FullBatchNodeGenerator","`","class","for","node","inference","-","the",":","class",":","`",".ClusterNodeGenerator","`","class","for","scalable\/inductive","node","inference","using","the","Cluster-GCN","training","procedure","(","https",":","\/\/arxiv.org\/abs\/1905.07953",")","-","the",":","class",":","`",".FullBatchLinkGenerator","`","class","for","link","inference","To","have","the","appropriate","preprocessing","the","generator","object","should","be","instantiated","with","the","`","method='gat","'","`","argument",".","Examples",":","Creating","a","GAT","node","classification","model","from","an","existing",":","class",":","`",".StellarGraph","`","object","`","G","`",":",":","generator","=","FullBatchNodeGenerator","(","G",",","method=","''","gat","''",")","gat","=","GAT","(","layer_sizes=","[","8",",","4","]",",","activations=","[","``","elu","''",",","''","softmax","''","]",",","attn_heads=8",",","generator=generator",",","in_dropout=0.5",",","attn_dropout=0.5",",",")","x_inp",",","predictions","=","gat.in_out_tensors","(",")","Notes",":","-","The","inputs","are","tensors","with","a","batch","dimension","of","1",".","These","are","provided","by","the",":","class",":","`",".FullBatchNodeGenerator","`","object",".","-","This","does","not","add","self","loops","to","the","adjacency","matrix",",","you","should","preprocess","the","adjacency","matrix","to","add","self-loops",",","using","the","``","method='gat","'","``","argument","of","the",":","class",":","`",".FullBatchNodeGenerator","`",".","-","The","nodes","provided","to","the",":","meth",":","`",".FullBatchNodeGenerator.flow","`","method","are","used","by","the","final","layer","to","select","the","predictions","for","those","nodes","in","order",".","However",",","the","intermediate","layers","before","the","final","layer","order","the","nodes","in","the","same","way","as","the","adjacency","matrix",".","..","seealso",":",":","Examples","using","GAT",":","-","`","node","classification","<","https",":","\/\/stellargraph.readthedocs.io\/en\/stable\/demos\/node-classification\/gat-node-classification.html",">","`","__","-","`","unsupervised","representation","learning","with","Deep","Graph","Infomax","<","https",":","\/\/stellargraph.readthedocs.io\/en\/stable\/demos\/embeddings\/deep-graph-infomax-embeddings.html",">","`","__","-","`","interpreting","GAT","predictions","<","https",":","\/\/stellargraph.readthedocs.io\/en\/stable\/demos\/interpretability\/gat-node-link-importance.html",">","`","__","-","`","ensemble","model","for","node","classification","<","https",":","\/\/stellargraph.readthedocs.io\/en\/stable\/demos\/ensembles\/ensemble-node-classification-example.html",">","`","__","Appropriate","data","generators",":",":","class",":","`",".FullBatchNodeGenerator","`",",",":","class",":","`",".FullBatchLinkGenerator","`",",",":","class",":","`",".ClusterNodeGenerator","`",".","Related","models",":","-","Other","full-batch","models",":","see","the","documentation","of",":","class",":","`",".FullBatchNodeGenerator","`","for","a","full","list","-",":","class",":","`",".DeepGraphInfomax","`","for","unsupervised","training",":","class",":","`",".GraphAttention","`","and",":","class",":","`",".GraphAttentionSparse","`","are","the","base","layers","out","of","which","a","GAT","model","is","built",".","Args",":","layer_sizes","(","list","of","int",")",":","list","of","output","sizes","of","GAT","layers","in","the","stack",".","The","length","of","this","list","defines","the","number","of","GraphAttention","layers","in","the","stack",".","generator","(","FullBatchNodeGenerator",")",":","an","instance","of","FullBatchNodeGenerator","class","constructed","on","the","graph","of","interest","attn_heads","(","int","or","list","of","int",")",":","number","of","attention","heads","in","GraphAttention","layers",".","The","options","are",":","-","a","single","integer",":","the","passed","value","of","``","attn_heads","``","will","be","applied","to","all","GraphAttention","layers","in","the","stack",",","except","the","last","layer","(","for","which","the","number","of","attn_heads","will","be","set","to","1",")",".","-","a","list","of","integers",":","elements","of","the","list","define","the","number","of","attention","heads","in","the","corresponding","layers","in","the","stack",".","attn_heads_reduction","(","list","of","str","or","None",")",":","reductions","applied","to","output","features","of","each","attention","head",",","for","all","layers","in","the","stack",".","Valid","entries","in","the","list","are",":","``","concat","``",",","``","average","``",".","If","None","is","passed",",","the","default","reductions","are","applied",":","``","concat","``","reduction","to","all","layers","in","the","stack","except","the","final","layer",",","``","average","``","reduction","to","the","last","layer","(","Eqs",".","5-6","of","the","GAT","paper",")",".","bias","(","bool",")",":","toggles","an","optional","bias","in","GAT","layers","in_dropout","(","float",")",":","dropout","rate","applied","to","input","features","of","each","GAT","layer","attn_dropout","(","float",")",":","dropout","rate","applied","to","attention","maps","normalize","(","str","or","None",")",":","normalization","applied","to","the","final","output","features","of","the","GAT","layers","stack",".","Default","is","None",".","activations","(","list","of","str",")",":","list","of","activations","applied","to","each","layer","'s","output",";","defaults","to","``","[","'elu","'",",","...",",","'elu","'","]","``",".","saliency_map_support","(","bool",")",":","If","calculating","saliency","maps","using","the","tools","in","stellargraph.interpretability.saliency_maps","this","should","be","True",".","Otherwise","this","should","be","False","(","default",")",".","multiplicity","(","int",",","optional",")",":","The","number","of","nodes","to","process","at","a","time",".","This","is","1","for","a","node","inference","and","2","for","link","inference","(","currently","no","others","are","supported",")",".","num_nodes","(","int",",","optional",")",":","The","number","of","nodes","in","the","given","graph",".","num_features","(","int",",","optional",")",":","The","dimensions","of","the","node","features","used","as","input","to","the","model",".","kernel_initializer","(","str","or","func",",","optional",")",":","The","initialiser","to","use","for","the","weights","of","each","layer",".","kernel_regularizer","(","str","or","func",",","optional",")",":","The","regulariser","to","use","for","the","weights","of","each","layer",".","kernel_constraint","(","str","or","func",",","optional",")",":","The","constraint","to","use","for","the","weights","of","each","layer",".","bias_initializer","(","str","or","func",",","optional",")",":","The","initialiser","to","use","for","the","bias","of","each","layer",".","bias_regularizer","(","str","or","func",",","optional",")",":","The","regulariser","to","use","for","the","bias","of","each","layer",".","bias_constraint","(","str","or","func",",","optional",")",":","The","constraint","to","use","for","the","bias","of","each","layer",".","attn_kernel_initializer","(","str","or","func",",","optional",")",":","The","initialiser","to","use","for","the","attention","weights",".","attn_kernel_regularizer","(","str","or","func",",","optional",")",":","The","regulariser","to","use","for","the","attention","weights",".","attn_kernel_constraint","(","str","or","func",",","optional",")",":","The","constraint","to","use","for","the","attention","bias",".","..","note",":",":","The","values","for","``","multiplicity","``",",","``","num_nodes","``",",","and","``","num_features","``","are","obtained","from","the","provided","``","generator","``","by","default",".","The","additional","keyword","arguments","for","these","parameters","provide","an","alternative","way","to","specify","them","if","a","generator","can","not","be","supplied","."]
docstr: Builds a GAT model for node or link prediction
  
  Returns:
      tuple: ``(x_inp, x_out)``, where ``x_inp`` is a list of Keras/TensorFlow
          input tensors for the model and ``x_out`` is a tensor of the model output.
docstr_tok: ["Builds","a","GAT","model","for","node","or","link","prediction","Returns",":","tuple",":","``","(","x_inp",",","x_out",")","``",",","where","``","x_inp","``","is","a","list","of","Keras\/TensorFlow","input","tensors","for","the","model","and","``","x_out","``","is","a","tensor","of","the","model","output","."]
code: def in_out_tensors(self, multiplicity=None):
      """
      Builds a GAT model for node or link prediction
  
      Returns:
          tuple: ``(x_inp, x_out)``, where ``x_inp`` is a list of Keras/TensorFlow
              input tensors for the model and ``x_out`` is a tensor of the model output.
      """
  
      # Inputs for features
      x_t = Input(batch_shape=(1, self.n_nodes, self.n_features))
  
      # If not specified use multiplicity from instanciation
      if multiplicity is None:
          multiplicity = self.multiplicity
  
      # Indices to gather for model output
      if multiplicity == 1:
          out_indices_t = Input(batch_shape=(1, None), dtype="int32")
      else:
          out_indices_t = Input(
              batch_shape=(1, None, multiplicity), dtype="int32"
          )
  
      # Create inputs for sparse or dense matrices
      if self.use_sparse:
          # Placeholders for the sparse adjacency matrix
          A_indices_t = Input(batch_shape=(1, None, 2), dtype="int64")
          A_values_t = Input(batch_shape=(1, None))
          A_placeholders = [A_indices_t, A_values_t]
  
      else:
          # Placeholders for the dense adjacency matrix
          A_m = Input(batch_shape=(1, self.n_nodes, self.n_nodes))
          A_placeholders = [A_m]
  
      # TODO: Support multiple matrices
      x_inp = [x_t, out_indices_t] + A_placeholders
      x_out = self(x_inp)
  
      # Flatten output by removing singleton batch dimension
      if x_out.shape[0] == 1:
          self.x_out_flat = Lambda(lambda x: K.squeeze(x, 0))(x_out)
      else:
          self.x_out_flat = x_out
  
      return x_inp, x_out
  
imports: import warnings
  import tensorflow
  from tensorflow.keras import backend
  from tensorflow.keras import activations, constraints, initializers, regularizers
  from tensorflow.keras.layers import Input, Layer, Dropout, LeakyReLU, Lambda, Reshape
  from ..mapper import FullBatchNodeGenerator, FullBatchGenerator, ClusterNodeGenerator
  from .misc import SqueezedSparseConversion, deprecated_model_function, GatherIndices
label_desc: Use image node_id 3 for calling the GAT obj's underlying member method code with example usage: obj.in_out_tensors(multiplicity) and returns: x_inp,  x_out