diff options
author | 2018-01-09 13:32:17 -0800 | |
---|---|---|
committer | 2018-01-09 13:36:12 -0800 | |
commit | 3e852d462aaba446f62f76007405c0794a6087b9 (patch) | |
tree | 790dc1747aa319facc98f18450a94015f83a9a89 /tensorflow/core/ops/array_ops.cc | |
parent | 55cd506ab8220c6a1075965eb7839cac4af1db3e (diff) |
Automated g4 rollback of changelist 180691955
PiperOrigin-RevId: 181365803
Diffstat (limited to 'tensorflow/core/ops/array_ops.cc')
-rw-r--r-- | tensorflow/core/ops/array_ops.cc | 3073 |
1 files changed, 94 insertions, 2979 deletions
diff --git a/tensorflow/core/ops/array_ops.cc b/tensorflow/core/ops/array_ops.cc index 29ae20d086..b4c312ff66 100644 --- a/tensorflow/core/ops/array_ops.cc +++ b/tensorflow/core/ops/array_ops.cc @@ -261,33 +261,7 @@ REGISTER_OP("ParallelConcat") c->set_output(0, passed_shape); return Status::OK(); - }) - .Doc(R"doc( -Concatenates a list of `N` tensors along the first dimension. - -The input tensors are all required to have size 1 in the first dimension. - -For example: - -``` -# 'x' is [[1, 4]] -# 'y' is [[2, 5]] -# 'z' is [[3, 6]] -parallel_concat([x, y, z]) => [[1, 4], [2, 5], [3, 6]] # Pack along first dim. -``` - -The difference between concat and parallel_concat is that concat requires all -of the inputs be computed before the operation will begin but doesn't require -that the input shapes be known during graph construction. Parallel concat -will copy pieces of the input into the output as they become available, in -some situations this can provide a performance benefit. - -values: Tensors to be concatenated. All must have size 1 in the first dimension - and same shape. -output: The concatenated tensor. -shape: the final shape of the result; should be equal to the shapes of any input - but with the number of input values in the first dimension. -)doc"); + }); REGISTER_OP("Pack") .Input("values: N * T") @@ -323,35 +297,7 @@ REGISTER_OP("Pack") c->set_output(0, c->MakeShape(dims)); return Status::OK(); - }) - .Doc(R"doc( -Packs a list of `N` rank-`R` tensors into one rank-`(R+1)` tensor. - -Packs the `N` tensors in `values` into a tensor with rank one higher than each -tensor in `values`, by packing them along the `axis` dimension. -Given a list of tensors of shape `(A, B, C)`; - -if `axis == 0` then the `output` tensor will have the shape `(N, A, B, C)`. -if `axis == 1` then the `output` tensor will have the shape `(A, N, B, C)`. -Etc. - -For example: - -``` -# 'x' is [1, 4] -# 'y' is [2, 5] -# 'z' is [3, 6] -pack([x, y, z]) => [[1, 4], [2, 5], [3, 6]] # Pack along first dim. -pack([x, y, z], axis=1) => [[1, 2, 3], [4, 5, 6]] -``` - -This is the opposite of `unpack`. - -values: Must be of same shape and type. -axis: Dimension along which to pack. Negative values wrap around, so the - valid range is `[-(R+1), R+1)`. -output: The packed tensor. -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("Unpack") @@ -387,28 +333,7 @@ REGISTER_OP("Unpack") } for (int i = 0; i < c->num_outputs(); ++i) c->set_output(i, out); return Status::OK(); - }) - .Doc(R"doc( -Unpacks a given dimension of a rank-`R` tensor into `num` rank-`(R-1)` tensors. - -Unpacks `num` tensors from `value` by chipping it along the `axis` dimension. -For example, given a tensor of shape `(A, B, C, D)`; - -If `axis == 0` then the i'th tensor in `output` is the slice `value[i, :, :, :]` - and each tensor in `output` will have shape `(B, C, D)`. (Note that the - dimension unpacked along is gone, unlike `split`). - -If `axis == 1` then the i'th tensor in `output` is the slice `value[:, i, :, :]` - and each tensor in `output` will have shape `(A, C, D)`. -Etc. - -This is the opposite of `pack`. - -value: 1-D or higher, with `axis` dimension size equal to `num`. -axis: Dimension along which to unpack. Negative values wrap around, so the - valid range is `[-R, R)`. -output: The list of tensors unpacked from `value`. -)doc"); + }); // -------------------------------------------------------------------------- // TODO(josh11b): Remove the >= 2 constraint, once we can rewrite the graph @@ -421,18 +346,7 @@ REGISTER_OP("Concat") .Attr("T: type") .SetShapeFn([](InferenceContext* c) { return shape_inference::ConcatShape(c, c->num_inputs() - 1); - }) - .Doc(R"doc( -Concatenates tensors along one dimension. - -concat_dim: 0-D. The dimension along which to concatenate. Must be in the - range [0, rank(values)). -values: The `N` Tensors to concatenate. Their ranks and types must match, - and their sizes must match in all dimensions except `concat_dim`. -output: A `Tensor` with the concatenation of values stacked along the - `concat_dim` dimension. This tensor's shape matches that of `values` except - in `concat_dim` where it has the sum of the sizes. -)doc"); + }); REGISTER_OP("ConcatV2") .Input("values: N * T") @@ -441,18 +355,7 @@ REGISTER_OP("ConcatV2") .Attr("N: int >= 2") .Attr("T: type") .Attr("Tidx: {int32, int64} = DT_INT32") - .SetShapeFn(shape_inference::ConcatV2Shape) - .Doc(R"doc( -Concatenates tensors along one dimension. - -values: List of `N` Tensors to concatenate. Their ranks and types must match, - and their sizes must match in all dimensions except `concat_dim`. -axis: 0-D. The dimension along which to concatenate. Must be in the - range [-rank(values), rank(values)). -output: A `Tensor` with the concatenation of values stacked along the - `concat_dim` dimension. This tensor's shape matches that of `values` except - in `concat_dim` where it has the sum of the sizes. -)doc"); + .SetShapeFn(shape_inference::ConcatV2Shape); // TODO(vivek.v.rane@intel.com): Prefix the op names with underscore if the ops // are not to be made user-accessible. @@ -486,26 +389,7 @@ REGISTER_OP("ConcatOffset") c->set_output(i - 1, c->input(i)); } return Status::OK(); - }) - .Doc(R"doc( -Computes offsets of concat inputs within its output. - -For example: - -``` -# 'x' is [2, 2, 7] -# 'y' is [2, 3, 7] -# 'z' is [2, 5, 7] -concat_offset(2, [x, y, z]) => [0, 0, 0], [0, 2, 0], [0, 5, 0] -``` - -This is typically used by gradient computations for a concat operation. - -concat_dim: The dimension along which to concatenate. -shape: The `N` int32 vectors representing shape of tensors being concatenated. -offset: The `N` int32 vectors representing the starting offset - of input tensors within the concatenated output. -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("Split") @@ -540,19 +424,7 @@ REGISTER_OP("Split") } for (int i = 0; i < num_split; ++i) c->set_output(i, out); return Status::OK(); - }) - .Doc(R"doc( -Splits a tensor into `num_split` tensors along one dimension. - -split_dim: 0-D. The dimension along which to split. Must be in the range - `[-rank(value), rank(value))`. -num_split: The number of ways to split. Must evenly divide - `value.shape[split_dim]`. -value: The tensor to split. -output: They are identically shaped tensors, whose shape matches that of `value` - except along `split_dim`, where their sizes are - `values.shape[split_dim] / num_split`. -)doc"); + }); REGISTER_OP("SplitV") .Input("value: T") @@ -647,20 +519,7 @@ REGISTER_OP("SplitV") } return Status::OK(); - }) - .Doc(R"doc( -Splits a tensor into `num_split` tensors along one dimension. - -value: The tensor to split. -size_splits: list containing the sizes of each output tensor along the split - dimension. Must sum to the dimension of value along split_dim. - Can contain one -1 indicating that dimension is to be inferred. -split_dim: 0-D. The dimension along which to split. Must be in the range - `[-rank(value), rank(value))`. -output: Tensors whose shape matches that of `value` - except along `split_dim`, where their sizes are - `size_splits[i]`. -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("Const") @@ -679,12 +538,7 @@ REGISTER_OP("Const") } c->set_output(0, c->MakeShape(dims)); return Status::OK(); - }) - .Doc(R"doc( -Returns a constant tensor. - -value: Attr `value` is the tensor to return. -)doc"); + }); // -------------------------------------------------------------------------- // TODO(mgubin): Update the doc when the freeze_graph script supports converting @@ -694,17 +548,7 @@ REGISTER_OP("ImmutableConst") .Attr("shape: shape") .Attr("memory_region_name: string") .Output("tensor: dtype") - .SetShapeFn(shape_inference::ExplicitShape) - .Doc(R"doc( -Returns immutable tensor from memory region. - -The current implementation memmaps the tensor from a file. - -dtype: Type of the returned tensor. -shape: Shape of the returned tensor. -memory_region_name: Name of readonly memory region used by the tensor, see - NewReadOnlyMemoryRegionFromFile in tensorflow::Env. -)doc"); + .SetShapeFn(shape_inference::ExplicitShape); REGISTER_OP("GuaranteeConst") .Input("input: T") @@ -714,30 +558,14 @@ REGISTER_OP("GuaranteeConst") return UnchangedShape(c); }) // We don't want this to be optimized away. - .SetIsStateful() - .Doc(R"( -Gives a guarantee to the TF runtime that the input tensor is a constant. - -The runtime is then free to make optimizations based on this. - -Only accepts value typed tensors as inputs and rejects resource variable handles -as input. - -Returns the input tensor without modification. -)"); + .SetIsStateful(); // -------------------------------------------------------------------------- REGISTER_OP("ZerosLike") .Input("x: T") .Output("y: T") .Attr("T: type") - .SetShapeFn(shape_inference::UnchangedShape) - .Doc(R"doc( -Returns a tensor of zeros with the same shape and type as x. - -x: a tensor of type T. -y: a tensor of the same shape and type as x but filled with zeros. -)doc"); + .SetShapeFn(shape_inference::UnchangedShape); // -------------------------------------------------------------------------- REGISTER_OP("OnesLike") @@ -746,13 +574,7 @@ REGISTER_OP("OnesLike") .Attr( "T: {bfloat16, float, double, int8, uint8, int16, uint16, int32, " "int64, complex64, complex128, bool}") - .SetShapeFn(shape_inference::UnchangedShape) - .Doc(R"doc( -Returns a tensor of ones with the same shape and type as x. - -x: a tensor of type T. -y: a tensor of the same shape and type as x but filled with ones. -)doc"); + .SetShapeFn(shape_inference::UnchangedShape); // -------------------------------------------------------------------------- REGISTER_OP("Diag") @@ -767,30 +589,7 @@ REGISTER_OP("Diag") TF_RETURN_IF_ERROR(c->Concatenate(in, in, &out)); c->set_output(0, out); return Status::OK(); - }) - .Doc(R"doc( -Returns a diagonal tensor with a given diagonal values. - -Given a `diagonal`, this operation returns a tensor with the `diagonal` and -everything else padded with zeros. The diagonal is computed as follows: - -Assume `diagonal` has dimensions [D1,..., Dk], then the output is a tensor of -rank 2k with dimensions [D1,..., Dk, D1,..., Dk] where: - -`output[i1,..., ik, i1,..., ik] = diagonal[i1, ..., ik]` and 0 everywhere else. - -For example: - -``` -# 'diagonal' is [1, 2, 3, 4] -tf.diag(diagonal) ==> [[1, 0, 0, 0] - [0, 2, 0, 0] - [0, 0, 3, 0] - [0, 0, 0, 4]] -``` - -diagonal: Rank k tensor where k is at most 1. -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("DiagPart") @@ -819,33 +618,7 @@ REGISTER_OP("DiagPart") } c->set_output(0, c->MakeShape(dims)); return Status::OK(); - }) - .Doc(R"doc( -Returns the diagonal part of the tensor. - -This operation returns a tensor with the `diagonal` part -of the `input`. The `diagonal` part is computed as follows: - -Assume `input` has dimensions `[D1,..., Dk, D1,..., Dk]`, then the output is a -tensor of rank `k` with dimensions `[D1,..., Dk]` where: - -`diagonal[i1,..., ik] = input[i1, ..., ik, i1,..., ik]`. - -For example: - -``` -# 'input' is [[1, 0, 0, 0] - [0, 2, 0, 0] - [0, 0, 3, 0] - [0, 0, 0, 4]] - -tf.diag_part(input) ==> [1, 2, 3, 4] -``` - -input: Rank k tensor where k is even and not zero. -diagonal: The extracted diagonal. - -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("MatrixDiag") @@ -865,40 +638,7 @@ REGISTER_OP("MatrixDiag") c->Concatenate(in, c->Vector(c->Dim(in, rank - 1)), &out)); c->set_output(0, out); return Status::OK(); - }) - .Doc(R"doc( -Returns a batched diagonal tensor with a given batched diagonal values. - -Given a `diagonal`, this operation returns a tensor with the `diagonal` and -everything else padded with zeros. The diagonal is computed as follows: - -Assume `diagonal` has `k` dimensions `[I, J, K, ..., N]`, then the output is a -tensor of rank `k+1` with dimensions [I, J, K, ..., N, N]` where: - -`output[i, j, k, ..., m, n] = 1{m=n} * diagonal[i, j, k, ..., n]`. - -For example: - -``` -# 'diagonal' is [[1, 2, 3, 4], [5, 6, 7, 8]] - -and diagonal.shape = (2, 4) - -tf.matrix_diag(diagonal) ==> [[[1, 0, 0, 0] - [0, 2, 0, 0] - [0, 0, 3, 0] - [0, 0, 0, 4]], - [[5, 0, 0, 0] - [0, 6, 0, 0] - [0, 0, 7, 0] - [0, 0, 0, 8]]] - -which has shape (2, 4, 4) -``` - -diagonal: Rank `k`, where `k >= 1`. -output: Rank `k+1`, with `output.shape = diagonal.shape + [diagonal.shape[-1]]`. -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("MatrixSetDiag") @@ -931,27 +671,7 @@ REGISTER_OP("MatrixSetDiag") } c->set_output(0, output); return Status::OK(); - }) - .Doc(R"doc( -Returns a batched matrix tensor with new batched diagonal values. - -Given `input` and `diagonal`, this operation returns a tensor with the -same shape and values as `input`, except for the main diagonal of the -innermost matrices. These will be overwritten by the values in `diagonal`. - -The output is computed as follows: - -Assume `input` has `k+1` dimensions `[I, J, K, ..., M, N]` and `diagonal` has -`k` dimensions `[I, J, K, ..., min(M, N)]`. Then the output is a -tensor of rank `k+1` with dimensions `[I, J, K, ..., M, N]` where: - - * `output[i, j, k, ..., m, n] = diagonal[i, j, k, ..., n]` for `m == n`. - * `output[i, j, k, ..., m, n] = input[i, j, k, ..., m, n]` for `m != n`. - -input: Rank `k+1`, where `k >= 1`. -diagonal: Rank `k`, where `k >= 1`. -output: Rank `k+1`, with `output.shape = input.shape`. -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("MatrixDiagPart") @@ -976,43 +696,7 @@ REGISTER_OP("MatrixDiagPart") dims.push_back(min_dim); c->set_output(0, c->MakeShape(dims)); return Status::OK(); - }) - .Doc(R"doc( -Returns the batched diagonal part of a batched tensor. - -This operation returns a tensor with the `diagonal` part -of the batched `input`. The `diagonal` part is computed as follows: - -Assume `input` has `k` dimensions `[I, J, K, ..., M, N]`, then the output is a -tensor of rank `k - 1` with dimensions `[I, J, K, ..., min(M, N)]` where: - -`diagonal[i, j, k, ..., n] = input[i, j, k, ..., n, n]`. - -The input must be at least a matrix. - -For example: - -``` -# 'input' is [[[1, 0, 0, 0] - [0, 2, 0, 0] - [0, 0, 3, 0] - [0, 0, 0, 4]], - [[5, 0, 0, 0] - [0, 6, 0, 0] - [0, 0, 7, 0] - [0, 0, 0, 8]]] - -and input.shape = (2, 4, 4) - -tf.matrix_diag_part(input) ==> [[1, 2, 3, 4], [5, 6, 7, 8]] - -which has shape (2, 4) -``` - -input: Rank `k` tensor where `k >= 2`. -diagonal: The extracted diagonal(s) having shape - `diagonal.shape = input.shape[:-2] + [min(input.shape[-2:])]`. -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("MatrixBandPart") @@ -1021,57 +705,7 @@ REGISTER_OP("MatrixBandPart") .Input("num_upper: int64") .Output("band: T") .Attr("T: type") - .SetShapeFn(shape_inference::UnchangedShape) - .Doc(R"doc( -Copy a tensor setting everything outside a central band in each innermost matrix -to zero. - -The `band` part is computed as follows: -Assume `input` has `k` dimensions `[I, J, K, ..., M, N]`, then the output is a -tensor with the same shape where - -`band[i, j, k, ..., m, n] = in_band(m, n) * input[i, j, k, ..., m, n]`. - -The indicator function - -`in_band(m, n) = (num_lower < 0 || (m-n) <= num_lower)) && - (num_upper < 0 || (n-m) <= num_upper)`. - -For example: - -``` -# if 'input' is [[ 0, 1, 2, 3] - [-1, 0, 1, 2] - [-2, -1, 0, 1] - [-3, -2, -1, 0]], - -tf.matrix_band_part(input, 1, -1) ==> [[ 0, 1, 2, 3] - [-1, 0, 1, 2] - [ 0, -1, 0, 1] - [ 0, 0, -1, 0]], - -tf.matrix_band_part(input, 2, 1) ==> [[ 0, 1, 0, 0] - [-1, 0, 1, 0] - [-2, -1, 0, 1] - [ 0, -2, -1, 0]] -``` - -Useful special cases: - -``` - tf.matrix_band_part(input, 0, -1) ==> Upper triangular part. - tf.matrix_band_part(input, -1, 0) ==> Lower triangular part. - tf.matrix_band_part(input, 0, 0) ==> Diagonal. -``` - -input: Rank `k` tensor. -num_lower: 0-D tensor. Number of subdiagonals to keep. If negative, keep entire - lower triangle. -num_upper: 0-D tensor. Number of superdiagonals to keep. If negative, keep - entire upper triangle. -band: Rank `k` tensor of the same shape as input. The extracted banded tensor. - -)doc"); + .SetShapeFn(shape_inference::UnchangedShape); // -------------------------------------------------------------------------- REGISTER_OP("Reverse") @@ -1095,59 +729,7 @@ REGISTER_OP("Reverse") } c->set_output(0, input); return Status::OK(); - }) - .Doc(R"Doc( -Reverses specific dimensions of a tensor. - -Given a `tensor`, and a `bool` tensor `dims` representing the dimensions -of `tensor`, this operation reverses each dimension i of `tensor` where -`dims[i]` is `True`. - -`tensor` can have up to 8 dimensions. The number of dimensions -of `tensor` must equal the number of elements in `dims`. In other words: - -`rank(tensor) = size(dims)` - -For example: - -``` -# tensor 't' is [[[[ 0, 1, 2, 3], -# [ 4, 5, 6, 7], -# [ 8, 9, 10, 11]], -# [[12, 13, 14, 15], -# [16, 17, 18, 19], -# [20, 21, 22, 23]]]] -# tensor 't' shape is [1, 2, 3, 4] - -# 'dims' is [False, False, False, True] -reverse(t, dims) ==> [[[[ 3, 2, 1, 0], - [ 7, 6, 5, 4], - [ 11, 10, 9, 8]], - [[15, 14, 13, 12], - [19, 18, 17, 16], - [23, 22, 21, 20]]]] - -# 'dims' is [False, True, False, False] -reverse(t, dims) ==> [[[[12, 13, 14, 15], - [16, 17, 18, 19], - [20, 21, 22, 23] - [[ 0, 1, 2, 3], - [ 4, 5, 6, 7], - [ 8, 9, 10, 11]]]] - -# 'dims' is [False, False, True, False] -reverse(t, dims) ==> [[[[8, 9, 10, 11], - [4, 5, 6, 7], - [0, 1, 2, 3]] - [[20, 21, 22, 23], - [16, 17, 18, 19], - [12, 13, 14, 15]]]] -``` - -tensor: Up to 8-D. -dims: 1-D. The dimensions to reverse. -output: The same shape as `tensor`. -)Doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("ReverseV2") @@ -1169,62 +751,7 @@ REGISTER_OP("ReverseV2") } c->set_output(0, input); return Status::OK(); - }) - .Doc(R"Doc( -Reverses specific dimensions of a tensor. - -NOTE `tf.reverse` has now changed behavior in preparation for 1.0. -`tf.reverse_v2` is currently an alias that will be deprecated before TF 1.0. - -Given a `tensor`, and a `int32` tensor `axis` representing the set of -dimensions of `tensor` to reverse. This operation reverses each dimension -`i` for which there exists `j` s.t. `axis[j] == i`. - -`tensor` can have up to 8 dimensions. The number of dimensions specified -in `axis` may be 0 or more entries. If an index is specified more than -once, a InvalidArgument error is raised. - -For example: - -``` -# tensor 't' is [[[[ 0, 1, 2, 3], -# [ 4, 5, 6, 7], -# [ 8, 9, 10, 11]], -# [[12, 13, 14, 15], -# [16, 17, 18, 19], -# [20, 21, 22, 23]]]] -# tensor 't' shape is [1, 2, 3, 4] - -# 'dims' is [3] or 'dims' is [-1] -reverse(t, dims) ==> [[[[ 3, 2, 1, 0], - [ 7, 6, 5, 4], - [ 11, 10, 9, 8]], - [[15, 14, 13, 12], - [19, 18, 17, 16], - [23, 22, 21, 20]]]] - -# 'dims' is '[1]' (or 'dims' is '[-3]') -reverse(t, dims) ==> [[[[12, 13, 14, 15], - [16, 17, 18, 19], - [20, 21, 22, 23] - [[ 0, 1, 2, 3], - [ 4, 5, 6, 7], - [ 8, 9, 10, 11]]]] - -# 'dims' is '[2]' (or 'dims' is '[-2]') -reverse(t, dims) ==> [[[[8, 9, 10, 11], - [4, 5, 6, 7], - [0, 1, 2, 3]] - [[20, 21, 22, 23], - [16, 17, 18, 19], - [12, 13, 14, 15]]]] -``` - -tensor: Up to 8-D. -axis: 1-D. The indices of the dimensions to reverse. Must be in the range - `[-rank(tensor), rank(tensor))`. -output: The same shape as `tensor`. -)Doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("EditDistance") @@ -1266,65 +793,7 @@ REGISTER_OP("EditDistance") c->set_output(0, c->MakeShape(dims)); return Status::OK(); - }) - .Doc(R"doc( -Computes the (possibly normalized) Levenshtein Edit Distance. - -The inputs are variable-length sequences provided by SparseTensors - (hypothesis_indices, hypothesis_values, hypothesis_shape) -and - (truth_indices, truth_values, truth_shape). - -The inputs are: - -hypothesis_indices: The indices of the hypothesis list SparseTensor. - This is an N x R int64 matrix. -hypothesis_values: The values of the hypothesis list SparseTensor. - This is an N-length vector. -hypothesis_shape: The shape of the hypothesis list SparseTensor. - This is an R-length vector. -truth_indices: The indices of the truth list SparseTensor. - This is an M x R int64 matrix. -truth_values: The values of the truth list SparseTensor. - This is an M-length vector. -truth_shape: The shape of the truth list SparseTensor. - This is an R-length vector. -truth_shape: truth indices, vector. -normalize: boolean (if true, edit distances are normalized by length of truth). - -The output is: - -output: A dense float tensor with rank R - 1. - -For the example input: - - // hypothesis represents a 2x1 matrix with variable-length values: - // (0,0) = ["a"] - // (1,0) = ["b"] - hypothesis_indices = [[0, 0, 0], - [1, 0, 0]] - hypothesis_values = ["a", "b"] - hypothesis_shape = [2, 1, 1] - - // truth represents a 2x2 matrix with variable-length values: - // (0,0) = [] - // (0,1) = ["a"] - // (1,0) = ["b", "c"] - // (1,1) = ["a"] - truth_indices = [[0, 1, 0], - [1, 0, 0], - [1, 0, 1], - [1, 1, 0]] - truth_values = ["a", "b", "c", "a"] - truth_shape = [2, 2, 2] - normalize = true - -The output will be: - - // output is a 2x2 matrix with edit distances normalized by truth lengths. - output = [[inf, 1.0], // (0,0): no truth, (0,1): no hypothesis - [0.5, 1.0]] // (1,0): addition, (1,1): no hypothesis -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("Fill") @@ -1357,27 +826,7 @@ REGISTER_OP("Fill") TF_RETURN_IF_ERROR(c->MakeShapeFromShapeTensor(0, &out)); c->set_output(0, out); return Status::OK(); - }) - .Doc(R"doc( -Creates a tensor filled with a scalar value. - -This operation creates a tensor of shape `dims` and fills it with `value`. - -For example: - -``` -# Output tensor has shape [2, 3]. -fill([2, 3], 9) ==> [[9, 9, 9] - [9, 9, 9]] -``` - -dims: 1-D. Represents the shape of the output tensor. -value: 0-D (scalar). Value to fill the returned tensor. - -@compatibility(numpy) -Equivalent to np.full -@end_compatibility -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("_ParallelConcatStart") @@ -1439,36 +888,7 @@ REGISTER_OP("Gather") TF_RETURN_IF_ERROR(c->Concatenate(indices_shape, params_subshape, &out)); c->set_output(0, out); return Status::OK(); - }) - .Doc(R"doc( -Gather slices from `params` according to `indices`. - -`indices` must be an integer tensor of any dimension (usually 0-D or 1-D). -Produces an output tensor with shape `indices.shape + params.shape[1:]` where: - -```python - # Scalar indices - output[:, ..., :] = params[indices, :, ... :] - - # Vector indices - output[i, :, ..., :] = params[indices[i], :, ... :] - - # Higher rank indices - output[i, ..., j, :, ... :] = params[indices[i, ..., j], :, ..., :] -``` - -If `indices` is a permutation and `len(indices) == params.shape[0]` then -this operation will permute `params` accordingly. - -`validate_indices`: DEPRECATED. If this operation is assigned to CPU, values in -`indices` are always validated to be within range. If assigned to GPU, -out-of-bound indices result in safe but unspecified behavior, which may include -raising an error. - -<div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"> -<img style="width:100%" src="https://www.tensorflow.org/images/Gather.png" alt> -</div> -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("GatherV2") @@ -1534,40 +954,7 @@ REGISTER_OP("GatherV2") c->set_output(0, out); return Status::OK(); - }) - .Doc(R"doc( -Gather slices from `params` axis `axis` according to `indices`. - -`indices` must be an integer tensor of any dimension (usually 0-D or 1-D). -Produces an output tensor with shape `params.shape[:axis] + indices.shape + -params.shape[axis + 1:]` where: - -```python - # Scalar indices (output is rank(params) - 1). - output[a_0, ..., a_n, b_0, ..., b_n] = - params[a_0, ..., a_n, indices, b_0, ..., b_n] - - # Vector indices (output is rank(params)). - output[a_0, ..., a_n, i, b_0, ..., b_n] = - params[a_0, ..., a_n, indices[i], b_0, ..., b_n] - - # Higher rank indices (output is rank(params) + rank(indices) - 1). - output[a_0, ..., a_n, i, ..., j, b_0, ... b_n] = - params[a_0, ..., a_n, indices[i, ..., j], b_0, ..., b_n] -``` - -<div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"> -<img style="width:100%" src="https://www.tensorflow.org/images/Gather.png" alt> -</div> - -params: The tensor from which to gather values. Must be at least rank - `axis + 1`. -indices: Index tensor. Must be in range `[0, params.shape[axis])`. -axis: The axis in `params` to gather `indices` from. Defaults to the first - dimension. Supports negative indexes. -output: Values from `params` gathered from indices given by `indices`, with - shape `params.shape[:axis] + indices.shape + params.shape[axis + 1:]`. -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("GatherNd") @@ -1603,114 +990,7 @@ REGISTER_OP("GatherNd") TF_RETURN_IF_ERROR(c->Concatenate(indices_slice, params_slice, &out)); c->set_output(0, out); return Status::OK(); - }) - .Doc(R"doc( -Gather slices from `params` into a Tensor with shape specified by `indices`. - -`indices` is an K-dimensional integer tensor, best thought of as a -(K-1)-dimensional tensor of indices into `params`, where each element defines a -slice of `params`: - - output[i_0, ..., i_{K-2}] = params[indices[i0, ..., i_{K-2}]] - -Whereas in @{tf.gather} `indices` defines slices into the first -dimension of `params`, in `tf.gather_nd`, `indices` defines slices into the -first `N` dimensions of `params`, where `N = indices.shape[-1]`. - -The last dimension of `indices` can be at most the rank of -`params`: - - indices.shape[-1] <= params.rank - -The last dimension of `indices` corresponds to elements -(if `indices.shape[-1] == params.rank`) or slices -(if `indices.shape[-1] < params.rank`) along dimension `indices.shape[-1]` -of `params`. The output tensor has shape - - indices.shape[:-1] + params.shape[indices.shape[-1]:] - -Some examples below. - -Simple indexing into a matrix: - -```python - indices = [[0, 0], [1, 1]] - params = [['a', 'b'], ['c', 'd']] - output = ['a', 'd'] -``` - -Slice indexing into a matrix: - -```python - indices = [[1], [0]] - params = [['a', 'b'], ['c', 'd']] - output = [['c', 'd'], ['a', 'b']] -``` - -Indexing into a 3-tensor: - -```python - indices = [[1]] - params = [[['a0', 'b0'], ['c0', 'd0']], - [['a1', 'b1'], ['c1', 'd1']]] - output = [[['a1', 'b1'], ['c1', 'd1']]] - - - indices = [[0, 1], [1, 0]] - params = [[['a0', 'b0'], ['c0', 'd0']], - [['a1', 'b1'], ['c1', 'd1']]] - output = [['c0', 'd0'], ['a1', 'b1']] - - - indices = [[0, 0, 1], [1, 0, 1]] - params = [[['a0', 'b0'], ['c0', 'd0']], - [['a1', 'b1'], ['c1', 'd1']]] - output = ['b0', 'b1'] -``` - -Batched indexing into a matrix: - -```python - indices = [[[0, 0]], [[0, 1]]] - params = [['a', 'b'], ['c', 'd']] - output = [['a'], ['b']] -``` - -Batched slice indexing into a matrix: - -```python - indices = [[[1]], [[0]]] - params = [['a', 'b'], ['c', 'd']] - output = [[['c', 'd']], [['a', 'b']]] -``` - -Batched indexing into a 3-tensor: - -```python - indices = [[[1]], [[0]]] - params = [[['a0', 'b0'], ['c0', 'd0']], - [['a1', 'b1'], ['c1', 'd1']]] - output = [[[['a1', 'b1'], ['c1', 'd1']]], - [[['a0', 'b0'], ['c0', 'd0']]]] - - indices = [[[0, 1], [1, 0]], [[0, 0], [1, 1]]] - params = [[['a0', 'b0'], ['c0', 'd0']], - [['a1', 'b1'], ['c1', 'd1']]] - output = [[['c0', 'd0'], ['a1', 'b1']], - [['a0', 'b0'], ['c1', 'd1']]] - - - indices = [[[0, 0, 1], [1, 0, 1]], [[0, 1, 1], [1, 1, 0]]] - params = [[['a0', 'b0'], ['c0', 'd0']], - [['a1', 'b1'], ['c1', 'd1']]] - output = [['b0', 'b1'], ['d0', 'c1']] -``` - -params: The tensor from which to gather values. -indices: Index tensor. -output: Values from `params` gathered from indices given by `indices`, with - shape `indices.shape[:-1] + params.shape[indices.shape[-1]:]`. -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("Identity") @@ -1724,10 +1004,7 @@ REGISTER_OP("Identity") c->set_output_handle_shapes_and_types(0, *handle_data); } return Status::OK(); - }) - .Doc(R"Doc( -Return a tensor with the same shape and contents as the input tensor or value. -)Doc"); + }); REGISTER_OP("Snapshot") .Input("input: T") @@ -1740,8 +1017,7 @@ REGISTER_OP("Snapshot") c->set_output_handle_shapes_and_types(0, *handle_data); } return Status::OK(); - }) - .Doc(R"Doc(Returns a copy of the input tensor.)Doc"); + }); #ifdef INTEL_MKL REGISTER_OP("_MklIdentity") @@ -1771,25 +1047,7 @@ REGISTER_OP("IdentityN") TF_RETURN_IF_ERROR(c->input("input", &input)); TF_RETURN_IF_ERROR(c->set_output("output", input)); return Status::OK(); - }) - .Doc(R"Doc( -Returns a list of tensors with the same shapes and contents as the input -tensors. - -This op can be used to override the gradient for complicated functions. For -example, suppose y = f(x) and we wish to apply a custom function g for backprop -such that dx = g(dy). In Python, - -```python -with tf.get_default_graph().gradient_override_map( - {'IdentityN': 'OverrideGradientWithG'}): - y, _ = identity_n([f(x), x]) - -@tf.RegisterGradient('OverrideGradientWithG') -def ApplyG(op, dy, _): - return [None, g(dy)] # Do not backprop to f(x). -``` -)Doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("RefIdentity") @@ -1797,10 +1055,7 @@ REGISTER_OP("RefIdentity") .Output("output: Ref(T)") .Attr("T: type") .SetShapeFn(shape_inference::UnchangedShape) - .SetAllowsUninitializedInput() - .Doc(R"Doc( -Return the same ref tensor as the input ref tensor. -)Doc"); + .SetAllowsUninitializedInput(); // -------------------------------------------------------------------------- REGISTER_OP("DebugGradientIdentity") @@ -1808,81 +1063,28 @@ REGISTER_OP("DebugGradientIdentity") .Output("output: T") .Attr("T: type") .SetShapeFn(shape_inference::UnchangedShape) - .SetAllowsUninitializedInput() - .Doc(R"Doc( -Identity op for gradient debugging. - -This op is hidden from public in Python. It is used by TensorFlow Debugger to -register gradient tensors for gradient debugging. -This op operates on non-reference-type tensors. -)Doc"); + .SetAllowsUninitializedInput(); REGISTER_OP("DebugGradientRefIdentity") .Input("input: Ref(T)") .Output("output: Ref(T)") .Attr("T: type") .SetShapeFn(shape_inference::UnchangedShape) - .SetAllowsUninitializedInput() - .Doc(R"Doc( -Identity op for gradient debugging. - -This op is hidden from public in Python. It is used by TensorFlow Debugger to -register gradient tensors for gradient debugging. -This op operates on reference-type tensors. -)Doc"); + .SetAllowsUninitializedInput(); // -------------------------------------------------------------------------- REGISTER_OP("StopGradient") .Input("input: T") .Output("output: T") .Attr("T: type") - .SetShapeFn(shape_inference::UnchangedShape) - .Doc(R"Doc( -Stops gradient computation. - -When executed in a graph, this op outputs its input tensor as-is. - -When building ops to compute gradients, this op prevents the contribution of -its inputs to be taken into account. Normally, the gradient generator adds ops -to a graph to compute the derivatives of a specified 'loss' by recursively -finding out inputs that contributed to its computation. If you insert this op -in the graph it inputs are masked from the gradient generator. They are not -taken into account for computing gradients. - -This is useful any time you want to compute a value with TensorFlow but need -to pretend that the value was a constant. Some examples include: - -* The *EM* algorithm where the *M-step* should not involve backpropagation - through the output of the *E-step*. -* Contrastive divergence training of Boltzmann machines where, when - differentiating the energy function, the training must not backpropagate - through the graph that generated the samples from the model. -* Adversarial training, where no backprop should happen through the adversarial - example generation process. -)Doc"); + .SetShapeFn(shape_inference::UnchangedShape); REGISTER_OP("PreventGradient") .Input("input: T") .Output("output: T") .Attr("T: type") .Attr("message: string = ''") - .SetShapeFn(shape_inference::UnchangedShape) - .Doc(R"Doc( -An identity op that triggers an error if a gradient is requested. - -When executed in a graph, this op outputs its input tensor as-is. - -When building ops to compute gradients, the TensorFlow gradient system -will return an error when trying to lookup the gradient of this op, -because no gradient must ever be registered for this function. This -op exists to prevent subtle bugs from silently returning unimplemented -gradients in some corner cases. - -input: any tensor. -output: the same input tensor. -message: Will be printed in the error when anyone tries to differentiate -this operation. -)Doc"); + .SetShapeFn(shape_inference::UnchangedShape); // -------------------------------------------------------------------------- REGISTER_OP("CheckNumerics") @@ -1890,15 +1092,7 @@ REGISTER_OP("CheckNumerics") .Output("output: T") .Attr("T: {half, bfloat16, float, double}") .Attr("message: string") - .SetShapeFn(shape_inference::UnchangedShape) - .Doc(R"doc( -Checks a tensor for NaN and Inf values. - -When run, reports an `InvalidArgument` error if `tensor` has any values -that are not a number (NaN) or infinity (Inf). Otherwise, passes `tensor` as-is. - -message: Prefix of the error message. -)doc"); + .SetShapeFn(shape_inference::UnchangedShape); // -------------------------------------------------------------------------- REGISTER_OP("Reshape") @@ -1907,69 +1101,9 @@ REGISTER_OP("Reshape") .Output("output: T") .Attr("T: type") .Attr("Tshape: {int32, int64} = DT_INT32") - .SetShapeFn([](InferenceContext* c) { return SetOutputShapeForReshape(c); }) - .Doc(R"Doc( -Reshapes a tensor. - -Given `tensor`, this operation returns a tensor that has the same values -as `tensor` with shape `shape`. - -If one component of `shape` is the special value -1, the size of that dimension -is computed so that the total size remains constant. In particular, a `shape` -of `[-1]` flattens into 1-D. At most one component of `shape` can be -1. - -If `shape` is 1-D or higher, then the operation returns a tensor with shape -`shape` filled with the values of `tensor`. In this case, the number of elements -implied by `shape` must be the same as the number of elements in `tensor`. - -For example: - -``` -# tensor 't' is [1, 2, 3, 4, 5, 6, 7, 8, 9] -# tensor 't' has shape [9] -reshape(t, [3, 3]) ==> [[1, 2, 3], - [4, 5, 6], - [7, 8, 9]] - -# tensor 't' is [[[1, 1], [2, 2]], -# [[3, 3], [4, 4]]] -# tensor 't' has shape [2, 2, 2] -reshape(t, [2, 4]) ==> [[1, 1, 2, 2], - [3, 3, 4, 4]] - -# tensor 't' is [[[1, 1, 1], -# [2, 2, 2]], -# [[3, 3, 3], -# [4, 4, 4]], -# [[5, 5, 5], -# [6, 6, 6]]] -# tensor 't' has shape [3, 2, 3] -# pass '[-1]' to flatten 't' -reshape(t, [-1]) ==> [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6] - -# -1 can also be used to infer the shape - -# -1 is inferred to be 9: -reshape(t, [2, -1]) ==> [[1, 1, 1, 2, 2, 2, 3, 3, 3], - [4, 4, 4, 5, 5, 5, 6, 6, 6]] -# -1 is inferred to be 2: -reshape(t, [-1, 9]) ==> [[1, 1, 1, 2, 2, 2, 3, 3, 3], - [4, 4, 4, 5, 5, 5, 6, 6, 6]] -# -1 is inferred to be 3: -reshape(t, [ 2, -1, 3]) ==> [[[1, 1, 1], - [2, 2, 2], - [3, 3, 3]], - [[4, 4, 4], - [5, 5, 5], - [6, 6, 6]]] - -# tensor 't' is [7] -# shape `[]` reshapes to a scalar -reshape(t, []) ==> 7 -``` - -shape: Defines the shape of the output tensor. -)Doc"); + .SetShapeFn([](InferenceContext* c) { + return SetOutputShapeForReshape(c); + }); #ifdef INTEL_MKL REGISTER_OP("_MklReshape") @@ -1996,29 +1130,7 @@ REGISTER_OP("InvertPermutation") TF_RETURN_IF_ERROR(c->WithRank(c->input(0), 1, &x)); c->set_output(0, x); return Status::OK(); - }) - .Doc(R"doc( -Computes the inverse permutation of a tensor. - -This operation computes the inverse of an index permutation. It takes a 1-D -integer tensor `x`, which represents the indices of a zero-based array, and -swaps each value with its index position. In other words, for an output tensor -`y` and an input tensor `x`, this operation computes the following: - -`y[x[i]] = i for i in [0, 1, ..., len(x) - 1]` - -The values must include 0. There can be no duplicate values or negative values. - -For example: - -``` -# tensor `x` is [3, 4, 0, 2, 1] -invert_permutation(x) ==> [2, 4, 3, 0, 1] -``` - -x: 1-D. -y: 1-D. -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("Transpose") @@ -2027,13 +1139,7 @@ REGISTER_OP("Transpose") .Output("y: T") .Attr("T: type") .Attr("Tperm: {int32, int64} = DT_INT32") - .SetShapeFn(TransposeShapeFn) - .Doc(R"doc( -Shuffle dimensions of x according to a permutation. - -The output `y` has the same rank as `x`. The shapes of `x` and `y` satisfy: - `y.shape[i] == x.shape[perm[i]] for i in [0, 1, ..., rank(x) - 1]` -)doc"); + .SetShapeFn(TransposeShapeFn); // -------------------------------------------------------------------------- REGISTER_OP("ConjugateTranspose") @@ -2042,14 +1148,7 @@ REGISTER_OP("ConjugateTranspose") .Output("y: T") .Attr("T: type") .Attr("Tperm: {int32, int64} = DT_INT32") - .SetShapeFn(TransposeShapeFn) - .Doc(R"doc( -Shuffle dimensions of x according to a permutation and conjugate the result. - -The output `y` has the same rank as `x`. The shapes of `x` and `y` satisfy: - `y.shape[i] == x.shape[perm[i]] for i in [0, 1, ..., rank(x) - 1]` - `y[i,j,k,...,s,t,u] == conj(x[perm[i], perm[j], perm[k],...,perm[s], perm[t], perm[u]])` -)doc"); + .SetShapeFn(TransposeShapeFn); // -------------------------------------------------------------------------- REGISTER_OP("Unique") @@ -2062,30 +1161,7 @@ REGISTER_OP("Unique") c->set_output(0, c->Vector(InferenceContext::kUnknownDim)); c->set_output(1, c->input(0)); return Status::OK(); - }) - .Doc(R"doc( -Finds unique elements in a 1-D tensor. - -This operation returns a tensor `y` containing all of the unique elements of `x` -sorted in the same order that they occur in `x`. This operation also returns a -tensor `idx` the same size as `x` that contains the index of each value of `x` -in the unique output `y`. In other words: - -`y[idx[i]] = x[i] for i in [0, 1,...,rank(x) - 1]` - -For example: - -``` -# tensor 'x' is [1, 1, 2, 4, 4, 4, 7, 8, 8] -y, idx = unique(x) -y ==> [1, 2, 4, 7, 8] -idx ==> [0, 0, 1, 2, 2, 2, 3, 4, 4] -``` - -x: 1-D. -y: 1-D. -idx: 1-D. -)doc"); + }); REGISTER_OP("UniqueV2") .Input("x: T") @@ -2098,34 +1174,7 @@ REGISTER_OP("UniqueV2") c->set_output(0, c->Vector(InferenceContext::kUnknownDim)); c->set_output(1, c->input(0)); return Status::OK(); - }) - .Doc(R"doc( -Finds unique elements in a 1-D tensor. - -This operation returns a tensor `y` containing all of the unique elements of `x` -sorted in the same order that they occur in `x`. This operation also returns a -tensor `idx` the same size as `x` that contains the index of each value of `x` -in the unique output `y`. In other words: - -`y[idx[i]] = x[i] for i in [0, 1,...,rank(x) - 1]` - -For example: - -``` -# tensor 'x' is [1, 1, 2, 4, 4, 4, 7, 8, 8] -y, idx = unique(x) -y ==> [1, 2, 4, 7, 8] -idx ==> [0, 0, 1, 2, 2, 2, 3, 4, 4] -``` - - -x: A `Tensor`. -axis: A `Tensor` of type `int64` (default: 0). The axis of the Tensor to - find the unique elements. -y: A `Tensor`. Unique elements along the `axis` of `Tensor` x. -idx: A 1-D Tensor. Has the same type as x that contains the index of each - value of x in the output y. -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("UniqueWithCounts") @@ -2141,33 +1190,7 @@ REGISTER_OP("UniqueWithCounts") c->set_output(1, c->input(0)); c->set_output(2, uniq); return Status::OK(); - }) - .Doc(R"doc( -Finds unique elements in a 1-D tensor. - -This operation returns a tensor `y` containing all of the unique elements of `x` -sorted in the same order that they occur in `x`. This operation also returns a -tensor `idx` the same size as `x` that contains the index of each value of `x` -in the unique output `y`. Finally, it returns a third tensor `count` that -contains the count of each element of `y` in `x`. In other words: - -`y[idx[i]] = x[i] for i in [0, 1,...,rank(x) - 1]` - -For example: - -``` -# tensor 'x' is [1, 1, 2, 4, 4, 4, 7, 8, 8] -y, idx, count = unique_with_counts(x) -y ==> [1, 2, 4, 7, 8] -idx ==> [0, 0, 1, 2, 2, 2, 3, 4, 4] -count ==> [2, 1, 3, 1, 2] -``` - -x: 1-D. -y: 1-D. -idx: 1-D. -count: 1-D. -)doc"); + }); namespace { @@ -2192,20 +1215,7 @@ REGISTER_OP("Shape") .Output("output: out_type") .Attr("T: type") .Attr("out_type: {int32, int64} = DT_INT32") - .SetShapeFn(ShapeShapeFn) - .Doc(R"doc( -Returns the shape of a tensor. - -This operation returns a 1-D integer tensor representing the shape of `input`. - -For example: - -``` -# 't' is [[[1, 1, 1], [2, 2, 2]], [[3, 3, 3], [4, 4, 4]]] -shape(t) ==> [2, 2, 3] -``` - -)doc"); + .SetShapeFn(ShapeShapeFn); REGISTER_OP("ShapeN") .Input("input: N * T") @@ -2213,12 +1223,7 @@ REGISTER_OP("ShapeN") .Attr("N: int") .Attr("T: type") .Attr("out_type: {int32, int64} = DT_INT32") - .SetShapeFn(ShapeShapeFn) - .Doc(R"doc( -Returns shape of tensors. - -This operation returns N 1-D integer tensors representing shape of `input[i]s`. -)doc"); + .SetShapeFn(ShapeShapeFn); // -------------------------------------------------------------------------- REGISTER_OP("ReverseSequence") @@ -2264,96 +1269,14 @@ REGISTER_OP("ReverseSequence") c->ReplaceDim(input, batch_dim, batch_dim_dim, &output_shape)); c->set_output(0, output_shape); return Status::OK(); - }) - .Doc(R"doc( -Reverses variable length slices. - -This op first slices `input` along the dimension `batch_dim`, and for each -slice `i`, reverses the first `seq_lengths[i]` elements along -the dimension `seq_dim`. - -The elements of `seq_lengths` must obey `seq_lengths[i] <= input.dims[seq_dim]`, -and `seq_lengths` must be a vector of length `input.dims[batch_dim]`. - -The output slice `i` along dimension `batch_dim` is then given by input -slice `i`, with the first `seq_lengths[i]` slices along dimension -`seq_dim` reversed. - -For example: - -``` -# Given this: -batch_dim = 0 -seq_dim = 1 -input.dims = (4, 8, ...) -seq_lengths = [7, 2, 3, 5] - -# then slices of input are reversed on seq_dim, but only up to seq_lengths: -output[0, 0:7, :, ...] = input[0, 7:0:-1, :, ...] -output[1, 0:2, :, ...] = input[1, 2:0:-1, :, ...] -output[2, 0:3, :, ...] = input[2, 3:0:-1, :, ...] -output[3, 0:5, :, ...] = input[3, 5:0:-1, :, ...] - -# while entries past seq_lens are copied through: -output[0, 7:, :, ...] = input[0, 7:, :, ...] -output[1, 2:, :, ...] = input[1, 2:, :, ...] -output[2, 3:, :, ...] = input[2, 3:, :, ...] -output[3, 2:, :, ...] = input[3, 2:, :, ...] -``` - -In contrast, if: - -``` -# Given this: -batch_dim = 2 -seq_dim = 0 -input.dims = (8, ?, 4, ...) -seq_lengths = [7, 2, 3, 5] - -# then slices of input are reversed on seq_dim, but only up to seq_lengths: -output[0:7, :, 0, :, ...] = input[7:0:-1, :, 0, :, ...] -output[0:2, :, 1, :, ...] = input[2:0:-1, :, 1, :, ...] -output[0:3, :, 2, :, ...] = input[3:0:-1, :, 2, :, ...] -output[0:5, :, 3, :, ...] = input[5:0:-1, :, 3, :, ...] - -# while entries past seq_lens are copied through: -output[7:, :, 0, :, ...] = input[7:, :, 0, :, ...] -output[2:, :, 1, :, ...] = input[2:, :, 1, :, ...] -output[3:, :, 2, :, ...] = input[3:, :, 2, :, ...] -output[2:, :, 3, :, ...] = input[2:, :, 3, :, ...] -``` - -input: The input to reverse. -seq_lengths: 1-D with length `input.dims(batch_dim)` and - `max(seq_lengths) <= input.dims(seq_dim)` -seq_dim: The dimension which is partially reversed. -batch_dim: The dimension along which reversal is performed. -output: The partially reversed input. It has the same shape as `input`. -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("Rank") .Input("input: T") .Output("output: int32") .Attr("T: type") - .SetShapeFn(shape_inference::ScalarShape) - .Doc(R"doc( -Returns the rank of a tensor. - -This operation returns an integer representing the rank of `input`. - -For example: - -``` -# 't' is [[[1, 1, 1], [2, 2, 2]], [[3, 3, 3], [4, 4, 4]]] -# shape of tensor 't' is [2, 2, 3] -rank(t) ==> 3 -``` - -**Note**: The rank of a tensor is not the same as the rank of a matrix. The rank -of a tensor is the number of indices required to uniquely select each element -of the tensor. Rank is also known as "order", "degree", or "ndims." -)doc"); + .SetShapeFn(shape_inference::ScalarShape); // -------------------------------------------------------------------------- REGISTER_OP("Size") @@ -2361,21 +1284,7 @@ REGISTER_OP("Size") .Output("output: out_type") .Attr("T: type") .Attr("out_type: {int32, int64} = DT_INT32") - .SetShapeFn(shape_inference::ScalarShape) - .Doc(R"doc( -Returns the size of a tensor. - -This operation returns an integer representing the number of elements in -`input`. - -For example: - -``` -# 't' is [[[1, 1,, 1], [2, 2, 2]], [[3, 3, 3], [4, 4, 4]]]] -size(t) ==> 12 -``` - -)doc"); + .SetShapeFn(shape_inference::ScalarShape); namespace { @@ -2492,24 +1401,7 @@ REGISTER_OP("Slice") } return Status::OK(); - }) - .Doc(R"doc( -Return a slice from 'input'. - -The output tensor is a tensor with dimensions described by 'size' -whose values are extracted from 'input' starting at the offsets in -'begin'. - -*Requirements*: - 0 <= begin[i] <= begin[i] + size[i] <= Di for i in [0, n) - -begin: begin[i] specifies the offset into the 'i'th dimension of - 'input' to slice from. -size: size[i] specifies the number of elements of the 'i'th dimension - of 'input' to slice. If size[i] is -1, all remaining elements in dimension - i are included in the slice (i.e. this is equivalent to setting - size[i] = input.dim_size(i) - begin[i]). -)doc"); + }); REGISTER_OP("StridedSlice") .Input("input: T") @@ -2574,133 +1466,7 @@ REGISTER_OP("StridedSlice") c->set_output(0, out); return Status::OK(); - }) - .Doc(R"doc( -Return a strided slice from `input`. - -Note, most python users will want to use the Python `Tensor.__getitem__` -or `Variable.__getitem__` rather than this op directly. - -The goal of this op is to produce a new tensor with a subset of -the elements from the `n` dimensional `input` tensor. The subset is chosen using -a sequence of `m` sparse range specifications encoded into the arguments -of this function. Note, in some cases -`m` could be equal to `n`, but this need not be the case. Each -range specification entry can be one of the following: - -- An ellipsis (...). Ellipses are used to imply zero or more - dimensions of full-dimension selection and are produced using - `ellipsis_mask`. For example, `foo[...]` is the identity slice. - -- A new axis. This is used to insert a new shape=1 dimension and is - produced using `new_axis_mask`. For example, `foo[:, ...]` where - `foo` is shape `(3, 4)` produces a `(1, 3, 4)` tensor. - - -- A range `begin:end:stride`. This is used to specify how much to choose from - a given dimension. `stride` can be any integer but 0. `begin` is an integer - which represents the index of the first value to select while `end` represents - the index of the last value to select. The number of values selected in each - dimension is `end - begin` if `stride > 0` and `begin - end` if `stride < 0`. - `begin` and `end` can be negative where `-1` is the last element, `-2` is - the second to last. `begin_mask` controls whether to replace the explicitly - given `begin` with an implicit effective value of `0` if `stride > 0` and - `-1` if `stride < 0`. `end_mask` is analogous but produces the number - required to create the largest open interval. For example, given a shape - `(3,)` tensor `foo[:]`, the effective `begin` and `end` are `0` and `3`. Do - not assume this is equivalent to `foo[0:-1]` which has an effective `begin` - and `end` of `0` and `2`. Another example is `foo[-2::-1]` which reverses the - first dimension of a tensor while dropping the last two (in the original - order elements). For example `foo = [1,2,3,4]; foo[-2::-1]` is `[4,3]`. - -- A single index. This is used to keep only elements that have a given - index. For example (`foo[2, :]` on a shape `(5,6)` tensor produces a - shape `(6,)` tensor. This is encoded in `begin` and `end` and - `shrink_axis_mask`. - -Each conceptual range specification is encoded in the op's argument. This -encoding is best understand by considering a non-trivial example. In -particular, -`foo[1, 2:4, None, ..., :-3:-1, :]` will be encoded as - -``` -begin = [1, 2, x, x, 0, x] # x denotes don't care (usually 0) -end = [2, 4, x, x, -3, x] -strides = [1, 1, x, x, -1, 1] -begin_mask = 1<<4 | 1 << 5 = 48 -end_mask = 1<<5 = 32 -ellipsis_mask = 1<<3 = 8 -new_axis_mask = 1<<2 4 -shrink_axis_mask = 1<<0 -``` - -In this case if `foo.shape` is (5, 5, 5, 5, 5, 5) the final shape of -the slice becomes (2, 1, 5, 5, 2, 5). -Let us walk step by step through each argument specification. - -1. The first argument in the example slice is turned into `begin = 1` and -`end = begin + 1 = 2`. To disambiguate from the original spec `2:4` we -also set the appropriate bit in `shrink_axis_mask`. - -2. `2:4` is contributes 2, 4, 1 to begin, end, and stride. All masks have -zero bits contributed. - -3. None is a synonym for `tf.newaxis`. This means insert a dimension of size 1 -dimension in the final shape. Dummy values are contributed to begin, -end and stride, while the new_axis_mask bit is set. - -4. `...` grab the full ranges from as many dimensions as needed to -fully specify a slice for every dimension of the input shape. - -5. `:-3:-1` shows the use of negative indices. A negative index `i` associated -with a dimension that has shape `s` is converted to a positive index -`s + i`. So `-1` becomes `s-1` (i.e. the last element). This conversion -is done internally so begin, end and strides receive x, -3, and -1. -The appropriate begin_mask bit is set to indicate the start range is the -full range (ignoring the x). - -6. `:` indicates that the entire contents of the corresponding dimension -is selected. This is equivalent to `::` or `0::1`. begin, end, and strides -receive 0, 0, and 1, respectively. The appropriate bits in `begin_mask` and -`end_mask` are also set. - -*Requirements*: - `0 != strides[i] for i in [0, m)` - `ellipsis_mask must be a power of two (only one ellipsis)` - -begin: `begin[k]` specifies the offset into the `k`th range specification. - The exact dimension this corresponds to will be determined by context. - Out-of-bounds values will be silently clamped. If the `k`th bit of - `begin_mask` then `begin[k]` is ignored and the full range of the - appropriate dimension is used instead. Negative values causes indexing - to start from the highest element e.g. If `foo==[1,2,3]` then `foo[-1]==3`. -end: `end[i]` is like `begin` with the exception that `end_mask` is - used to determine full ranges. -strides: `strides[i]` specifies the increment in the `i`th specification - after extracting a given element. Negative indices will reverse - the original order. Out or range values are - clamped to `[0,dim[i]) if slice[i]>0` or `[-1,dim[i]-1] if slice[i] < 0` -begin_mask: a bitmask where a bit i being 1 means to ignore the begin - value and instead use the largest interval possible. At runtime - begin[i] will be replaced with `[0, n-1) if `stride[i] > 0` or - `[-1, n-1]` if `stride[i] < 0` -end_mask: analogous to `begin_mask` -ellipsis_mask: a bitmask where bit `i` being 1 means the `i`th - position is actually an ellipsis. One bit at most can be 1. - If `ellipsis_mask == 0`, then an implicit ellipsis mask of `1 << (m+1)` - is provided. This means that `foo[3:5] == foo[3:5, ...]`. An ellipsis - implicitly creates as many range specifications as necessary to fully - specify the sliced range for every dimension. For example for a 4-dimensional - tensor `foo` the slice `foo[2, ..., 5:8]` implies `foo[2, :, :, 5:8]`. -new_axis_mask: a bitmask where bit `i` being 1 means the `i`th - specification creates a new shape 1 dimension. For example - `foo[:4, tf.newaxis, :2]` would produce a shape `(4, 1, 2)` tensor. -shrink_axis_mask: a bitmask where bit `i` implies that the `i`th - specification should shrink the dimensionality. begin and end - must imply a slice of size 1 in the dimension. For example in - python one might do `foo[:, 3, :]` which would result in - `shrink_axis_mask` being 2. -)doc"); + }); REGISTER_OP("StridedSliceGrad") .Input("shape: Index") @@ -2721,19 +1487,7 @@ REGISTER_OP("StridedSliceGrad") TF_RETURN_IF_ERROR(c->MakeShapeFromShapeTensor(0, &out)); c->set_output(0, out); return Status::OK(); - }) - .Doc(R"doc( -Returns the gradient of `StridedSlice`. - -Since `StridedSlice` cuts out pieces of its `input` which is size -`shape`, its gradient will have the same shape (which is passed here -as `shape`). The gradient will be zero in any element that the slice -does not select. - -Arguments are the same as StridedSliceGrad with the exception that -`dy` is the input gradient to be propagated and `shape` is the -shape of `StridedSlice`'s `input`. -)doc"); + }); REGISTER_OP("StridedSliceAssign") .Input("ref: Ref(T)") @@ -2749,18 +1503,7 @@ REGISTER_OP("StridedSliceAssign") .Attr("ellipsis_mask: int = 0") .Attr("new_axis_mask: int = 0") .Attr("shrink_axis_mask: int = 0") - .SetShapeFn(shape_inference::UnchangedShape) - .Doc(R"doc( -Assign `value` to the sliced l-value reference of `ref`. - -The values of `value` are assigned to the positions in the variable -`ref` that are selected by the slice parameters. The slice parameters -`begin, `end`, `strides`, etc. work exactly as in `StridedSlice`. - -NOTE this op currently does not support broadcasting and so `value`'s -shape must be exactly the shape produced by the slice of `ref`. - -)doc"); + .SetShapeFn(shape_inference::UnchangedShape); // TODO(aselle): Fix this documentation once StridedSliceAssign Supports // broadcasting. // -------------------------------------------------------------------------- @@ -2778,18 +1521,7 @@ REGISTER_OP("ResourceStridedSliceAssign") .Attr("ellipsis_mask: int = 0") .Attr("new_axis_mask: int = 0") .Attr("shrink_axis_mask: int = 0") - .SetShapeFn(shape_inference::NoOutputs) - .Doc(R"doc( -Assign `value` to the sliced l-value reference of `ref`. - -The values of `value` are assigned to the positions in the variable -`ref` that are selected by the slice parameters. The slice parameters -`begin, `end`, `strides`, etc. work exactly as in `StridedSlice`. - -NOTE this op currently does not support broadcasting and so `value`'s -shape must be exactly the shape produced by the slice of `ref`. - -)doc"); + .SetShapeFn(shape_inference::NoOutputs); REGISTER_OP("Tile") .Input("input: T") @@ -2821,19 +1553,7 @@ REGISTER_OP("Tile") } c->set_output(0, c->MakeShape(dims)); return Status::OK(); - }) - .Doc(R"doc( -Constructs a tensor by tiling a given tensor. - -This operation creates a new tensor by replicating `input` `multiples` times. -The output tensor's i'th dimension has `input.dims(i) * multiples[i]` elements, -and the values of `input` are replicated `multiples[i]` times along the 'i'th -dimension. For example, tiling `[a b c d]` by `[2]` produces -`[a b c d a b c d]`. - -input: 1-D or higher. -multiples: 1-D. Length must be the same as the number of dimensions in `input` -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("TileGrad") @@ -2842,14 +1562,7 @@ REGISTER_OP("TileGrad") .Output("output: T") .Attr("T: type") .Deprecated(3, "TileGrad has been replaced with reduce_sum") - .SetShapeFn(tensorflow::shape_inference::UnknownShape) - .Doc(R"doc( -Returns the gradient of `Tile`. - -Since `Tile` takes an input and repeats the input `multiples` times -along each dimension, `TileGrad` takes in `multiples` and aggregates -each repeated tile of `input` into `output`. -)doc"); + .SetShapeFn(tensorflow::shape_inference::UnknownShape); // -------------------------------------------------------------------------- REGISTER_OP("Where") @@ -2859,71 +1572,7 @@ REGISTER_OP("Where") .SetShapeFn([](InferenceContext* c) { c->set_output(0, c->Matrix(c->UnknownDim(), c->Rank(c->input(0)))); return Status::OK(); - }) - .Doc(R"doc( -Returns locations of nonzero / true values in a tensor. - -This operation returns the coordinates of true elements in `input`. The -coordinates are returned in a 2-D tensor where the first dimension (rows) -represents the number of true elements, and the second dimension (columns) -represents the coordinates of the true elements. Keep in mind, the shape of -the output tensor can vary depending on how many true values there are in -`input`. Indices are output in row-major order. - -For example: - -``` -# 'input' tensor is [[True, False] -# [True, False]] -# 'input' has two true values, so output has two coordinates. -# 'input' has rank of 2, so coordinates have two indices. -where(input) ==> [[0, 0], - [1, 0]] - -# `input` tensor is [[[True, False] -# [True, False]] -# [[False, True] -# [False, True]] -# [[False, False] -# [False, True]]] -# 'input' has 5 true values, so output has 5 coordinates. -# 'input' has rank of 3, so coordinates have three indices. -where(input) ==> [[0, 0, 0], - [0, 1, 0], - [1, 0, 1], - [1, 1, 1], - [2, 1, 1]] - -# `input` tensor is [[[1.5, 0.0] -# [-0.5, 0.0]] -# [[0.0, 0.25] -# [0.0, 0.75]] -# [[0.0, 0.0] -# [0.0, 0.01]]] -# 'input' has 5 nonzero values, so output has 5 coordinates. -# 'input' has rank of 3, so coordinates have three indices. -where(input) ==> [[0, 0, 0], - [0, 1, 0], - [1, 0, 1], - [1, 1, 1], - [2, 1, 1]] - -# `input` tensor is [[[1.5 + 0.0j, 0.0 + 0.0j] -# [0.0 + 0.5j, 0.0 + 0.0j]] -# [[0.0 + 0.0j, 0.25 + 1.5j] -# [0.0 + 0.0j, 0.75 + 0.0j]] -# [[0.0 + 0.0j, 0.0 + 0.0j] -# [0.0 + 0.0j, 0.01 + 0.0j]]] -# 'input' has 5 nonzero magnitude values, so output has 5 coordinates. -# 'input' has rank of 3, so coordinates have three indices. -where(input) ==> [[0, 0, 0], - [0, 1, 0], - [1, 0, 1], - [1, 1, 1], - [2, 1, 1]] -``` - -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("BroadcastArgs") @@ -2950,13 +1599,7 @@ REGISTER_OP("BroadcastArgs") // Broadcasted shape is going to be as large as the largest dimension. c->set_output(0, c->Vector(std::max(x_dim, y_dim))); return Status::OK(); - }) - .Doc(R"doc( -Return the shape of s0 op s1 with broadcast. - -Given `s0` and `s1`, tensors that represent shapes, compute `r0`, the -broadcasted shape. `s0`, `s1` and `r0` are all integer vectors. -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("BroadcastGradientArgs") @@ -2973,12 +1616,7 @@ REGISTER_OP("BroadcastGradientArgs") c->set_output(0, c->Vector(InferenceContext::kUnknownDim)); c->set_output(1, c->Vector(InferenceContext::kUnknownDim)); return Status::OK(); - }) - .Doc(R"doc( -Return the reduction indices for computing gradients of s0 op s1 with broadcast. - -This is typically used by gradient computations for a broadcasting operation. -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("Pad") @@ -2987,34 +1625,7 @@ REGISTER_OP("Pad") .Output("output: T") .Attr("T: type") .Attr("Tpaddings: {int32, int64} = DT_INT32") - .SetShapeFn(PadShapeFn) - .Doc(R"doc( -Pads a tensor with zeros. - -This operation pads a `input` with zeros according to the `paddings` you -specify. `paddings` is an integer tensor with shape `[Dn, 2]`, where n is the -rank of `input`. For each dimension D of `input`, `paddings[D, 0]` indicates -how many zeros to add before the contents of `input` in that dimension, and -`paddings[D, 1]` indicates how many zeros to add after the contents of `input` -in that dimension. - -The padded size of each dimension D of the output is: - -`paddings(D, 0) + input.dim_size(D) + paddings(D, 1)` - -For example: - -``` -# 't' is [[1, 1], [2, 2]] -# 'paddings' is [[1, 1], [2, 2]] -# rank of 't' is 2 -pad(t, paddings) ==> [[0, 0, 0, 0, 0, 0] - [0, 0, 1, 1, 0, 0] - [0, 0, 2, 2, 0, 0] - [0, 0, 0, 0, 0, 0]] -``` - -)doc"); + .SetShapeFn(PadShapeFn); // -------------------------------------------------------------------------- REGISTER_OP("PadV2") @@ -3024,36 +1635,7 @@ REGISTER_OP("PadV2") .Output("output: T") .Attr("T: type") .Attr("Tpaddings: {int32, int64} = DT_INT32") - .SetShapeFn(PadShapeFn) - .Doc(R"doc( -Pads a tensor. - -This operation pads `input` according to the `paddings` and `constant_values` -you specify. `paddings` is an integer tensor with shape `[Dn, 2]`, where n is -the rank of `input`. For each dimension D of `input`, `paddings[D, 0]` indicates -how many padding values to add before the contents of `input` in that dimension, -and `paddings[D, 1]` indicates how many padding values to add after the contents -of `input` in that dimension. `constant_values` is a scalar tensor of the same -type as `input` that indicates the value to use for padding `input`. - -The padded size of each dimension D of the output is: - -`paddings(D, 0) + input.dim_size(D) + paddings(D, 1)` - -For example: - -``` -# 't' is [[1, 1], [2, 2]] -# 'paddings' is [[1, 1], [2, 2]] -# 'constant_values' is 0 -# rank of 't' is 2 -pad(t, paddings) ==> [[0, 0, 0, 0, 0, 0] - [0, 0, 1, 1, 0, 0] - [0, 0, 2, 2, 0, 0] - [0, 0, 0, 0, 0, 0]] -``` - -)doc"); + .SetShapeFn(PadShapeFn); // -------------------------------------------------------------------------- REGISTER_OP("MirrorPad") @@ -3063,46 +1645,7 @@ REGISTER_OP("MirrorPad") .Attr("T: type") .Attr("Tpaddings: {int32, int64} = DT_INT32") .Attr(GetMirrorPadModeAttrString()) - .SetShapeFn(PadShapeFn) - .Doc(R"doc( -Pads a tensor with mirrored values. - -This operation pads a `input` with mirrored values according to the `paddings` -you specify. `paddings` is an integer tensor with shape `[n, 2]`, where n is -the rank of `input`. For each dimension D of `input`, `paddings[D, 0]` indicates -how many values to add before the contents of `input` in that dimension, and -`paddings[D, 1]` indicates how many values to add after the contents of `input` -in that dimension. Both `paddings[D, 0]` and `paddings[D, 1]` must be no greater -than `input.dim_size(D)` (or `input.dim_size(D) - 1`) if `copy_border` is true -(if false, respectively). - -The padded size of each dimension D of the output is: - -`paddings(D, 0) + input.dim_size(D) + paddings(D, 1)` - -For example: - -``` -# 't' is [[1, 2, 3], [4, 5, 6]]. -# 'paddings' is [[1, 1]], [2, 2]]. -# 'mode' is SYMMETRIC. -# rank of 't' is 2. -pad(t, paddings) ==> [[2, 1, 1, 2, 3, 3, 2] - [2, 1, 1, 2, 3, 3, 2] - [5, 4, 4, 5, 6, 6, 5] - [5, 4, 4, 5, 6, 6, 5]] -``` - -input: The input tensor to be padded. -paddings: A two-column matrix specifying the padding sizes. The number of - rows must be the same as the rank of `input`. -mode: Either `REFLECT` or `SYMMETRIC`. In reflect mode the padded regions - do not include the borders, while in symmetric mode the padded regions - do include the borders. For example, if `input` is `[1, 2, 3]` and `paddings` - is `[0, 2]`, then the output is `[1, 2, 3, 2, 1]` in reflect mode, and - it is `[1, 2, 3, 3, 2]` in symmetric mode. -output: The padded tensor. -)doc"); + .SetShapeFn(PadShapeFn); // -------------------------------------------------------------------------- namespace { @@ -3164,35 +1707,7 @@ REGISTER_OP("MirrorPadGrad") } else { return MirrorPadKnown<int64>(c, input, paddings_t, input_rank); } - }) - .Doc(R"doc( -Gradient op for `MirrorPad` op. This op folds a mirror-padded tensor. - -This operation folds the padded areas of `input` by `MirrorPad` according to the -`paddings` you specify. `paddings` must be the same as `paddings` argument -given to the corresponding `MirrorPad` op. - -The folded size of each dimension D of the output is: - -`input.dim_size(D) - paddings(D, 0) - paddings(D, 1)` - -For example: - -``` -# 't' is [[1, 2, 3], [4, 5, 6], [7, 8, 9]]. -# 'paddings' is [[0, 1]], [0, 1]]. -# 'mode' is SYMMETRIC. -# rank of 't' is 2. -pad(t, paddings) ==> [[ 1, 5] - [11, 28]] -``` - -input: The input tensor to be folded. -paddings: A two-column matrix specifying the padding sizes. The number of - rows must be the same as the rank of `input`. -mode: The mode used in the `MirrorPad` op. -output: The folded tensor. -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("Placeholder") @@ -3214,19 +1729,7 @@ REGISTER_OP("Placeholder") TF_RETURN_IF_ERROR(c->MakeShapeFromPartialTensorShape(shape, &out)); c->set_output(0, out); return Status::OK(); - }) - .Doc(R"doc( -A placeholder op for a value that will be fed into the computation. - -N.B. This operation will fail with an error if it is executed. It is -intended as a way to represent a value that will always be fed, and to -provide attrs that enable the fed value to be checked at runtime. - -output: A placeholder tensor that must be replaced using the feed mechanism. -dtype: The type of elements in the tensor. -shape: (Optional) The shape of the tensor. If the shape has 0 dimensions, the - shape is unconstrained. -)doc"); + }); // Placeholder was modified in a backwards compatible way to do what // PlaceholderV2 did, so we have deprecated V2 (no one was really @@ -3236,19 +1739,7 @@ REGISTER_OP("PlaceholderV2") .Attr("dtype: type") .Attr("shape: shape") .SetShapeFn(shape_inference::ExplicitShape) - .Deprecated(23, "Placeholder now behaves the same as PlaceholderV2.") - .Doc(R"doc( -A placeholder op for a value that will be fed into the computation. - -N.B. This operation will fail with an error if it is executed. It is -intended as a way to represent a value that will always be fed, and to -provide attrs that enable the fed value to be checked at runtime. - -output: A placeholder tensor that must be replaced using the feed mechanism. -dtype: The type of elements in the tensor. -shape: The shape of the tensor. The shape can be any partially-specified - shape. To be unconstrained, pass in a shape with unknown rank. -)doc"); + .Deprecated(23, "Placeholder now behaves the same as PlaceholderV2."); // -------------------------------------------------------------------------- REGISTER_OP("PlaceholderWithDefault") @@ -3269,15 +1760,7 @@ REGISTER_OP("PlaceholderWithDefault") TF_RETURN_IF_ERROR(c->Merge(input, out, &unused)); c->set_output(0, out); return Status::OK(); - }) - .Doc(R"doc( -A placeholder op that passes through `input` when its output is not fed. - -input: The default value to produce when `output` is not fed. -output: A placeholder tensor that defaults to `input` if it is not fed. -dtype: The type of elements in the tensor. -shape: The (possibly partial) shape of the tensor. -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("ExpandDims") @@ -3327,47 +1810,7 @@ REGISTER_OP("ExpandDims") TF_RETURN_IF_ERROR(c->Concatenate(output, end, &output)); c->set_output(0, output); return Status::OK(); - }) - .Doc(R"doc( -Inserts a dimension of 1 into a tensor's shape. - -Given a tensor `input`, this operation inserts a dimension of 1 at the -dimension index `dim` of `input`'s shape. The dimension index `dim` starts at -zero; if you specify a negative number for `dim` it is counted backward from -the end. - -This operation is useful if you want to add a batch dimension to a single -element. For example, if you have a single image of shape `[height, width, -channels]`, you can make it a batch of 1 image with `expand_dims(image, 0)`, -which will make the shape `[1, height, width, channels]`. - -Other examples: - -``` -# 't' is a tensor of shape [2] -shape(expand_dims(t, 0)) ==> [1, 2] -shape(expand_dims(t, 1)) ==> [2, 1] -shape(expand_dims(t, -1)) ==> [2, 1] - -# 't2' is a tensor of shape [2, 3, 5] -shape(expand_dims(t2, 0)) ==> [1, 2, 3, 5] -shape(expand_dims(t2, 2)) ==> [2, 3, 1, 5] -shape(expand_dims(t2, 3)) ==> [2, 3, 5, 1] -``` - -This operation requires that: - -`-1-input.dims() <= dim <= input.dims()` - -This operation is related to `squeeze()`, which removes dimensions of -size 1. - -dim: 0-D (scalar). Specifies the dimension index at which to - expand the shape of `input`. Must be in the range - `[-rank(input) - 1, rank(input)]`. -output: Contains the same data as `input`, but its shape has an additional - dimension of size 1 added. -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("Squeeze") @@ -3435,36 +1878,7 @@ REGISTER_OP("Squeeze") c->set_output(0, c->MakeShape(result_shape)); return Status::OK(); - }) - .Doc(R"doc( -Removes dimensions of size 1 from the shape of a tensor. - -Given a tensor `input`, this operation returns a tensor of the same type with -all dimensions of size 1 removed. If you don't want to remove all size 1 -dimensions, you can remove specific size 1 dimensions by specifying -`squeeze_dims`. - -For example: - -``` -# 't' is a tensor of shape [1, 2, 1, 3, 1, 1] -shape(squeeze(t)) ==> [2, 3] -``` - -Or, to remove specific size 1 dimensions: - -``` -# 't' is a tensor of shape [1, 2, 1, 3, 1, 1] -shape(squeeze(t, [2, 4])) ==> [1, 2, 3, 1] -``` - -input: The `input` to squeeze. -squeeze_dims: If specified, only squeezes the dimensions listed. The dimension - index starts at 0. It is an error to squeeze a dimension that is not 1. Must - be in the range `[-rank(input), rank(input))`. -output: Contains the same data as `input`, but has one or more dimensions of - size 1 removed. -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("ListDiff") @@ -3483,37 +1897,7 @@ REGISTER_OP("ListDiff") c->set_output(0, out); c->set_output(1, out); return Status::OK(); - }) - .Doc(R"doc( -Computes the difference between two lists of numbers or strings. - -Given a list `x` and a list `y`, this operation returns a list `out` that -represents all values that are in `x` but not in `y`. The returned list `out` -is sorted in the same order that the numbers appear in `x` (duplicates are -preserved). This operation also returns a list `idx` that represents the -position of each `out` element in `x`. In other words: - -`out[i] = x[idx[i]] for i in [0, 1, ..., len(out) - 1]` - -For example, given this input: - -``` -x = [1, 2, 3, 4, 5, 6] -y = [1, 3, 5] -``` - -This operation would return: - -``` -out ==> [2, 4, 6] -idx ==> [1, 3, 5] -``` - -x: 1-D. Values to keep. -y: 1-D. Values to remove. -out: 1-D. Values present in `x` but not in `y`. -idx: 1-D. Positions of `x` values preserved in `out`. -)doc"); + }); namespace { @@ -3701,133 +2085,7 @@ REGISTER_OP("SpaceToBatchND") return SpaceToBatchShapeHelper(c, c->input(0), c->input(1), c->input_tensor(1), c->input(2), c->input_tensor(2)); - }) - .Doc(R"doc( -SpaceToBatch for N-D tensors of type T. - -This operation divides "spatial" dimensions `[1, ..., M]` of the input into a -grid of blocks of shape `block_shape`, and interleaves these blocks with the -"batch" dimension (0) such that in the output, the spatial dimensions -`[1, ..., M]` correspond to the position within the grid, and the batch -dimension combines both the position within a spatial block and the original -batch position. Prior to division into blocks, the spatial dimensions of the -input are optionally zero padded according to `paddings`. See below for a -precise description. - -input: N-D with shape `input_shape = [batch] + spatial_shape + remaining_shape`, - where spatial_shape has `M` dimensions. - -block_shape: 1-D with shape `[M]`, all values must be >= 1. - -paddings: 2-D with shape `[M, 2]`, all values must be >= 0. - `paddings[i] = [pad_start, pad_end]` specifies the padding for input dimension - `i + 1`, which corresponds to spatial dimension `i`. It is required that - `block_shape[i]` divides `input_shape[i + 1] + pad_start + pad_end`. - -This operation is equivalent to the following steps: - -1. Zero-pad the start and end of dimensions `[1, ..., M]` of the - input according to `paddings` to produce `padded` of shape `padded_shape`. - -2. Reshape `padded` to `reshaped_padded` of shape: - - [batch] + - [padded_shape[1] / block_shape[0], - block_shape[0], - ..., - padded_shape[M] / block_shape[M-1], - block_shape[M-1]] + - remaining_shape - -3. Permute dimensions of `reshaped_padded` to produce - `permuted_reshaped_padded` of shape: - - block_shape + - [batch] + - [padded_shape[1] / block_shape[0], - ..., - padded_shape[M] / block_shape[M-1]] + - remaining_shape - -4. Reshape `permuted_reshaped_padded` to flatten `block_shape` into the batch - dimension, producing an output tensor of shape: - - [batch * prod(block_shape)] + - [padded_shape[1] / block_shape[0], - ..., - padded_shape[M] / block_shape[M-1]] + - remaining_shape - -Some examples: - -(1) For the following input of shape `[1, 2, 2, 1]`, `block_shape = [2, 2]`, and - `paddings = [[0, 0], [0, 0]]`: - -``` -x = [[[[1], [2]], [[3], [4]]]] -``` - -The output tensor has shape `[4, 1, 1, 1]` and value: - -``` -[[[[1]]], [[[2]]], [[[3]]], [[[4]]]] -``` - -(2) For the following input of shape `[1, 2, 2, 3]`, `block_shape = [2, 2]`, and - `paddings = [[0, 0], [0, 0]]`: - -``` -x = [[[[1, 2, 3], [4, 5, 6]], - [[7, 8, 9], [10, 11, 12]]]] -``` - -The output tensor has shape `[4, 1, 1, 3]` and value: - -``` -[[[1, 2, 3]], [[4, 5, 6]], [[7, 8, 9]], [[10, 11, 12]]] -``` - -(3) For the following input of shape `[1, 4, 4, 1]`, `block_shape = [2, 2]`, and - `paddings = [[0, 0], [0, 0]]`: - -``` -x = [[[[1], [2], [3], [4]], - [[5], [6], [7], [8]], - [[9], [10], [11], [12]], - [[13], [14], [15], [16]]]] -``` - -The output tensor has shape `[4, 2, 2, 1]` and value: - -``` -x = [[[[1], [3]], [[9], [11]]], - [[[2], [4]], [[10], [12]]], - [[[5], [7]], [[13], [15]]], - [[[6], [8]], [[14], [16]]]] -``` - -(4) For the following input of shape `[2, 2, 4, 1]`, block_shape = `[2, 2]`, and - paddings = `[[0, 0], [2, 0]]`: - -``` -x = [[[[1], [2], [3], [4]], - [[5], [6], [7], [8]]], - [[[9], [10], [11], [12]], - [[13], [14], [15], [16]]]] -``` - -The output tensor has shape `[8, 1, 3, 1]` and value: - -``` -x = [[[[0], [1], [3]]], [[[0], [9], [11]]], - [[[0], [2], [4]]], [[[0], [10], [12]]], - [[[0], [5], [7]]], [[[0], [13], [15]]], - [[[0], [6], [8]]], [[[0], [14], [16]]]] -``` - -Among others, this operation is useful for reducing atrous convolution into -regular convolution. -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("SpaceToBatch") @@ -3852,106 +2110,7 @@ REGISTER_OP("SpaceToBatch") return SpaceToBatchShapeHelper(c, input_shape, c->MakeShape({2}), &block_shape, c->input(1), c->input_tensor(1)); - }) - .Doc(R"doc( -SpaceToBatch for 4-D tensors of type T. - -This is a legacy version of the more general SpaceToBatchND. - -Zero-pads and then rearranges (permutes) blocks of spatial data into batch. -More specifically, this op outputs a copy of the input tensor where values from -the `height` and `width` dimensions are moved to the `batch` dimension. After -the zero-padding, both `height` and `width` of the input must be divisible by the -block size. - -input: 4-D with shape `[batch, height, width, depth]`. - -paddings: 2-D tensor of non-negative integers with shape `[2, 2]`. It specifies - the padding of the input with zeros across the spatial dimensions as follows: - - paddings = [[pad_top, pad_bottom], [pad_left, pad_right]] - - The effective spatial dimensions of the zero-padded input tensor will be: - - height_pad = pad_top + height + pad_bottom - width_pad = pad_left + width + pad_right - -The attr `block_size` must be greater than one. It indicates the block size. - - * Non-overlapping blocks of size `block_size x block size` in the height and - width dimensions are rearranged into the batch dimension at each location. - * The batch of the output tensor is `batch * block_size * block_size`. - * Both height_pad and width_pad must be divisible by block_size. - -The shape of the output will be: - - [batch*block_size*block_size, height_pad/block_size, width_pad/block_size, - depth] - -Some examples: - -(1) For the following input of shape `[1, 2, 2, 1]` and block_size of 2: - -``` -x = [[[[1], [2]], [[3], [4]]]] -``` - -The output tensor has shape `[4, 1, 1, 1]` and value: - -``` -[[[[1]]], [[[2]]], [[[3]]], [[[4]]]] -``` - -(2) For the following input of shape `[1, 2, 2, 3]` and block_size of 2: - -``` -x = [[[[1, 2, 3], [4, 5, 6]], - [[7, 8, 9], [10, 11, 12]]]] -``` - -The output tensor has shape `[4, 1, 1, 3]` and value: - -``` -[[[1, 2, 3]], [[4, 5, 6]], [[7, 8, 9]], [[10, 11, 12]]] -``` - -(3) For the following input of shape `[1, 4, 4, 1]` and block_size of 2: - -``` -x = [[[[1], [2], [3], [4]], - [[5], [6], [7], [8]], - [[9], [10], [11], [12]], - [[13], [14], [15], [16]]]] -``` - -The output tensor has shape `[4, 2, 2, 1]` and value: - -``` -x = [[[[1], [3]], [[9], [11]]], - [[[2], [4]], [[10], [12]]], - [[[5], [7]], [[13], [15]]], - [[[6], [8]], [[14], [16]]]] -``` - -(4) For the following input of shape `[2, 2, 4, 1]` and block_size of 2: - -``` -x = [[[[1], [2], [3], [4]], - [[5], [6], [7], [8]]], - [[[9], [10], [11], [12]], - [[13], [14], [15], [16]]]] -``` - -The output tensor has shape `[8, 1, 2, 1]` and value: - -``` -x = [[[[1], [3]]], [[[9], [11]]], [[[2], [4]]], [[[10], [12]]], - [[[5], [7]]], [[[13], [15]]], [[[6], [8]]], [[[14], [16]]]] -``` - -Among others, this operation is useful for reducing atrous convolution into -regular convolution. -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("BatchToSpaceND") @@ -3966,132 +2125,7 @@ REGISTER_OP("BatchToSpaceND") return BatchToSpaceShapeHelper(c, c->input(0), c->input(1), c->input_tensor(1), c->input(2), c->input_tensor(2)); - }) - .Doc(R"doc( -BatchToSpace for N-D tensors of type T. - -This operation reshapes the "batch" dimension 0 into `M + 1` dimensions of shape -`block_shape + [batch]`, interleaves these blocks back into the grid defined by -the spatial dimensions `[1, ..., M]`, to obtain a result with the same rank as -the input. The spatial dimensions of this intermediate result are then -optionally cropped according to `crops` to produce the output. This is the -reverse of SpaceToBatch. See below for a precise description. - -input: N-D with shape `input_shape = [batch] + spatial_shape + remaining_shape`, - where spatial_shape has M dimensions. - -block_shape: 1-D with shape `[M]`, all values must be >= 1. - -crops: 2-D with shape `[M, 2]`, all values must be >= 0. - `crops[i] = [crop_start, crop_end]` specifies the amount to crop from input - dimension `i + 1`, which corresponds to spatial dimension `i`. It is - required that - `crop_start[i] + crop_end[i] <= block_shape[i] * input_shape[i + 1]`. - -This operation is equivalent to the following steps: - -1. Reshape `input` to `reshaped` of shape: - [block_shape[0], ..., block_shape[M-1], - batch / prod(block_shape), - input_shape[1], ..., input_shape[N-1]] - -2. Permute dimensions of `reshaped` to produce `permuted` of shape - [batch / prod(block_shape), - - input_shape[1], block_shape[0], - ..., - input_shape[M], block_shape[M-1], - - input_shape[M+1], ..., input_shape[N-1]] - -3. Reshape `permuted` to produce `reshaped_permuted` of shape - [batch / prod(block_shape), - - input_shape[1] * block_shape[0], - ..., - input_shape[M] * block_shape[M-1], - - input_shape[M+1], - ..., - input_shape[N-1]] - -4. Crop the start and end of dimensions `[1, ..., M]` of - `reshaped_permuted` according to `crops` to produce the output of shape: - [batch / prod(block_shape), - - input_shape[1] * block_shape[0] - crops[0,0] - crops[0,1], - ..., - input_shape[M] * block_shape[M-1] - crops[M-1,0] - crops[M-1,1], - - input_shape[M+1], ..., input_shape[N-1]] - -Some examples: - -(1) For the following input of shape `[4, 1, 1, 1]`, `block_shape = [2, 2]`, and - `crops = [[0, 0], [0, 0]]`: - -``` -[[[[1]]], [[[2]]], [[[3]]], [[[4]]]] -``` - -The output tensor has shape `[1, 2, 2, 1]` and value: - -``` -x = [[[[1], [2]], [[3], [4]]]] -``` - -(2) For the following input of shape `[4, 1, 1, 3]`, `block_shape = [2, 2]`, and - `crops = [[0, 0], [0, 0]]`: - -``` -[[[1, 2, 3]], [[4, 5, 6]], [[7, 8, 9]], [[10, 11, 12]]] -``` - -The output tensor has shape `[1, 2, 2, 3]` and value: - -``` -x = [[[[1, 2, 3], [4, 5, 6]], - [[7, 8, 9], [10, 11, 12]]]] -``` - -(3) For the following input of shape `[4, 2, 2, 1]`, `block_shape = [2, 2]`, and - `crops = [[0, 0], [0, 0]]`: - -``` -x = [[[[1], [3]], [[9], [11]]], - [[[2], [4]], [[10], [12]]], - [[[5], [7]], [[13], [15]]], - [[[6], [8]], [[14], [16]]]] -``` - -The output tensor has shape `[1, 4, 4, 1]` and value: - -``` -x = [[[1], [2], [3], [4]], - [[5], [6], [7], [8]], - [[9], [10], [11], [12]], - [[13], [14], [15], [16]]] -``` - -(4) For the following input of shape `[8, 1, 3, 1]`, `block_shape = [2, 2]`, and - `crops = [[0, 0], [2, 0]]`: - -``` -x = [[[[0], [1], [3]]], [[[0], [9], [11]]], - [[[0], [2], [4]]], [[[0], [10], [12]]], - [[[0], [5], [7]]], [[[0], [13], [15]]], - [[[0], [6], [8]]], [[[0], [14], [16]]]] -``` - -The output tensor has shape `[2, 2, 4, 1]` and value: - -``` -x = [[[[1], [2], [3], [4]], - [[5], [6], [7], [8]]], - [[[9], [10], [11], [12]], - [[13], [14], [15], [16]]]] -``` -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("BatchToSpace") @@ -4116,97 +2150,7 @@ REGISTER_OP("BatchToSpace") return BatchToSpaceShapeHelper(c, input_shape, c->MakeShape({2}), &block_shape, c->input(1), c->input_tensor(1)); - }) - .Doc(R"doc( -BatchToSpace for 4-D tensors of type T. - -This is a legacy version of the more general BatchToSpaceND. - -Rearranges (permutes) data from batch into blocks of spatial data, followed by -cropping. This is the reverse transformation of SpaceToBatch. More specifically, -this op outputs a copy of the input tensor where values from the `batch` -dimension are moved in spatial blocks to the `height` and `width` dimensions, -followed by cropping along the `height` and `width` dimensions. - -input: 4-D tensor with shape - `[batch*block_size*block_size, height_pad/block_size, width_pad/block_size, - depth]`. Note that the batch size of the input tensor must be divisible by - `block_size * block_size`. - -crops: 2-D tensor of non-negative integers with shape `[2, 2]`. It specifies - how many elements to crop from the intermediate result across the spatial - dimensions as follows: - - crops = [[crop_top, crop_bottom], [crop_left, crop_right]] - -output: 4-D with shape `[batch, height, width, depth]`, where: - - height = height_pad - crop_top - crop_bottom - width = width_pad - crop_left - crop_right - -The attr `block_size` must be greater than one. It indicates the block size. - -Some examples: - -(1) For the following input of shape `[4, 1, 1, 1]` and block_size of 2: - -``` -[[[[1]]], [[[2]]], [[[3]]], [[[4]]]] -``` - -The output tensor has shape `[1, 2, 2, 1]` and value: - -``` -x = [[[[1], [2]], [[3], [4]]]] -``` - -(2) For the following input of shape `[4, 1, 1, 3]` and block_size of 2: - -``` -[[[1, 2, 3]], [[4, 5, 6]], [[7, 8, 9]], [[10, 11, 12]]] -``` - -The output tensor has shape `[1, 2, 2, 3]` and value: - -``` -x = [[[[1, 2, 3], [4, 5, 6]], - [[7, 8, 9], [10, 11, 12]]]] -``` - -(3) For the following input of shape `[4, 2, 2, 1]` and block_size of 2: - -``` -x = [[[[1], [3]], [[9], [11]]], - [[[2], [4]], [[10], [12]]], - [[[5], [7]], [[13], [15]]], - [[[6], [8]], [[14], [16]]]] -``` - -The output tensor has shape `[1, 4, 4, 1]` and value: - -``` -x = [[[1], [2], [3], [4]], - [[5], [6], [7], [8]], - [[9], [10], [11], [12]], - [[13], [14], [15], [16]]] -``` - -(4) For the following input of shape `[8, 1, 2, 1]` and block_size of 2: - -``` -x = [[[[1], [3]]], [[[9], [11]]], [[[2], [4]]], [[[10], [12]]], - [[[5], [7]]], [[[13], [15]]], [[[6], [8]]], [[[14], [16]]]] -``` - -The output tensor has shape `[2, 2, 4, 1]` and value: - -``` -x = [[[[1], [3]], [[5], [7]]], - [[[2], [4]], [[10], [12]]], - [[[5], [7]], [[13], [15]]], - [[[6], [8]], [[14], [16]]]] -``` -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("SpaceToDepth") @@ -4260,96 +2204,7 @@ REGISTER_OP("SpaceToDepth") c->set_output(0, output_shape); return Status::OK(); - }) - .Doc(R"doc( -SpaceToDepth for tensors of type T. - -Rearranges blocks of spatial data, into depth. More specifically, -this op outputs a copy of the input tensor where values from the `height` -and `width` dimensions are moved to the `depth` dimension. -The attr `block_size` indicates the input block size. - - * Non-overlapping blocks of size `block_size x block size` are rearranged - into depth at each location. - * The depth of the output tensor is `block_size * block_size * input_depth`. - * The Y, X coordinates within each block of the input become the high order - component of the output channel index. - * The input tensor's height and width must be divisible by block_size. - -The `data_format` attr specifies the layout of the input and output tensors -with the following options: - "NHWC": `[ batch, height, width, channels ]` - "NCHW": `[ batch, channels, height, width ]` - "NCHW_VECT_C": - `qint8 [ batch, channels / 4, height, width, 4 ]` - -It is useful to consider the operation as transforming a 6-D Tensor. -e.g. for data_format = NHWC, - Each element in the input tensor can be specified via 6 coordinates, - ordered by decreasing memory layout significance as: - n,oY,bY,oX,bX,iC (where n=batch index, oX, oY means X or Y coordinates - within the output image, bX, bY means coordinates - within the input block, iC means input channels). - The output would be a transpose to the following layout: - n,oY,oX,bY,bX,iC - -This operation is useful for resizing the activations between convolutions -(but keeping all data), e.g. instead of pooling. It is also useful for training -purely convolutional models. - -For example, given an input of shape `[1, 2, 2, 1]`, data_format = "NHWC" and -block_size = 2: - -``` -x = [[[[1], [2]], - [[3], [4]]]] -``` - -This operation will output a tensor of shape `[1, 1, 1, 4]`: - -``` -[[[[1, 2, 3, 4]]]] -``` - -Here, the input has a batch of 1 and each batch element has shape `[2, 2, 1]`, -the corresponding output will have a single element (i.e. width and height are -both 1) and will have a depth of 4 channels (1 * block_size * block_size). -The output element shape is `[1, 1, 4]`. - -For an input tensor with larger depth, here of shape `[1, 2, 2, 3]`, e.g. - -``` -x = [[[[1, 2, 3], [4, 5, 6]], - [[7, 8, 9], [10, 11, 12]]]] -``` - -This operation, for block_size of 2, will return the following tensor of shape -`[1, 1, 1, 12]` - -``` -[[[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]]]] -``` - -Similarly, for the following input of shape `[1 4 4 1]`, and a block size of 2: - -``` -x = [[[[1], [2], [5], [6]], - [[3], [4], [7], [8]], - [[9], [10], [13], [14]], - [[11], [12], [15], [16]]]] -``` - -the operator will return the following tensor of shape `[1 2 2 4]`: - -``` -x = [[[[1, 2, 3, 4], - [5, 6, 7, 8]], - [[9, 10, 11, 12], - [13, 14, 15, 16]]]] -``` - -block_size: The size of the spatial block. -)doc"); + }); // -------------------------------------------------------------------------- REGISTER_OP("DepthToSpace") @@ -4401,102 +2256,7 @@ REGISTER_OP("DepthToSpace") c->set_output(0, output_shape); return Status::OK(); - }) - .Doc(R"doc( -DepthToSpace for tensors of type T. - -Rearranges data from depth into blocks of spatial data. -This is the reverse transformation of SpaceToDepth. More specifically, -this op outputs a copy of the input tensor where values from the `depth` -dimension are moved in spatial blocks to the `height` and `width` dimensions. -The attr `block_size` indicates the input block size and how the data is moved. - - * Chunks of data of size `block_size * block_size` from depth are rearranged - into non-overlapping blocks of size `block_size x block_size` - * The width the output tensor is `input_depth * block_size`, whereas the - height is `input_height * block_size`. - * The Y, X coordinates within each block of the output image are determined - by the high order component of the input channel index. - * The depth of the input tensor must be divisible by - `block_size * block_size`. - -The `data_format` attr specifies the layout of the input and output tensors -with the following options: - "NHWC": `[ batch, height, width, channels ]` - "NCHW": `[ batch, channels, height, width ]` - "NCHW_VECT_C": - `qint8 [ batch, channels / 4, height, width, 4 ]` - -It is useful to consider the operation as transforming a 6-D Tensor. -e.g. for data_format = NHWC, - Each element in the input tensor can be specified via 6 coordinates, - ordered by decreasing memory layout significance as: - n,iY,iX,bY,bX,oC (where n=batch index, iX, iY means X or Y coordinates - within the input image, bX, bY means coordinates - within the output block, oC means output channels). - The output would be the input transposed to the following layout: - n,iY,bY,iX,bX,oC - -This operation is useful for resizing the activations between convolutions -(but keeping all data), e.g. instead of pooling. It is also useful for training -purely convolutional models. - -For example, given an input of shape `[1, 1, 1, 4]`, data_format = "NHWC" and -block_size = 2: - -``` -x = [[[[1, 2, 3, 4]]]] - -``` - -This operation will output a tensor of shape `[1, 2, 2, 1]`: - -``` - [[[[1], [2]], - [[3], [4]]]] -``` - -Here, the input has a batch of 1 and each batch element has shape `[1, 1, 4]`, -the corresponding output will have 2x2 elements and will have a depth of -1 channel (1 = `4 / (block_size * block_size)`). -The output element shape is `[2, 2, 1]`. - -For an input tensor with larger depth, here of shape `[1, 1, 1, 12]`, e.g. - -``` -x = [[[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]]]] -``` - -This operation, for block size of 2, will return the following tensor of shape -`[1, 2, 2, 3]` - -``` - [[[[1, 2, 3], [4, 5, 6]], - [[7, 8, 9], [10, 11, 12]]]] - -``` - -Similarly, for the following input of shape `[1 2 2 4]`, and a block size of 2: - -``` -x = [[[[1, 2, 3, 4], - [5, 6, 7, 8]], - [[9, 10, 11, 12], - [13, 14, 15, 16]]]] -``` - -the operator will return the following tensor of shape `[1 4 4 1]`: - -``` -x = [[[ [1], [2], [5], [6]], - [ [3], [4], [7], [8]], - [ [9], [10], [13], [14]], - [ [11], [12], [15], [16]]]] - -``` - -block_size: The size of the spatial block, same as in Space2Depth. -)doc"); + }); // -------------------------------------------------------------------------- @@ -4583,34 +2343,7 @@ REGISTER_OP("ExtractImagePatches") {batch_size_dim, output_rows, output_cols, output_depth_dim}); c->set_output(0, output_shape); return Status::OK(); - }) - .Doc(R"doc( -Extract `patches` from `images` and put them in the "depth" output dimension. - -images: 4-D Tensor with shape `[batch, in_rows, in_cols, depth]`. -patches: 4-D Tensor with shape `[batch, out_rows, out_cols, ksize_rows * - ksize_cols * depth]` containing image patches with size - `ksize_rows x ksize_cols x depth` vectorized in the "depth" dimension. Note - `out_rows` and `out_cols` are the dimensions of the output patches. -ksizes: The size of the sliding window for each dimension of `images`. -strides: 1-D of length 4. How far the centers of two consecutive patches are in - the images. Must be: `[1, stride_rows, stride_cols, 1]`. -rates: 1-D of length 4. Must be: `[1, rate_rows, rate_cols, 1]`. This is the - input stride, specifying how far two consecutive patch samples are in the - input. Equivalent to extracting patches with - `patch_sizes_eff = patch_sizes + (patch_sizes - 1) * (rates - 1)`, followed by - subsampling them spatially by a factor of `rates`. This is equivalent to - `rate` in dilated (a.k.a. Atrous) convolutions. -padding: The type of padding algorithm to use. - -We specify the size-related attributes as: - -```python - ksizes = [1, ksize_rows, ksize_cols, 1] - strides = [1, strides_rows, strides_cols, 1] - rates = [1, rates_rows, rates_cols, 1] -``` -)doc"); + }); // -------------------------------------------------------------------------- @@ -4674,23 +2407,7 @@ REGISTER_OP("Bitcast") c->set_output(0, new_shape); return Status::OK(); - }) - .Doc(R"doc( -Bitcasts a tensor from one type to another without copying data. - -Given a tensor `input`, this operation returns a tensor that has the same buffer -data as `input` with datatype `type`. - -If the input datatype `T` is larger than the output datatype `type` then the -shape changes from [...] to [..., sizeof(`T`)/sizeof(`type`)]. - -If `T` is smaller than `type`, the operator requires that the rightmost -dimension be equal to sizeof(`type`)/sizeof(`T`). The shape then goes from -[..., sizeof(`type`)/sizeof(`T`)] to [...]. - -*NOTE*: Bitcast is implemented as a low-level cast, so machines with different -endian orderings will give different results. -)doc"); + }); REGISTER_OP("OneHot") .Input("indices: TI") @@ -4726,106 +2443,7 @@ REGISTER_OP("OneHot") TF_RETURN_IF_ERROR(c->Concatenate(front, back, &out)); c->set_output(0, out); return Status::OK(); - }) - .Doc(R"doc( -Returns a one-hot tensor. - -The locations represented by indices in `indices` take value `on_value`, -while all other locations take value `off_value`. - -If the input `indices` is rank `N`, the output will have rank `N+1`, -The new axis is created at dimension `axis` (default: the new axis is -appended at the end). - -If `indices` is a scalar the output shape will be a vector of length `depth`. - -If `indices` is a vector of length `features`, the output shape will be: -``` - features x depth if axis == -1 - depth x features if axis == 0 -``` - -If `indices` is a matrix (batch) with shape `[batch, features]`, -the output shape will be: -``` - batch x features x depth if axis == -1 - batch x depth x features if axis == 1 - depth x batch x features if axis == 0 -``` - - -Examples -========= - -Suppose that - -``` - indices = [0, 2, -1, 1] - depth = 3 - on_value = 5.0 - off_value = 0.0 - axis = -1 -``` - -Then output is `[4 x 3]`: - - ```output = - [5.0 0.0 0.0] // one_hot(0) - [0.0 0.0 5.0] // one_hot(2) - [0.0 0.0 0.0] // one_hot(-1) - [0.0 5.0 0.0] // one_hot(1) - ``` - -Suppose that - -``` - indices = [0, 2, -1, 1] - depth = 3 - on_value = 0.0 - off_value = 3.0 - axis = 0 -``` - -Then output is `[3 x 4]`: - - ```output = - [0.0 3.0 3.0 3.0] - [3.0 3.0 3.0 0.0] - [3.0 3.0 3.0 3.0] - [3.0 0.0 3.0 3.0] - // ^ one_hot(0) - // ^ one_hot(2) - // ^ one_hot(-1) - // ^ one_hot(1) - ``` -Suppose that - -``` - indices = [[0, 2], [1, -1]] - depth = 3 - on_value = 1.0 - off_value = 0.0 - axis = -1 -``` - -Then output is `[2 x 2 x 3]`: - - ```output = - [ - [1.0, 0.0, 0.0] // one_hot(0) - [0.0, 0.0, 1.0] // one_hot(2) - ][ - [0.0, 1.0, 0.0] // one_hot(1) - [0.0, 0.0, 0.0] // one_hot(-1) - ]``` - -indices: A tensor of indices. -depth: A scalar defining the depth of the one hot dimension. -on_value: A scalar defining the value to fill in output when `indices[j] = i`. -off_value: A scalar defining the value to fill in output when `indices[j] != i`. -axis: The axis to fill (default: -1, a new inner-most axis). -output: The one-hot tensor. -)doc"); + }); // EXPERIMENTAL. DO NOT USE OR DEPEND ON THIS YET. REGISTER_OP("QuantizeAndDequantize") @@ -4838,10 +2456,7 @@ REGISTER_OP("QuantizeAndDequantize") .Output("output: T") .Attr("T: {bfloat16, float, double}") .SetShapeFn(shape_inference::UnchangedShape) - .Deprecated(22, "Replaced by QuantizeAndDequantizeV2") - .Doc(R"doc( -Use QuantizeAndDequantizeV2 instead. -)doc"); + .Deprecated(22, "Replaced by QuantizeAndDequantizeV2"); // TODO(suharshs): Deprecate QuantizeAndDequantizeV2. REGISTER_OP("QuantizeAndDequantizeV2") @@ -4859,69 +2474,7 @@ REGISTER_OP("QuantizeAndDequantizeV2") TF_RETURN_IF_ERROR(c->WithRank(c->input(2), 0, &unused)); c->set_output(0, c->input(0)); return Status::OK(); - }) - .Doc(R"doc( -Quantizes then dequantizes a tensor. - -This op simulates the precision loss from the quantized forward pass by: -1. Quantizing the tensor to fixed point numbers, which should match the target - quantization method when it is used in inference. -2. Dequantizing it back to floating point numbers for the following ops, most - likely matmul. - -There are different ways to quantize. This version does not use the full range -of the output type, choosing to elide the lowest possible value for symmetry -(e.g., output range is -127 to 127, not -128 to 127 for signed 8 bit -quantization), so that 0.0 maps to 0. - -To perform this op, we first find the range of values in our tensor. The range -we use is always centered on 0, so we find m such that - -1. m = max(abs(input_min), abs(input_max)) if range_given is true, -2. m = max(abs(min_elem(input)), abs(max_elem(input))) otherwise. - -Our input tensor range is then [-m, m]. - -Next, we choose our fixed-point quantization buckets, [min_fixed, max_fixed]. -If signed_input is true, this is - - [min_fixed, max_fixed ] = - [-(1 << (num_bits - 1) - 1), (1 << (num_bits - 1)) - 1]. - -Otherwise, if signed_input is false, the fixed-point range is - - [min_fixed, max_fixed] = [0, (1 << num_bits) - 1]. - -From this we compute our scaling factor, s: - - s = (max_fixed - min_fixed) / (2 * m). - -Now we can quantize and dequantize the elements of our tensor. An element e -is transformed into e': - - e' = (e * s).round_to_nearest() / s. - -Note that we have a different number of buckets in the signed vs. unsigned -cases. For example, if num_bits == 8, we get 254 buckets in the signed case -vs. 255 in the unsigned case. - -For example, suppose num_bits = 8 and m = 1. Then - - [min_fixed, max_fixed] = [-127, 127], and - s = (127 + 127) / 2 = 127. - -Given the vector {-1, -0.5, 0, 0.3}, this is quantized to -{-127, -63, 0, 38}, and dequantized to {-1, -63.0/127, 0, 38.0/127}. - -input: Tensor to quantize and then dequantize. -signed_input: If the quantization is signed or unsigned. -num_bits: The bitwidth of the quantization. -range_given: If the range is given or should be computed from the tensor. -input_min: If range_given, this is the min of the range, otherwise this input - will be ignored. -input_max: If range_given, this is the max of the range, otherwise this input - will be ignored. -)doc"); + }); REGISTER_OP("QuantizeAndDequantizeV3") .Input("input: T") @@ -4939,13 +2492,7 @@ REGISTER_OP("QuantizeAndDequantizeV3") TF_RETURN_IF_ERROR(c->WithRank(c->input(3), 0, &unused)); c->set_output(0, c->input(0)); return Status::OK(); - }) - .Doc(R"doc( -Quantizes then dequantizes a tensor. - -This is almost identical to QuantizeAndDequantizeV2, except that num_bits is a -tensor, so its value can change during training. -)doc"); + }); REGISTER_OP("QuantizeV2") .Input("input: float") @@ -4967,110 +2514,7 @@ REGISTER_OP("QuantizeV2") c->set_output(1, c->Scalar()); c->set_output(2, c->Scalar()); return Status::OK(); - }) - .Doc(R"doc( -Quantize the 'input' tensor of type float to 'output' tensor of type 'T'. - -[min_range, max_range] are scalar floats that specify the range for -the 'input' data. The 'mode' attribute controls exactly which calculations are -used to convert the float values to their quantized equivalents. The -'round_mode' attribute controls which rounding tie-breaking algorithm is used -when rounding float values to their quantized equivalents. - -In 'MIN_COMBINED' mode, each value of the tensor will undergo the following: - -``` -out[i] = (in[i] - min_range) * range(T) / (max_range - min_range) -if T == qint8, out[i] -= (range(T) + 1) / 2.0 -``` -here `range(T) = numeric_limits<T>::max() - numeric_limits<T>::min()` - -*MIN_COMBINED Mode Example* - -Assume the input is type float and has a possible range of [0.0, 6.0] and the -output type is quint8 ([0, 255]). The min_range and max_range values should be -specified as 0.0 and 6.0. Quantizing from float to quint8 will multiply each -value of the input by 255/6 and cast to quint8. - -If the output type was qint8 ([-128, 127]), the operation will additionally -subtract each value by 128 prior to casting, so that the range of values aligns -with the range of qint8. - -If the mode is 'MIN_FIRST', then this approach is used: - -``` -num_discrete_values = 1 << (# of bits in T) -range_adjust = num_discrete_values / (num_discrete_values - 1) -range = (range_max - range_min) * range_adjust -range_scale = num_discrete_values / range -quantized = round(input * range_scale) - round(range_min * range_scale) + - numeric_limits<T>::min() -quantized = max(quantized, numeric_limits<T>::min()) -quantized = min(quantized, numeric_limits<T>::max()) -``` - -The biggest difference between this and MIN_COMBINED is that the minimum range -is rounded first, before it's subtracted from the rounded value. With -MIN_COMBINED, a small bias is introduced where repeated iterations of quantizing -and dequantizing will introduce a larger and larger error. - -*SCALED mode Example* - -`SCALED` mode matches the quantization approach used in -`QuantizeAndDequantize{V2|V3}`. - -If the mode is `SCALED`, we do not use the full range of the output type, -choosing to elide the lowest possible value for symmetry (e.g., output range is --127 to 127, not -128 to 127 for signed 8 bit quantization), so that 0.0 maps to -0. - -We first find the range of values in our tensor. The -range we use is always centered on 0, so we find m such that -```c++ - m = max(abs(input_min), abs(input_max)) -``` - -Our input tensor range is then `[-m, m]`. - -Next, we choose our fixed-point quantization buckets, `[min_fixed, max_fixed]`. -If T is signed, this is -``` - num_bits = sizeof(T) * 8 - [min_fixed, max_fixed] = - [-(1 << (num_bits - 1) - 1), (1 << (num_bits - 1)) - 1] -``` - -Otherwise, if T is unsigned, the fixed-point range is -``` - [min_fixed, max_fixed] = [0, (1 << num_bits) - 1] -``` - -From this we compute our scaling factor, s: -```c++ - s = (max_fixed - min_fixed) / (2 * m) -``` - -Now we can quantize the elements of our tensor: -```c++ -result = round(input * s) -``` - -One thing to watch out for is that the operator may choose to adjust the -requested minimum and maximum values slightly during the quantization process, -so you should always use the output ports as the range for further calculations. -For example, if the requested minimum and maximum values are close to equal, -they will be separated by a small epsilon value to prevent ill-formed quantized -buffers from being created. Otherwise, you can end up with buffers where all the -quantized values map to the same float value, which causes problems for -operations that have to perform further calculations on them. - -min_range: The minimum scalar value possibly produced for the input. -max_range: The maximum scalar value possibly produced for the input. -output: The quantized data produced from the float input. -output_min: The actual minimum scalar value used for the output. -output_max: The actual maximum scalar value used for the output. - -)doc"); + }); REGISTER_OP("Dequantize") .Input("input: T") @@ -5085,88 +2529,7 @@ REGISTER_OP("Dequantize") TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 0, &unused)); TF_RETURN_IF_ERROR(c->WithRank(c->input(2), 0, &unused)); return Status::OK(); - }) - .Doc(R"doc( -Dequantize the 'input' tensor into a float Tensor. - -[min_range, max_range] are scalar floats that specify the range for -the 'input' data. The 'mode' attribute controls exactly which calculations are -used to convert the float values to their quantized equivalents. - -In 'MIN_COMBINED' mode, each value of the tensor will undergo the following: - -``` -if T == qint8, in[i] += (range(T) + 1)/ 2.0 -out[i] = min_range + (in[i]* (max_range - min_range) / range(T)) -``` -here `range(T) = numeric_limits<T>::max() - numeric_limits<T>::min()` - -*MIN_COMBINED Mode Example* - -If the input comes from a QuantizedRelu6, the output type is -quint8 (range of 0-255) but the possible range of QuantizedRelu6 is -0-6. The min_range and max_range values are therefore 0.0 and 6.0. -Dequantize on quint8 will take each value, cast to float, and multiply -by 6 / 255. -Note that if quantizedtype is qint8, the operation will additionally add -each value by 128 prior to casting. - -If the mode is 'MIN_FIRST', then this approach is used: - -```c++ -num_discrete_values = 1 << (# of bits in T) -range_adjust = num_discrete_values / (num_discrete_values - 1) -range = (range_max - range_min) * range_adjust -range_scale = range / num_discrete_values -const double offset_input = static_cast<double>(input) - lowest_quantized; -result = range_min + ((input - numeric_limits<T>::min()) * range_scale) -``` - -*SCALED mode Example* - -`SCALED` mode matches the quantization approach used in -`QuantizeAndDequantize{V2|V3}`. - -If the mode is `SCALED`, we do not use the full range of the output type, -choosing to elide the lowest possible value for symmetry (e.g., output range is --127 to 127, not -128 to 127 for signed 8 bit quantization), so that 0.0 maps to -0. - -We first find the range of values in our tensor. The -range we use is always centered on 0, so we find m such that -```c++ - m = max(abs(input_min), abs(input_max)) -``` - -Our input tensor range is then `[-m, m]`. - -Next, we choose our fixed-point quantization buckets, `[min_fixed, max_fixed]`. -If T is signed, this is -``` - num_bits = sizeof(T) * 8 - [min_fixed, max_fixed] = - [-(1 << (num_bits - 1) - 1), (1 << (num_bits - 1)) - 1] -``` - -Otherwise, if T is unsigned, the fixed-point range is -``` - [min_fixed, max_fixed] = [0, (1 << num_bits) - 1] -``` - -From this we compute our scaling factor, s: -```c++ - s = (2 * m) / (max_fixed - min_fixed) -``` - -Now we can dequantize the elements of our tensor: -```c++ -result = input * s -``` - -min_range: The minimum scalar value possibly produced for the input. -max_range: The maximum scalar value possibly produced for the input. - -)doc"); + }); REGISTER_OP("QuantizedConcat") .Input("concat_dim: int32") @@ -5188,22 +2551,7 @@ REGISTER_OP("QuantizedConcat") c->set_output(1, c->Scalar()); c->set_output(2, c->Scalar()); return Status::OK(); - }) - .Doc(R"doc( -Concatenates quantized tensors along one dimension. - -concat_dim: 0-D. The dimension along which to concatenate. Must be in the - range [0, rank(values)). -values: The `N` Tensors to concatenate. Their ranks and types must match, - and their sizes must match in all dimensions except `concat_dim`. -input_mins: The minimum scalar values for each of the input tensors. -input_maxes: The maximum scalar values for each of the input tensors. -output_min: The float value that the minimum quantized output value represents. -output_max: The float value that the maximum quantized output value represents. -output: A `Tensor` with the concatenation of values stacked along the - `concat_dim` dimension. This tensor's shape matches that of `values` except - in `concat_dim` where it has the sum of the sizes. -)doc"); + }); REGISTER_OP("QuantizedReshape") .Input("tensor: T") @@ -5223,17 +2571,7 @@ REGISTER_OP("QuantizedReshape") c->set_output(1, c->Scalar()); c->set_output(2, c->Scalar()); return Status::OK(); - }) - .Doc(R"Doc( -Reshapes a quantized tensor as per the Reshape op. -``` - -shape: Defines the shape of the output tensor. -input_min: The minimum value of the input. -input_max: The maximum value of the input. -output_min: This value is copied from input_min. -output_max: This value is copied from input_max. -)Doc"); + }); REGISTER_OP("QuantizedInstanceNorm") .Input("x: T") @@ -5261,24 +2599,7 @@ REGISTER_OP("QuantizedInstanceNorm") c->set_output(1, c->Scalar()); c->set_output(2, c->Scalar()); return Status::OK(); - }) - .Doc(R"doc( -Quantized Instance normalization. - -x: A 4D input Tensor. -x_min: The value represented by the lowest quantized input. -x_max: The value represented by the highest quantized input. -y: A 4D Tensor. -y_min: The value represented by the lowest quantized output. -y_max: The value represented by the highest quantized output. -output_range_given: If True, `given_y_min` and `given_y_min` - and `given_y_max` are used as the output range. Otherwise, - the implementation computes the output range. -given_y_min: Output in `y_min` if `output_range_given` is True. -given_y_max: Output in `y_max` if `output_range_given` is True. -variance_epsilon: A small float number to avoid dividing by 0. -min_separation: Minimum value of `y_max - y_min` -)doc"); + }); namespace { @@ -5352,88 +2673,7 @@ REGISTER_OP("ScatterNd") .Output("output: T") .Attr("T: type") .Attr("Tindices: {int32, int64}") - .SetShapeFn(ScatterNdShape) - .Doc(R"doc( -Scatter `updates` into a new (initially zero) tensor according to `indices`. - -Creates a new tensor by applying sparse `updates` to individual -values or slices within a zero tensor of the given `shape` according to -indices. This operator is the inverse of the @{tf.gather_nd} operator which -extracts values or slices from a given tensor. - -**WARNING**: The order in which updates are applied is nondeterministic, so the -output will be nondeterministic if `indices` contains duplicates. - -`indices` is an integer tensor containing indices into a new tensor of shape -`shape`. The last dimension of `indices` can be at most the rank of `shape`: - - indices.shape[-1] <= shape.rank - -The last dimension of `indices` corresponds to indices into elements -(if `indices.shape[-1] = shape.rank`) or slices -(if `indices.shape[-1] < shape.rank`) along dimension `indices.shape[-1]` of -`shape`. `updates` is a tensor with shape - - indices.shape[:-1] + shape[indices.shape[-1]:] - -The simplest form of scatter is to insert individual elements in a tensor by -index. For example, say we want to insert 4 scattered elements in a rank-1 -tensor with 8 elements. - -<div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"> -<img style="width:100%" src="https://www.tensorflow.org/images/ScatterNd1.png" alt> -</div> - -In Python, this scatter operation would look like this: - -```python - indices = tf.constant([[4], [3], [1], [7]]) - updates = tf.constant([9, 10, 11, 12]) - shape = tf.constant([8]) - scatter = tf.scatter_nd(indices, updates, shape) - with tf.Session() as sess: - print(sess.run(scatter)) -``` - -The resulting tensor would look like this: - - [0, 11, 0, 10, 9, 0, 0, 12] - -We can also, insert entire slices of a higher rank tensor all at once. For -example, if we wanted to insert two slices in the first dimension of a -rank-3 tensor with two matrices of new values. - -<div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"> -<img style="width:100%" src="https://www.tensorflow.org/images/ScatterNd2.png" alt> -</div> - -In Python, this scatter operation would look like this: - -```python - indices = tf.constant([[0], [2]]) - updates = tf.constant([[[5, 5, 5, 5], [6, 6, 6, 6], - [7, 7, 7, 7], [8, 8, 8, 8]], - [[5, 5, 5, 5], [6, 6, 6, 6], - [7, 7, 7, 7], [8, 8, 8, 8]]]) - shape = tf.constant([4, 4, 4]) - scatter = tf.scatter_nd(indices, updates, shape) - with tf.Session() as sess: - print(sess.run(scatter)) -``` - -The resulting tensor would look like this: - - [[[5, 5, 5, 5], [6, 6, 6, 6], [7, 7, 7, 7], [8, 8, 8, 8]], - [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]], - [[5, 5, 5, 5], [6, 6, 6, 6], [7, 7, 7, 7], [8, 8, 8, 8]], - [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]] - -indices: Index tensor. -updates: Updates to scatter into output. -shape: 1-D. The shape of the resulting tensor. -output: A new tensor with the given shape and updates applied according - to the indices. -)doc"); + .SetShapeFn(ScatterNdShape); REGISTER_OP("ScatterNdNonAliasingAdd") .Input("input: T") @@ -5442,53 +2682,7 @@ REGISTER_OP("ScatterNdNonAliasingAdd") .Output("output: T") .Attr("T: numbertype") .Attr("Tindices: {int32, int64}") - .SetShapeFn(shape_inference::ScatterNdUpdateShape) - .Doc(R"doc( -Applies sparse addition to `input` using individual values or slices -from `updates` according to indices `indices`. The updates are non-aliasing: -`input` is only modified in-place if no other operations will use it. -Otherwise, a copy of `input` is made. This operation has a gradient with -respect to both `input` and `updates`. - -`input` is a `Tensor` with rank `P` and `indices` is a `Tensor` of rank `Q`. - -`indices` must be integer tensor, containing indices into `input`. -It must be shape `[d_0, ..., d_{Q-2}, K]` where `0 < K <= P`. - -The innermost dimension of `indices` (with length `K`) corresponds to -indices into elements (if `K = P`) or `(P-K)`-dimensional slices -(if `K < P`) along the `K`th dimension of `input`. - -`updates` is `Tensor` of rank `Q-1+P-K` with shape: - -``` -[d_0, ..., d_{Q-2}, input.shape[K], ..., input.shape[P-1]]. -``` - -For example, say we want to add 4 scattered elements to a rank-1 tensor to 8 -elements. In Python, that addition would look like this: - - input = tf.constant([1, 2, 3, 4, 5, 6, 7, 8]) - indices = tf.constant([[4], [3], [1], [7]]) - updates = tf.constant([9, 10, 11, 12]) - output = tf.scatter_nd_non_aliasing_add(input, indices, updates) - with tf.Session() as sess: - print(sess.run(output)) - -The resulting value `output` would look like this: - - [1, 13, 3, 14, 14, 6, 7, 20] - -See @{tf.scatter_nd} for more details about how to make updates to slices. - -input: A Tensor. -indices: A Tensor. Must be one of the following types: `int32`, `int64`. - A tensor of indices into `input`. -updates: A Tensor. Must have the same type as ref. A tensor of updated values - to add to `input`. -output: A `Tensor` with the same shape as `input`, containing values of `input` - updated with `updates`. -)doc"); + .SetShapeFn(shape_inference::ScatterNdUpdateShape); REGISTER_OP("FakeQuantWithMinMaxArgs") .Attr("min: float = -6.0") @@ -5497,18 +2691,7 @@ REGISTER_OP("FakeQuantWithMinMaxArgs") .Attr("narrow_range: bool = false") .Input("inputs: float") .Output("outputs: float") - .SetShapeFn(shape_inference::UnchangedShape) - .Doc(R"doc( -Fake-quantize the 'inputs' tensor, type float to 'outputs' tensor of same type. - -Attributes `[min; max]` define the clamping range for the `inputs` data. -`inputs` values are quantized into the quantization range (`[0; 2^num_bits - 1]` -when `narrow_range` is false and `[1; 2^num_bits - 1]` when it is true) and -then de-quantized and output as floats in `[min; max]` interval. -`num_bits` is the bitwidth of the quantization; between 2 and 8, inclusive. - -Quantization is called fake since the output is still in floating point. -)doc"); + .SetShapeFn(shape_inference::UnchangedShape); REGISTER_OP("FakeQuantWithMinMaxArgsGradient") .Attr("min: float = -6.0") @@ -5518,15 +2701,7 @@ REGISTER_OP("FakeQuantWithMinMaxArgsGradient") .Input("gradients: float") .Input("inputs: float") .Output("backprops: float") - .SetShapeFn(shape_inference::UnchangedShape) - .Doc(R"doc( -Compute gradients for a FakeQuantWithMinMaxArgs operation. - -gradients: Backpropagated gradients above the FakeQuantWithMinMaxArgs operation. -inputs: Values passed as inputs to the FakeQuantWithMinMaxArgs operation. -backprops: Backpropagated gradients below the FakeQuantWithMinMaxArgs operation: - `gradients * (inputs >= min && inputs <= max)`. -)doc"); + .SetShapeFn(shape_inference::UnchangedShape); REGISTER_OP("FakeQuantWithMinMaxVars") .Attr("num_bits: int = 8") @@ -5541,20 +2716,7 @@ REGISTER_OP("FakeQuantWithMinMaxVars") TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 0, &unused)); TF_RETURN_IF_ERROR(c->WithRank(c->input(2), 0, &unused)); return Status::OK(); - }) - .Doc(R"doc( -Fake-quantize the 'inputs' tensor of type float via global float scalars `min` -and `max` to 'outputs' tensor of same shape as `inputs`. - -`[min; max]` define the clamping range for the `inputs` data. -`inputs` values are quantized into the quantization range (`[0; 2^num_bits - 1]` -when `narrow_range` is false and `[1; 2^num_bits - 1]` when it is true) and -then de-quantized and output as floats in `[min; max]` interval. -`num_bits` is the bitwidth of the quantization; between 2 and 8, inclusive. - -This operation has a gradient and thus allows for training `min` and `max` -values. -)doc"); + }); REGISTER_OP("FakeQuantWithMinMaxVarsGradient") .Attr("num_bits: int = 8") @@ -5580,22 +2742,7 @@ REGISTER_OP("FakeQuantWithMinMaxVarsGradient") c->set_output(1, min_max); c->set_output(2, min_max); return Status::OK(); - }) - .Doc(R"doc( -Compute gradients for a FakeQuantWithMinMaxVars operation. - -gradients: Backpropagated gradients above the FakeQuantWithMinMaxVars operation. -inputs: Values passed as inputs to the FakeQuantWithMinMaxVars operation. -min, max: Quantization interval, scalar floats. -num_bits: The bitwidth of the quantization; between 2 and 8, inclusive. -narrow_range: Whether to quantize into 2^num_bits - 1 distinct values. -backprops_wrt_input: Backpropagated gradients w.r.t. inputs: - `gradients * (inputs >= min && inputs <= max)`. -backprop_wrt_min: Backpropagated gradients w.r.t. min parameter: - `sum(gradients * (inputs < min))`. -backprop_wrt_max: Backpropagated gradients w.r.t. max parameter: - `sum(gradients * (inputs > max))`. -)doc"); + }); REGISTER_OP("FakeQuantWithMinMaxVarsPerChannel") .Attr("num_bits: int = 8") @@ -5617,21 +2764,7 @@ REGISTER_OP("FakeQuantWithMinMaxVarsPerChannel") c->set_output(0, input); return Status::OK(); - }) - .Doc(R"doc( -Fake-quantize the 'inputs' tensor of type float and one of the shapes: `[d]`, -`[b, d]` `[b, h, w, d]` via per-channel floats `min` and `max` of shape `[d]` -to 'outputs' tensor of same shape as `inputs`. - -`[min; max]` define the clamping range for the `inputs` data. -`inputs` values are quantized into the quantization range (`[0; 2^num_bits - 1]` -when `narrow_range` is false and `[1; 2^num_bits - 1]` when it is true) and -then de-quantized and output as floats in `[min; max]` interval. -`num_bits` is the bitwidth of the quantization; between 2 and 8, inclusive. - -This operation has a gradient and thus allows for training `min` and `max` -values. -)doc"); + }); REGISTER_OP("FakeQuantWithMinMaxVarsPerChannelGradient") .Attr("num_bits: int = 8") @@ -5660,25 +2793,7 @@ REGISTER_OP("FakeQuantWithMinMaxVarsPerChannelGradient") c->set_output(1, min_max); c->set_output(2, min_max); return Status::OK(); - }) - .Doc(R"doc( -Compute gradients for a FakeQuantWithMinMaxVarsPerChannel operation. - -gradients: Backpropagated gradients above the FakeQuantWithMinMaxVars operation, - shape one of: `[d]`, `[b, d]`, `[b, h, w, d]`. -inputs: Values passed as inputs to the FakeQuantWithMinMaxVars operation, shape - same as `gradients`. -min, max: Quantization interval, floats of shape `[d]`. -num_bits: The bitwidth of the quantization; between 2 and 8, inclusive. -narrow_range: Whether to quantize into 2^num_bits - 1 distinct values. -backprops_wrt_input: Backpropagated gradients w.r.t. inputs, shape same as - `inputs`: - `gradients * (inputs >= min && inputs <= max)`. -backprop_wrt_min: Backpropagated gradients w.r.t. min parameter, shape `[d]`: - `sum_per_d(gradients * (inputs < min))`. -backprop_wrt_max: Backpropagated gradients w.r.t. max parameter, shape `[d]`: - `sum_per_d(gradients * (inputs > max))`. -)doc"); + }); #ifdef INTEL_MKL REGISTER_OP("_MklConcat") |