class_docstr: A node-attention global pooling layer. Pools a graph by learning attention
  coefficients to sum node features.
  
  This layer computes:
  $$
      \alpha = \textrm{softmax}( \X \a); \\
      \X' = \sum\limits_{i=1}^{N} \alpha_i \cdot \X_i
  $$
  where \(\a \in \mathbb{R}^F\) is a trainable vector. Note that the softmax
  is applied across nodes, and not across features.
  
  **Mode**: single, disjoint, mixed, batch.
  
  **Input**
  
  - Node features of shape `([batch], n_nodes, n_node_features)`;
  - Graph IDs of shape `(n_nodes, )` (only in disjoint mode);
  
  **Output**
  
  - Pooled node features of shape `(batch, n_node_features)` (if single mode, shape will
  be `(1, n_node_features)`).
  
  **Arguments**
  
  - `attn_kernel_initializer`: initializer for the attention weights;
  - `attn_kernel_regularizer`: regularization applied to the attention kernel
  matrix;
  - `attn_kernel_constraint`: constraint applied to the attention kernel
  matrix;
class_docstr_tok: ["A","node-attention","global","pooling","layer",".","Pools","a","graph","by","learning","attention","coefficients","to","sum","node","features",".","This","layer","computes",":","$","$","\\alpha","=","\\textrm","{","softmax","}","(","\\X","\\a",")",";","\\\\","\\X","'","=","\\sum\\limits_","{","i=1","}","^","{","N","}","\\alpha_i","\\cdot","\\X_i","$","$","where","\\","(","\\a","\\in","\\mathbb","{","R","}","^F\\",")","is","a","trainable","vector",".","Note","that","the","softmax","is","applied","across","nodes",",","and","not","across","features",".","*","*","Mode","*","*",":","single",",","disjoint",",","mixed",",","batch",".","*","*","Input","*","*","-","Node","features","of","shape","`","(","[","batch","]",",","n_nodes",",","n_node_features",")","`",";","-","Graph","IDs","of","shape","`","(","n_nodes",",",")","`","(","only","in","disjoint","mode",")",";","*","*","Output","*","*","-","Pooled","node","features","of","shape","`","(","batch",",","n_node_features",")","`","(","if","single","mode",",","shape","will","be","`","(","1",",","n_node_features",")","`",")",".","*","*","Arguments","*","*","-","`","attn_kernel_initializer","`",":","initializer","for","the","attention","weights",";","-","`","attn_kernel_regularizer","`",":","regularization","applied","to","the","attention","kernel","matrix",";","-","`","attn_kernel_constraint","`",":","constraint","applied","to","the","attention","kernel","matrix",";"]
code: def build(self, input_shape):
      assert len(input_shape) >= 2
      if isinstance(input_shape, list) and len(input_shape) == 2:
          self.data_mode = "disjoint"
          F = input_shape[0][-1]
      else:
          if len(input_shape) == 2:
              self.data_mode = "single"
          else:
              self.data_mode = "batch"
          F = input_shape[-1]
      # Attention kernels
      self.attn_kernel = self.add_weight(
          shape=(F, 1),
          initializer=self.attn_kernel_initializer,
          regularizer=self.attn_kernel_regularizer,
          constraint=self.attn_kernel_constraint,
          name="attn_kernel",
      )
      self.built = True
  
imports: import tensorflow
  from tensorflow.keras import backend
  from tensorflow.keras import constraints, initializers, regularizers
  from tensorflow.keras.layers import Dense, Layer
  from spektral.layers import ops
label_desc: Use image node_id 2 for calling the GlobalAttnSumPool obj's underlying member method code with example usage: obj.build(input_shape) without return types