parameters: (op, grad)
return_statement: return array_ops.reshape(out, input_shape), None
docstring: Gradient for Prod.
docstring_summary: Gradient for Prod.
docstring_tokens: Gradient for Prod .
function: def _ProdGrad(op, grad):
    """Gradient for Prod."""
    # The gradient can be expressed by dividing the product by each entry of the
    # input tensor, but this approach can't deal with zeros in the input.
    # Here, we avoid this problem by composing the output as a product of two
    # cumprod operations.
  
    input_shape = array_ops.shape(op.inputs[0])
  
    # Expand grad to full input shape
    output_shape_kept_dims = math_ops.reduced_shape(input_shape, op.inputs[1])
    tile_scaling = _safe_shape_div(input_shape, output_shape_kept_dims)
    grad = array_ops.reshape(grad, output_shape_kept_dims)
    grad = array_ops.tile(grad, tile_scaling)
  
    # Pack all reduced dimensions into a single one, so we can perform the
    # cumprod ops. If the reduction dims list is empty, it defaults to float32,
    # so we need to cast here.
    reduced = math_ops.cast(op.inputs[1], dtypes.int32)
    idx = math_ops.range(0, array_ops.rank(op.inputs[0]))
    other, _ = array_ops.listdiff(idx, reduced)
    perm = array_ops.concat(0, [reduced, other])
    reduced_num = math_ops.reduce_prod(array_ops.gather(input_shape, reduced))
    other_num = math_ops.reduce_prod(array_ops.gather(input_shape, other))
    permuted = array_ops.transpose(op.inputs[0], perm)
    permuted_shape = array_ops.shape(permuted)
    reshaped = array_ops.reshape(permuted, (reduced_num, other_num))
  
    # Calculate product, leaving out the current entry
    left = math_ops.cumprod(reshaped, axis=0, exclusive=True)
    right = math_ops.cumprod(reshaped, axis=0, exclusive=True, reverse=True)
    y = array_ops.reshape(left * right, permuted_shape)
  
    # Invert the transpose and reshape operations.
    # Make sure to set the statically known shape information through a reshape.
    out = grad * array_ops.transpose(y, array_ops.invert_permutation(perm))
    return array_ops.reshape(out, input_shape), None
function_tokens: def _ProdGrad ( op , grad ) : # The gradient can be expressed by dividing the product by each entry of the # input tensor, but this approach can't deal with zeros in the input. # Here, we avoid this problem by composing the output as a product of two # cumprod operations. input_shape = array_ops . shape ( op . inputs [ 0 ] ) # Expand grad to full input shape output_shape_kept_dims = math_ops . reduced_shape ( input_shape , op . inputs [ 1 ] ) tile_scaling = _safe_shape_div ( input_shape , output_shape_kept_dims ) grad = array_ops . reshape ( grad , output_shape_kept_dims ) grad = array_ops . tile ( grad , tile_scaling ) # Pack all reduced dimensions into a single one, so we can perform the # cumprod ops. If the reduction dims list is empty, it defaults to float32, # so we need to cast here. reduced = math_ops . cast ( op . inputs [ 1 ] , dtypes . int32 ) idx = math_ops . range ( 0 , array_ops . rank ( op . inputs [ 0 ] ) ) other , _ = array_ops . listdiff ( idx , reduced ) perm = array_ops . concat ( 0 , [ reduced , other ] ) reduced_num = math_ops . reduce_prod ( array_ops . gather ( input_shape , reduced ) ) other_num = math_ops . reduce_prod ( array_ops . gather ( input_shape , other ) ) permuted = array_ops . transpose ( op . inputs [ 0 ] , perm ) permuted_shape = array_ops . shape ( permuted ) reshaped = array_ops . reshape ( permuted , ( reduced_num , other_num ) ) # Calculate product, leaving out the current entry left = math_ops . cumprod ( reshaped , axis = 0 , exclusive = True ) right = math_ops . cumprod ( reshaped , axis = 0 , exclusive = True , reverse = True ) y = array_ops . reshape ( left * right , permuted_shape ) # Invert the transpose and reshape operations. # Make sure to set the statically known shape information through a reshape. out = grad * array_ops . transpose ( y , array_ops . invert_permutation ( perm ) ) return array_ops . reshape ( out , input_shape ) , None