parameters: (grads, op, loop_state, aggregation_method=None)
return_statement: return out_grads
docstring: Get the aggregated gradients for op.
  
    Args:
      grads: The map of memoized gradients.
      op: The op to get gradients for.
      loop_state: An object for maintaining the state of the while loops in the
                  graph. It is of type ControlFlowState. None if the graph
                  contains no while loops.
      aggregation_method: Specifies the method used to combine gradient terms.
        Accepted values are constants defined in the class `AggregationMethod`.
  
    Returns:
      A list of gradients, one per each output of `op`. If the gradients
        for a particular output is a list, this function aggregates it
        before returning.
  
    Raises:
      TypeError: if the incoming grads are not Tensors or IndexedSlices.
      ValueError: if the arguments are invalid.
docstring_summary: Get the aggregated gradients for op.
docstring_tokens: Get the aggregated gradients for op .
function: def _AggregatedGrads(grads, op, loop_state, aggregation_method=None):
    """Get the aggregated gradients for op.
  
    Args:
      grads: The map of memoized gradients.
      op: The op to get gradients for.
      loop_state: An object for maintaining the state of the while loops in the
                  graph. It is of type ControlFlowState. None if the graph
                  contains no while loops.
      aggregation_method: Specifies the method used to combine gradient terms.
        Accepted values are constants defined in the class `AggregationMethod`.
  
    Returns:
      A list of gradients, one per each output of `op`. If the gradients
        for a particular output is a list, this function aggregates it
        before returning.
  
    Raises:
      TypeError: if the incoming grads are not Tensors or IndexedSlices.
      ValueError: if the arguments are invalid.
  
    """
    if aggregation_method is None:
      aggregation_method = AggregationMethod.DEFAULT
    if aggregation_method not in [AggregationMethod.ADD_N,
                                  AggregationMethod.EXPERIMENTAL_TREE,
                                  AggregationMethod.EXPERIMENTAL_ACCUMULATE_N]:
      raise ValueError(
          "Invalid aggregation_method specified %s." % aggregation_method)
    out_grads = _GetGrads(grads, op)
    for i, out_grad in enumerate(out_grads):
      if loop_state:
        if isinstance(out_grad, (ops.Tensor, ops.IndexedSlices)):
          assert control_flow_ops.IsLoopSwitch(op)
          continue
      # Grads have to be Tensors or IndexedSlices
      if (isinstance(out_grad, collections.Sequence) and
          not all([isinstance(g, (ops.Tensor, ops.IndexedSlices))
                   for g in out_grad if g is not None])):
        raise TypeError("gradients have to be either all Tensors "
                        "or all IndexedSlices")
      # Aggregate multiple gradients, and convert [] to None.
      if out_grad:
        if len(out_grad) < 2:
          used = "nop"
          out_grads[i] = out_grad[0]
        elif all([isinstance(g, ops.Tensor) for g in out_grad if g is not None]):
          tensor_shape = _AccumulatorShape(out_grad)
          if (aggregation_method == AggregationMethod.EXPERIMENTAL_ACCUMULATE_N
              and len(out_grad) > 2 and tensor_shape.is_fully_defined()):
            # The benefit of using AccumulateN is that its inputs can be combined
            # in any order and this can allow the expression to be evaluated with
            # a smaller memory footprint.  When used with gpu_allocator_retry,
            # it is possible to compute a sum of terms which are much larger than
            # total GPU memory.
            # AccumulateN can currently only be used if we know the shape for
            # an accumulator variable.  If this is not known, or if we only have
            # 2 grads then we fall through to the "tree" case below.
            used = "accumulate_n"
            out_grads[i] = math_ops.accumulate_n(out_grad)
          elif aggregation_method in [AggregationMethod.EXPERIMENTAL_TREE,
                                      AggregationMethod.EXPERIMENTAL_ACCUMULATE_N
                                     ]:
            # Aggregate all gradients by doing pairwise sums: this may
            # reduce performance, but it can improve memory because the
            # gradients can be released earlier.
            #
            # TODO(vrv): Consider replacing this with a version of
            # tf.AddN() that eagerly frees its inputs as soon as they are
            # ready, so the order of this tree does not become a problem.
            used = "tree"
            with ops.name_scope(op.name + "_gradient_sum"):
              running_sum = out_grad[0]
              for grad in out_grad[1:]:
                running_sum = math_ops.add_n([running_sum, grad])
              out_grads[i] = running_sum
          else:
            used = "add_n"
            out_grads[i] = _MultiDeviceAddN(out_grad)
          logging.vlog(2, "  _AggregatedGrads %d x %s using %s", len(out_grad),
                       tensor_shape, used)
        else:
          out_grad = math_ops._as_indexed_slices_list([g for g in out_grad
                                                       if g is not None])
          out_grad = [_HandleNestedIndexedSlices(x) for x in out_grad]
          # Form IndexedSlices out of the concatenated values and
          # indices.
          out_grads[i] = ops.IndexedSlices(
              array_ops.concat(0, [x.values for x in out_grad]),
              array_ops.concat(0, [x.indices
                                   for x in out_grad]), out_grad[0].dense_shape)
      else:
        out_grads[i] = []
    return out_grads
function_tokens: def _AggregatedGrads ( grads , op , loop_state , aggregation_method = None ) : if aggregation_method is None : aggregation_method = AggregationMethod . DEFAULT if aggregation_method not in [ AggregationMethod . ADD_N , AggregationMethod . EXPERIMENTAL_TREE , AggregationMethod . EXPERIMENTAL_ACCUMULATE_N ] : raise ValueError ( "Invalid aggregation_method specified %s." % aggregation_method ) out_grads = _GetGrads ( grads , op ) for i , out_grad in enumerate ( out_grads ) : if loop_state : if isinstance ( out_grad , ( ops . Tensor , ops . IndexedSlices ) ) : assert control_flow_ops . IsLoopSwitch ( op ) continue # Grads have to be Tensors or IndexedSlices if ( isinstance ( out_grad , collections . Sequence ) and not all ( [ isinstance ( g , ( ops . Tensor , ops . IndexedSlices ) ) for g in out_grad if g is not None ] ) ) : raise TypeError ( "gradients have to be either all Tensors " "or all IndexedSlices" ) # Aggregate multiple gradients, and convert [] to None. if out_grad : if len ( out_grad ) < 2 : used = "nop" out_grads [ i ] = out_grad [ 0 ] elif all ( [ isinstance ( g , ops . Tensor ) for g in out_grad if g is not None ] ) : tensor_shape = _AccumulatorShape ( out_grad ) if ( aggregation_method == AggregationMethod . EXPERIMENTAL_ACCUMULATE_N and len ( out_grad ) > 2 and tensor_shape . is_fully_defined ( ) ) : # The benefit of using AccumulateN is that its inputs can be combined # in any order and this can allow the expression to be evaluated with # a smaller memory footprint.  When used with gpu_allocator_retry, # it is possible to compute a sum of terms which are much larger than # total GPU memory. # AccumulateN can currently only be used if we know the shape for # an accumulator variable.  If this is not known, or if we only have # 2 grads then we fall through to the "tree" case below. used = "accumulate_n" out_grads [ i ] = math_ops . accumulate_n ( out_grad ) elif aggregation_method in [ AggregationMethod . EXPERIMENTAL_TREE , AggregationMethod . EXPERIMENTAL_ACCUMULATE_N ] : # Aggregate all gradients by doing pairwise sums: this may # reduce performance, but it can improve memory because the # gradients can be released earlier. # # TODO(vrv): Consider replacing this with a version of # tf.AddN() that eagerly frees its inputs as soon as they are # ready, so the order of this tree does not become a problem. used = "tree" with ops . name_scope ( op . name + "_gradient_sum" ) : running_sum = out_grad [ 0 ] for grad in out_grad [ 1 : ] : running_sum = math_ops . add_n ( [ running_sum , grad ] ) out_grads [ i ] = running_sum else : used = "add_n" out_grads [ i ] = _MultiDeviceAddN ( out_grad ) logging . vlog ( 2 , "  _AggregatedGrads %d x %s using %s" , len ( out_grad ) , tensor_shape , used ) else : out_grad = math_ops . _as_indexed_slices_list ( [ g for g in out_grad if g is not None ] ) out_grad = [ _HandleNestedIndexedSlices ( x ) for x in out_grad ] # Form IndexedSlices out of the concatenated values and # indices. out_grads [ i ] = ops . IndexedSlices ( array_ops . concat ( 0 , [ x . values for x in out_grad ] ) , array_ops . concat ( 0 , [ x . indices for x in out_grad ] ) , out_grad [ 0 ] . dense_shape ) else : out_grads [ i ] = [ ] return out_grads