.. _op_ai_onnx_GatherND: GatherND ======== - **Domain**: ``ai.onnx`` - **Since version**: 13 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 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-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** .. code-block:: 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** .. code-block:: 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** .. code-block:: 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** .. code-block:: 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** .. code-block:: 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(bfloat16), 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). Examples -------- **test_cc_gathernd_example_float32** .. code-block:: text Node: GatherND(data, indices) -> (output) Attributes: batch_dims = 0 .. code-block:: text Inputs: data: shape=(2, 2), dtype=float32 [[0., 1.], [2., 3.]] indices: shape=(2, 1), dtype=int64 [[1], [0]] Outputs: output: shape=(2, 2), dtype=float32 [[2., 3.], [0., 1.]] **test_cc_gathernd_example_int32** .. code-block:: text Node: GatherND(data, indices) -> (output) Attributes: batch_dims = 0 .. code-block:: text Inputs: data: shape=(2, 2), dtype=int32 [[0, 1], [2, 3]] indices: shape=(2, 2), dtype=int64 [[0, 0], [1, 1]] Outputs: output: shape=(2,), dtype=int32 [0, 3] **test_cc_gathernd_example_int32_batch_dim1** .. code-block:: text Node: GatherND(data, indices) -> (output) Attributes: batch_dims = 1 .. code-block:: text Inputs: data: shape=(2, 2, 2), dtype=int32 [[[0, 1], [2, 3]], [[4, 5], [6, 7]]] indices: shape=(2, 1), dtype=int64 [[1], [0]] Outputs: output: shape=(2, 2), dtype=int32 [[2, 3], [4, 5]] Differences with previous version (12) -------------------------------------- **SchemaDiff**: ``GatherND`` (domain ``'ai.onnx'``) * old version: 12 * new version: 13 * breaking: no **Type constraints:** * changed 'T': added types: ['tensor(bfloat16)'] **Documentation:** * line similarity: 0.56 (+35/-42 lines) .. code-block:: diff --- GatherND v12 +++ GatherND v13 @@ -39,54 +39,47 @@ This operator is the inverse of `ScatterND`. -`Example 1` +**Example 1** - batch_dims = 0 +``` +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] +``` - data = [[0,1],[2,3]] # data_shape = [2, 2] +**Example 2** - indices = [[0,0],[1,1]] # indices_shape = [2, 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] +``` - output = [0,3] # output_shape = [2] +**Example 3** -`Example 2` +``` +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] +``` - batch_dims = 0 +**Example 4** - data = [[0,1],[2,3]] # data_shape = [2, 2] +``` +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] +``` - indices = [[1],[0]] # indices_shape = [2, 1] +**Example 5** - 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] - - +``` +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] +``` Version History --------------- - :doc:`Version 12 ` - :doc:`Version 11 `