GatherND - version 12#

This page documents version 12 of operator GatherND. See GatherND for the latest version (since version 13).

  • Domain: ai.onnx

  • Since version: 12

Given data tensor of rank r >= 1, indices tensor of rank q >= 1, and batch_dims integer b, this operator gathers slices of data into an output tensor of rank q + r - indices_shape[-1] - 1 - b.

indices is an q-dimensional integer tensor, best thought of as a (q-1)-dimensional tensor of index-tuples into data, where each element defines a slice of data

batch_dims (denoted as b) is an integer indicating the number of batch dimensions, i.e the leading b number of dimensions of data tensor and indices are representing the batches, and the gather starts from the b+1 dimension.

Some salient points about the inputs’ rank and shape:

  1. r >= 1 and q >= 1 are to be honored. There is no dependency condition to be met between ranks r and q

  2. The first b dimensions of the shape of indices tensor and data tensor must be equal.

  3. b r-b` => error condition

  1. If indices_shape[-1] == r-b, since the rank of indices is q, indices can be thought of as N (q-b-1)-dimensional tensors containing 1-D tensors of dimension r-b, where N is an integer equals to the product of 1 and all the elements in the batch dimensions of the indices_shape. Let us think of each such r-b ranked tensor as indices_slice. Each *scalar value* corresponding to data[0:b-1,indices_slice] is filled into the corresponding location of the (q-b-1)-dimensional tensor to form the output tensor (Example 1 below)

  2. If indices_shape[-1] < r-b, since the rank of indices is q, indices can be thought of as N (q-b-1)-dimensional tensor containing 1-D tensors of dimension < r-b. Let us think of each such tensors as indices_slice. Each *tensor slice* corresponding to data[0:b-1, indices_slice , :] is filled into the corresponding location of the (q-b-1)-dimensional tensor to form the output tensor (Examples 2, 3, 4 and 5 below)

This operator is the inverse of ScatterND.

Example 1

batch_dims = 0

data    = [[0,1],[2,3]]   # data_shape = [2, 2]

indices = [[0,0],[1,1]]   # indices_shape = [2, 2]

output  = [0,3]           # output_shape = [2]

Example 2

batch_dims = 0

data    = [[0,1],[2,3]]  # data_shape = [2, 2]

indices = [[1],[0]]      # indices_shape = [2, 1]

output  = [[2,3],[0,1]]  # output_shape = [2, 2]

Example 3

batch_dims = 0

data    = [[[0,1],[2,3]],[[4,5],[6,7]]] # data_shape = [2, 2, 2]

indices = [[0,1],[1,0]]                 # indices_shape = [2, 2]

output  = [[2,3],[4,5]]                 # output_shape = [2, 2]

Example 4

batch_dims = 0

data    = [[[0,1],[2,3]],[[4,5],[6,7]]] # data_shape = [2, 2, 2]

indices = [[[0,1]],[[1,0]]]             # indices_shape = [2, 1, 2]

output  = [[[2,3]],[[4,5]]]             # output_shape = [2, 1, 2]

Example 5

batch_dims = 1

data    = [[[0,1],[2,3]],[[4,5],[6,7]]] # data_shape = [2, 2, 2]

indices = [[1],[0]]             # indices_shape = [2, 1]

output  = [[2,3],[4,5]]             # output_shape = [2, 2]

Inputs

  • data (T): Tensor of rank r >= 1.

  • indices (tensor(int64)): Tensor of rank q >= 1. All index values are expected to be within bounds [-s, s-1] along axis of size s. It is an error if any of the index values are out of bounds.

Outputs

  • output (T): Tensor of rank q + r - indices_shape[-1] - 1.

Attributes

  • batch_dims (int): The number of batch dimensions. The gather of indexing starts from dimension of data[batch_dims:]

Type Constraints

  • T: Constrain input and output types to any tensor type. Allowed types: tensor(bool), tensor(complex128), tensor(complex64), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8).

Differences with previous version (11)#

SchemaDiff: GatherND (domain 'ai.onnx')

  • old version: 11

  • new version: 12

  • breaking: no

Attributes:

  • added ‘batch_dims’: type=INT; required=False; default=0

Documentation:

  • line similarity: 0.67 (+39/-13 lines)

--- GatherND v11
+++ GatherND v12
@@ -1,38 +1,47 @@

-Given `data` tensor of rank `r` >= 1, and `indices` tensor of rank `q` >= 1, this operator gathers
-slices of `data` into an output tensor of rank `q + r - indices_shape[-1] - 1`.
+Given `data` tensor of rank `r` >= 1, `indices` tensor of rank `q` >= 1, and `batch_dims` integer `b`, this operator gathers
+slices of `data` into an output tensor of rank `q + r - indices_shape[-1] - 1 - b`.

 `indices` is an q-dimensional integer tensor, best thought of as a `(q-1)`-dimensional tensor of index-tuples into `data`,
 where each element defines a slice of `data`
+
+`batch_dims` (denoted as `b`) is an integer indicating the number of batch dimensions, i.e the leading `b` number of dimensions of
+`data` tensor and `indices` are representing the batches, and the gather starts from the `b+1` dimension.

 Some salient points about the inputs' rank and shape:

 1) r >= 1 and q >= 1 are to be honored. There is no dependency condition to be met between ranks `r` and `q`

-2) The `indices_shape[-1]` should have a value between 1 (inclusive) and rank `r` (inclusive)
+2) The first `b` dimensions of the shape of `indices` tensor and `data` tensor must be equal.

-3) All values in `indices` are expected to be within bounds [-s, s-1] along axis of size `s` (i.e.) `-data_shape[i] <= indices[...,i] <= data_shape[i] - 1`.
+3) b < min(q, r) is to be honored.
+
+4) The `indices_shape[-1]` should have a value between 1 (inclusive) and rank `r-b` (inclusive)
+
+5) All values in `indices` are expected to be within bounds [-s, s-1] along axis of size `s` (i.e.) `-data_shape[i] <= indices[...,i] <= data_shape[i] - 1`.
    It is an error if any of the index values are out of bounds.

 The output is computed as follows:

 The output tensor is obtained by mapping each index-tuple in the `indices` tensor to the corresponding slice of the input `data`.

-1) If `indices_shape[-1] > r` => error condition
+1) If `indices_shape[-1] > r-b` => error condition

-2) If `indices_shape[-1] == r`, since the rank of `indices` is `q`, `indices` can be thought of as a `(q-1)`-dimensional tensor
-   containing 1-D tensors of dimension `r`. Let us think of each such `r` ranked tensor as `indices_slice`.
-   Each *scalar value* corresponding to `data[indices_slice]` is filled into the corresponding location of the `(q-1)`-dimensional tensor
-   to form the `output` tensor (Example 1 below)
+2) If `indices_shape[-1] == r-b`, since the rank of `indices` is `q`, `indices` can be thought of as `N` `(q-b-1)`-dimensional tensors
+   containing 1-D tensors of dimension `r-b`, where `N` is an integer equals to the product of 1 and all the elements in the batch dimensions
+   of the indices_shape. Let us think of each such `r-b` ranked tensor as `indices_slice`. Each *scalar value* corresponding to `data[0:b-1,indices_slice]`
+   is filled into the corresponding location of the `(q-b-1)`-dimensional tensor to form the `output` tensor (Example 1 below)

-3) If `indices_shape[-1] < r`, since the rank of `indices` is `q`, `indices` can be thought of as a `(q-1)`-dimensional tensor
-   containing 1-D tensors of dimension `< r`. Let us think of each such tensors as `indices_slice`.
-   Each *tensor slice* corresponding to `data[indices_slice , :]` is filled into the corresponding location of the `(q-1)`-dimensional tensor
-   to form the `output` tensor (Examples 2, 3, and 4 below)
+3) If `indices_shape[-1] < r-b`, since the rank of `indices` is `q`, `indices` can be thought of as `N` `(q-b-1)`-dimensional tensor
+   containing 1-D tensors of dimension `< r-b`. Let us think of each such tensors as `indices_slice`. Each *tensor slice* corresponding
+   to `data[0:b-1, indices_slice , :]` is filled into the corresponding location of the `(q-b-1)`-dimensional tensor
+   to form the `output` tensor (Examples 2, 3, 4 and 5 below)

 This operator is the inverse of `ScatterND`.

 `Example 1`
+
+  batch_dims = 0

   data    = [[0,1],[2,3]]   # data_shape = [2, 2]

@@ -42,6 +51,8 @@

 `Example 2`

+  batch_dims = 0
+
   data    = [[0,1],[2,3]]  # data_shape = [2, 2]

   indices = [[1],[0]]      # indices_shape = [2, 1]
@@ -49,6 +60,8 @@
   output  = [[2,3],[0,1]]  # output_shape = [2, 2]

 `Example 3`
+
+  batch_dims = 0

   data    = [[[0,1],[2,3]],[[4,5],[6,7]]] # data_shape = [2, 2, 2]

@@ -58,9 +71,22 @@

 `Example 4`

+  batch_dims = 0
+
   data    = [[[0,1],[2,3]],[[4,5],[6,7]]] # data_shape = [2, 2, 2]

   indices = [[[0,1]],[[1,0]]]             # indices_shape = [2, 1, 2]

   output  = [[[2,3]],[[4,5]]]             # output_shape = [2, 1, 2]

+`Example 5`
+
+  batch_dims = 1
+
+  data    = [[[0,1],[2,3]],[[4,5],[6,7]]] # data_shape = [2, 2, 2]
+
+  indices = [[1],[0]]             # indices_shape = [2, 1]
+
+  output  = [[2,3],[4,5]]             # output_shape = [2, 2]
+
+