class_docstr: Defines a generalized additive model (GAM) layer.
  
  This layer implements the neural generalized additive ranking model described
  in [Zhuang et al, 2021][zhuang2021].
  
  Neural Generalized Additive Ranking Model is an additive ranking model.
  For each example `x` with `n` features `(x_1, x_2, ..., x_n)`, the ranking
  score is:
  
    $$F(x) = f_1(x_1) + f_2(x_2) + \ldots + f_n(x_n)$$
  
  where each feature is scored by a corresponding submodel, and the overall
  ranking score is the sum of all the submodels' outputs. Each submodel is a
  standalone feed-forward network.
  
  When there are `m` context features `(c_1, c_2, ..., c_m)`, the ranking score
  will be determined by:
  
    $$F(c, x) = w_1(c) * f_1(x_1) + w_2(c) * f_2(x_2) + \ldots + w_n(c) *
    f_n(x_n)$$
  
  where `(w1(c), w2(c), ..., wn(c))` is a weighting vector determined solely by
  context features. For each context feature `c_j`, a feed-forward submodel is
  constructed to derive a weighting vector
  `(wj1(c_j), wj2(c_j), ..., wjn(c_j))`. The final weighting vector is the sum
  of the output of all the context features' submodels.
  
  The model is implicitly interpretable as the contribution of each feature to
  the final ranking score can be easily visualized. However, the model does not
  have higher-order inter-feature interactions and hence may not have
  performance as good as a fully-connected DNN.
  
  The output of each example feature's submodel can be retrieved by tensor
  named `{feature_name}_subscore`. The output of each context feature's submodel
  is a n-dimensional vector and can be retrieved by tensor named
  `{feature_name}_subweight`.
  
  ```python
  example_inputs = tf.constant([[1], [0], [-1]], dtype=tf.float32)
  context_inputs = tf.constant([[1, 2], [0, 1], [-1, 1]], dtype=tf.float32)
  gam = layers.GAMLayer(2, [3, 2, 1], 2, [3, 2, 1])
  outputs, sublogits_list, subweights_list = gam(
      ([example_inputs, example_inputs], [context_inputs, context_inputs]))
  ```
  
  References:
    - [Interpretable Ranking with Generalized Additive Models, Zhuang et al,
       2021][zhuang2021]
  
  [zhuang2021]: https://research.google/pubs/pub50040/
docstr: Initializes the layer.
  
  Args:
    example_feature_num: Number of example features.
    example_hidden_layer_dims: Iterable of number hidden units for an tower.
      Each example feature will have an identical tower.
    context_feature_num: Number of context features. If `None` or 0 then no
      context weighting will be applied, otherwise `context_hidden_layer_dims`
      is required.
    context_hidden_layer_dims: Iterable of number hidden units for an tower.
      Each context feature (if any) will have an identical tower. Required if
      `context_feature_num` is specified.
    activation: Activation function applied to each layer. If `None`, will use
      an identity activation.
    use_batch_norm: Whether to use batch normalization after each hidden
      layer.
    batch_norm_moment: Momentum for the moving average in batch normalization.
    dropout: When not `None`, the probability of dropout for the dropoout
      layer in each tower.
    name: Name of the Keras layer.
    **kwargs: Keyword arguments.
docstr_tok: ["Initializes","the","layer",".","Args",":","example_feature_num",":","Number","of","example","features",".","example_hidden_layer_dims",":","Iterable","of","number","hidden","units","for","an","tower",".","Each","example","feature","will","have","an","identical","tower",".","context_feature_num",":","Number","of","context","features",".","If","`","None","`","or","0","then","no","context","weighting","will","be","applied",",","otherwise","`","context_hidden_layer_dims","`","is","required",".","context_hidden_layer_dims",":","Iterable","of","number","hidden","units","for","an","tower",".","Each","context","feature","(","if","any",")","will","have","an","identical","tower",".","Required","if","`","context_feature_num","`","is","specified",".","activation",":","Activation","function","applied","to","each","layer",".","If","`","None","`",",","will","use","an","identity","activation",".","use_batch_norm",":","Whether","to","use","batch","normalization","after","each","hidden","layer",".","batch_norm_moment",":","Momentum","for","the","moving","average","in","batch","normalization",".","dropout",":","When","not","`","None","`",",","the","probability","of","dropout","for","the","dropoout","layer","in","each","tower",".","name",":","Name","of","the","Keras","layer",".","*","*","kwargs",":","Keyword","arguments","."]
code: def __init__(
      self,
      example_feature_num: int,
      example_hidden_layer_dims: List[int],
      context_feature_num: Optional[int] = None,
      context_hidden_layer_dims: Optional[List[int]] = None,
      activation: Optional[Callable[..., tf.Tensor]] = None,
      use_batch_norm: bool = True,
      batch_norm_moment: float = 0.999,
      dropout: float = 0.5,
      name: Optional[str] = None,
      **kwargs: Dict[Any, Any],
  ):
      """Initializes the layer.
  
      Args:
        example_feature_num: Number of example features.
        example_hidden_layer_dims: Iterable of number hidden units for an tower.
          Each example feature will have an identical tower.
        context_feature_num: Number of context features. If `None` or 0 then no
          context weighting will be applied, otherwise `context_hidden_layer_dims`
          is required.
        context_hidden_layer_dims: Iterable of number hidden units for an tower.
          Each context feature (if any) will have an identical tower. Required if
          `context_feature_num` is specified.
        activation: Activation function applied to each layer. If `None`, will use
          an identity activation.
        use_batch_norm: Whether to use batch normalization after each hidden
          layer.
        batch_norm_moment: Momentum for the moving average in batch normalization.
        dropout: When not `None`, the probability of dropout for the dropoout
          layer in each tower.
        name: Name of the Keras layer.
        **kwargs: Keyword arguments.
      """
  
      super().__init__(name=name, **kwargs)
      self._example_feature_num = example_feature_num
      self._context_feature_num = context_feature_num
      self._example_hidden_layer_dims = example_hidden_layer_dims
      self._context_hidden_layer_dims = context_hidden_layer_dims
      self._activation = tf.keras.activations.get(activation)
      self._use_batch_norm = use_batch_norm
      self._batch_norm_moment = batch_norm_moment
      self._dropout = dropout
  
      self._example_towers = []
      for i in range(self._example_feature_num):
          self._example_towers.append(
              create_tower(
                  hidden_layer_dims=self._example_hidden_layer_dims,
                  output_units=1,
                  activation=self._activation,
                  use_batch_norm=self._use_batch_norm,
                  batch_norm_moment=self._batch_norm_moment,
                  dropout=self._dropout,
                  name="{}_example_tower_{}".format(name, i),
              )
          )
  
      self._context_towers = None
      if context_feature_num and context_feature_num > 0:
          if not context_hidden_layer_dims:
              raise ValueError(
                  "When `context_feature_num` > 0, `context_hidden_layer_dims` is "
                  "required! Currently `context_feature_num` is {}, but "
                  "`context_hidden_layer_dims` is {}".format(
                      context_feature_num, context_hidden_layer_dims
                  )
              )
          self._context_towers = []
          for i in range(self._context_feature_num):
              self._context_towers.append(
                  create_tower(
                      hidden_layer_dims=self._context_hidden_layer_dims,
                      output_units=self._example_feature_num,
                      activation=self._activation,
                      use_batch_norm=self._use_batch_norm,
                      batch_norm_moment=self._batch_norm_moment,
                      dropout=self._dropout,
                      name="{}_context_tower_{}".format(name, i),
                  )
              )
  
imports: import math
  from typing import Any, Callable, Dict, List, Optional, Tuple
  import tensorflow
  from tensorflow_ranking.python import utils
label_desc: Use image node_id 1 to create a new GAMLayer object from inherited base classes: tf.keras.layers with example: obj = GAMLayer(example_feature_num, example_hidden_layer_dims, context_feature_num, context_hidden_layer_dims, activation, use_batch_norm, batch_norm_moment, dropout, name)