class_docstr: Composition of multiple `_RankingHead.
  
  The main functionality is to create an estimator spec that
    - merges all predictions from all heads.
    - merges all eval metrics from all heads.
    - combines all the losses using weights from all heads.
class_docstr_tok: ["Composition","of","multiple","`","_RankingHead",".","The","main","functionality","is","to","create","an","estimator","spec","that","-","merges","all","predictions","from","all","heads",".","-","merges","all","eval","metrics","from","all","heads",".","-","combines","all","the","losses","using","weights","from","all","heads","."]
docstr: Constructor.
  
  Args:
    heads: A tuple or list of `_RankingHead`.
    head_weights: A tuple or list of weights.
    optimizer: If not None, use this optimizer instead of the first head's
      optimizer.
    train_op_fn: If not None, use this train_op_fn instead of the first
      head's train_op_fn.
docstr_tok: ["Constructor",".","Args",":","heads",":","A","tuple","or","list","of","`","_RankingHead","`",".","head_weights",":","A","tuple","or","list","of","weights",".","optimizer",":","If","not","None",",","use","this","optimizer","instead","of","the","first","head's","optimizer",".","train_op_fn",":","If","not","None",",","use","this","train_op_fn","instead","of","the","first","head","'s","train_op_fn","."]
code: def __init__(
      self, heads, head_weights=None, optimizer=None, train_op_fn=None
  ):
      """Constructor.
  
      Args:
        heads: A tuple or list of `_RankingHead`.
        head_weights: A tuple or list of weights.
        optimizer: If not None, use this optimizer instead of the first head's
          optimizer.
        train_op_fn: If not None, use this train_op_fn instead of the first
          head's train_op_fn.
      """
      if not heads:
          raise ValueError(
              "Must specify heads. Given: {}".format(heads)
          )
      if head_weights:
          if len(head_weights) != len(heads):
              raise ValueError(
                  "heads and head_weights must have the same size. "
                  "Given len(heads): {}. Given len(head_weights): {}.".format(
                      len(heads), len(head_weights)
                  )
              )
      for head in heads:
          if head.name is None:
              raise ValueError(
                  "All given heads must have name specified. Given: {}".format(
                      head
                  )
              )
      self._heads = tuple(heads)
      self._head_weights = (
          tuple(head_weights) if head_weights else tuple()
      )
      # pylint: disable=protected-access
      if train_op_fn is None and optimizer is None:
          # TODO: Figure out a better way to set train_op_fn and optimizer
          # for _MultiRankingHead.
          tf.compat.v1.logging.info(
              "Use the train_op_fn and optimizer from the first head."
          )
          self._train_op_fn = self._heads[0]._train_op_fn
          self._optimizer = self._heads[0]._optimizer
      else:
          self._train_op_fn = train_op_fn
          self._optimizer = optimizer
  
imports: from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  import abc
  import six
  import tensorflow
  from tensorflow import estimator
label_desc: Use image node_id 1 to create a new _MultiRankingHead object from inherited base classes: _AbstractRankingHead with example: obj = _MultiRankingHead(heads, head_weights, optimizer, train_op_fn)