def reduce_max(input_tensor, reduction_indices=None, keep_dims=False, name=None): """Computes the maximum of elements across dimensions of a tensor. Reduces `input_tensor` along the dimensions given in `reduction_indices`. Unless `keep_dims` is true, the rank of the tensor is reduced by 1 for each entry in `reduction_indices`. If `keep_dims` is true, the reduced dimensions are retained with length 1. If `reduction_indices` has no entries, all dimensions are reduced, and a tensor with a single element is returned. Args: input_tensor: The tensor to reduce. Should have numeric type. reduction_indices: The dimensions to reduce. If `None` (the default), reduces all dimensions. keep_dims: If true, retains reduced dimensions with length 1. name: A name for the operation (optional). Returns: The reduced tensor. """ return gen_math_ops._max(input_tensor, _ReductionDims(input_tensor, reduction_indices), keep_dims, name=name)
def sequence_mask_mid(lengths, maxlen=None, dtype=dtypes.bool, name=None): """Return a mask tensor representing the first N positions of each row. Example: ```python tf.sequence_mask([1, 3, 2], 5) = [[True, False, False, False, False], [False,False, False, False, False], [False, True, False, False, False]] ``` Args: lengths: 1D integer tensor, all its values < maxlen. maxlen: scalar integer tensor, maximum length of each row. Default: use maximum over lengths. dtype: output type of the resulting tensor. name: name of the op. Returns: A 2D mask tensor, as shown in the example above, cast to specified dtype. Raises: ValueError: if the arguments have invalid rank. """ with ops.name_scope(name, "SequenceMask", [lengths, maxlen]): lengths = (np.array(lengths)) / 2 lengths = ops.convert_to_tensor(lengths, dtype=tf.int32) # lengths = ops.convert_to_tensor(lengths) if lengths.get_shape().ndims != 1: raise ValueError("lengths must be 1D for sequence_mask") if maxlen is None: maxlen = gen_math_ops._max(lengths, [0]) else: maxlen = ops.convert_to_tensor(maxlen) if maxlen.get_shape().ndims != 0: raise ValueError("maxlen must be scalar for sequence_mask") # The basic idea is to compare a range row vector of size maxlen: # [0, 1, 2, 3, 4] # to length as a matrix with 1 column: [[1], [3], [2]]. # Because of broadcasting on both arguments this comparison results # in a matrix of size (len(lengths), maxlen) row_vector = gen_math_ops._range(constant(0, maxlen.dtype), maxlen, constant(1, maxlen.dtype)) # Since maxlen >= max(lengths), it is safe to use maxlen as a cast # authoritative type. Whenever maxlen fits into tf.int32, so do the lengths. matrix_0 = gen_math_ops.cast(expand_dims(lengths, 1), maxlen.dtype) matrix_1 = gen_math_ops.cast(expand_dims(lengths - 1, 1), maxlen.dtype) result_0 = (row_vector < matrix_0) result_1 = (row_vector >= matrix_1) result = tf.logical_and(result_0, result_1) if dtype is None or result.dtype.base_dtype == dtype.base_dtype: return result else: return gen_math_ops.cast(result, dtype)
def sequence_mask(lengths, maxlen=None, dtype=dtypes.bool, name=None): """Returns a mask tensor representing the first N positions of each cell. If `lengths` has shape `[d_1, d_2, ..., d_n]` the resulting tensor `mask` has dtype `dtype` and shape `[d_1, d_2, ..., d_n, maxlen]`, with ``` mask[i_1, i_2, ..., i_n, j] = (j < lengths[i_1, i_2, ..., i_n]) ``` Examples: ```python tf.sequence_mask([1, 3, 2], 5) # [[True, False, False, False, False], # [True, True, True, False, False], # [True, True, False, False, False]] tf.sequence_mask([[1, 3],[2,0]]) # [[[True, False, False], # [True, True, True]], # [[True, True, False], # [False, False, False]]] ``` Args: lengths: integer tensor, all its values <= maxlen. maxlen: scalar integer tensor, size of last dimension of returned tensor. Default is the maximum value in `lengths`. dtype: output type of the resulting tensor. name: name of the op. Returns: A mask tensor of shape `lengths.shape + (maxlen,)`, cast to specified dtype. Raises: ValueError: if `maxlen` is not a scalar. """ with ops.name_scope(name, "SequenceMask", [lengths, maxlen]): lengths = ops.convert_to_tensor(lengths) if maxlen is None: maxlen = gen_math_ops._max(lengths, _all_dimensions(lengths)) maxlen = gen_math_ops.maximum(constant(0, maxlen.dtype), maxlen) else: maxlen = ops.convert_to_tensor(maxlen) if maxlen.get_shape( ).ndims is not None and maxlen.get_shape().ndims != 0: raise ValueError("maxlen must be scalar for sequence_mask") # The basic idea is to compare a range row vector of size maxlen: # [0, 1, 2, 3, 4] # to length as a matrix with 1 column: [[1], [3], [2]]. # Because of broadcasting on both arguments this comparison results # in a matrix of size (len(lengths), maxlen) row_vector = gen_math_ops._range(constant(0, maxlen.dtype), maxlen, constant(1, maxlen.dtype)) # Since maxlen >= max(lengths), it is safe to use maxlen as a cast # authoritative type. Whenever maxlen fits into tf.int32, so do the lengths. matrix = gen_math_ops.cast(expand_dims(lengths, -1), maxlen.dtype) result = row_vector < matrix if dtype is None or result.dtype.base_dtype == dtype.base_dtype: return result else: return gen_math_ops.cast(result, dtype)
def repeat_with_axis(data, repeats, axis, name=None): """Repeats elements of `data`. Args: data: An `N`-dimensional tensor. repeats: A 1-D integer tensor specifying how many times each element in `axis` should be repeated. `len(repeats)` must equal `data.shape[axis]`. Supports broadcasting from a scalar value. axis: `int`. The axis along which to repeat values. Must be less than `max(N, 1)`. name: A name for the operation. Returns: A tensor with `max(N, 1)` dimensions. Has the same shape as `data`, except that dimension `axis` has size `sum(repeats)`. #### Examples: ```python >>> repeat(['a', 'b', 'c'], repeats=[3, 0, 2], axis=0) ['a', 'a', 'a', 'c', 'c'] >>> repeat([[1, 2], [3, 4]], repeats=[2, 3], axis=0) [[1, 2], [1, 2], [3, 4], [3, 4], [3, 4]] >>> repeat([[1, 2], [3, 4]], repeats=[2, 3], axis=1) [[1, 1, 2, 2, 2], [3, 3, 4, 4, 4]] ``` """ if not isinstance(axis, int): raise TypeError("axis must be an int; got %s" % type(axis).__name__) with ops.name_scope(name, "Repeat", [data, repeats]): data = ops.convert_to_tensor(data, name="data") repeats = convert_to_int_tensor(repeats, name="repeats") repeats.shape.with_rank_at_most(1) # If `data` is a scalar, then upgrade it to a vector. data = _with_nonzero_rank(data) data_shape = shape(data) # If `axis` is negative, then convert it to a positive value. axis = get_positive_axis(axis, data.shape.ndims) # Check data Tensor shapes. if repeats.shape.ndims == 1: data.shape.dims[axis].assert_is_compatible_with(repeats.shape[0]) # If we know that `repeats` is a scalar, then we can just tile & reshape. if repeats.shape.ndims == 0: expanded = expand_dims(data, axis + 1) tiled = tile_one_dimension(expanded, axis + 1, repeats) result_shape = concat([data_shape[:axis], [-1], data_shape[axis + 1:]], axis=0) return tf.reshape(tiled, result_shape) # Broadcast the `repeats` tensor so rank(repeats) == axis + 1. if repeats.shape.ndims != axis + 1: repeats_shape = shape(repeats) repeats_ndims = rank(repeats) broadcast_shape = concat( [data_shape[:axis + 1 - repeats_ndims], repeats_shape], axis=0) repeats = broadcast_to(repeats, broadcast_shape) repeats.set_shape([None] * (axis + 1)) # Create a "sequence mask" based on `repeats`, where slices across `axis` # contain one `True` value for each repetition. E.g., if # `repeats = [3, 1, 2]`, then `mask = [[1, 1, 1], [1, 0, 0], [1, 1, 0]]`. max_repeat = gen_math_ops.maximum( 0, gen_math_ops._max(repeats, _all_dimensions(repeats))) mask = tf.sequence_mask(repeats, max_repeat) # Add a new dimension around each value that needs to be repeated, and # then tile that new dimension to match the maximum number of repetitions. expanded = expand_dims(data, axis + 1) tiled = tile_one_dimension(expanded, axis + 1, max_repeat) # Use `boolean_mask` to discard the extra repeated values. This also # flattens all dimensions up through `axis`. masked = tf.boolean_mask(tiled, mask) # Reshape the output tensor to add the outer dimensions back. if axis == 0: result = masked else: result_shape = concat([data_shape[:axis], [-1], data_shape[axis + 1:]], axis=0) result = tf.reshape(masked, result_shape) # Preserve shape information. if data.shape.ndims is not None: new_axis_size = 0 if repeats.shape[0] == 0 else None result.set_shape(data.shape[:axis].concatenate( [new_axis_size]).concatenate(data.shape[axis + 1:])) return result