SliceScatter#
Versioned name: SliceScatter-15
Category: Data movement
Short description: Creates copy of data
tensor and applies elements from updates
using slicing parametrized by start
, stop
and step
over axes
dimensions.
Detailed description:
The operation produces a copy of data
tensor and updates it using values specified by updates
at specific slices parametrized by start
, stop
and step
values over corresponding axes
dimensions.
The output shape and type is the same as data
. Number of elements for start
, stop
, step
and axes
is required to be equal. Values in axes
are required to be unique.
Operator SliceScatter-15 is an equivalent to following NumPy snippet:
def slice_scatter_15(
data: np.ndarray,
updates: np.ndarray,
start: List[int],
stop: List[int],
step: List[int],
axes: Optional[List[int]] = None,
):
out = np.copy(data)
if axes is None:
axes = list(range(len(start)))
slice_list = [slice(None)] * data.ndim
for slice_start, slice_stop, slice_step, slice_axis in zip(start, stop, step, axes):
slice_list[slice_axis] = slice(slice_start, slice_stop, slice_step)
out[tuple(slice_list)] = updates
return out
Attributes: SliceScatter does not have attributes.
Inputs:
1:
data
tensor of arbitrary rankr
>= 1 and of type T. Required.2:
updates
- tensor of type T and same shape asdata
except axes set byaxes
where dimensions should be equal to the length of corresponding update slices. Required.3:
start
- 1D tensor of type T_IND.Defines the starting coordinate of the update slice in the
data
tensor ataxes
dimension. A negative index value represents counting elements from the end of that dimension. A value larger than the size of a dimension is silently clamped. Required.4:
stop
- 1D tensor of type T_IND.Defines the coordinate of the opposite vertex of the update slice, or where the update slice ends. Stop indexes are exclusive, which means values lying on the ending edge are not updated. A value larger than the size of a dimension is silently clamped. To create slice to the end of a dimension of unknown size
INT_MAX
may be used (orINT_MIN
if slicing backwards). Required.5:
step
- 1D tensor of type T_IND.Integer value that specifies the increment between each index used in slicing. Value cannot be
0
, negative value indicates slicing backwards. Required.6:
axes
- 1D tensor of type T_AXIS.Optional 1D tensor indicating which dimensions the values in
start
,stop
andstep
apply to. Negative value means counting dimensions from the end. The range is[-r, r - 1]
, wherer
is the rank of thedata
input tensor. Values are required to be unique. Default value:[0, 1, 2, ..., start.shape[0] - 1]
. Optional.
Number of elements in start
, stop
, step
, and axes
inputs are required to be equal.
Outputs:
1: tensor with shape equal to
data
tensor of the type T.
Types
T: any numeric type.
T_IND: any supported integer type.
T_AXIS: any supported integer type.
Example
Example 1: Fill slice over axis==0.
<layer ... type="SliceScatter">
<input>
<port id="0" precision="FP32"> <!-- data -->
<dim>2</dim>
<dim>5</dim> <!-- values: [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]] -->
</port>
<port id="1" precision="FP32"> <!-- updates -->
<dim>1</dim>
<dim>5</dim> <!-- values: [[10, 20, 30, 40, 50]] -->
</port>
<port id="2" precision="I32"> <!-- start -->
<dim>1</dim> <!-- values: [0] -->
</port>
<port id="3" precision="I32"> <!-- stop -->
<dim>1</dim> <!-- values: [1] -->
</port>
<port id="4" precision="I32"> <!-- step -->
<dim>1</dim> <!-- values: [1] -->
</port>
<port id="5" precision="I32"> <!-- axes -->
<dim>1</dim> <!-- values: [0] -->
</port>
</input>
<output>
<port id="6" precision="FP32">
<dim>2</dim>
<dim>5</dim> <!-- values: [[10, 20, 30, 40, 50], [5, 6, 7, 8, 9]] -->
</port>
</output>
</layer>
Example 2: Update every second value over axis==1, clamp values of start and stop.
<layer ... type="SliceScatter">
<input>
<port id="0" precision="FP32"> <!-- data -->
<dim>2</dim>
<dim>5</dim> <!-- values: [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]] -->
</port>
<port id="1" precision="FP32"> <!-- updates -->
<dim>2</dim>
<dim>3</dim> <!-- values: [[10, 20, 30], [40, 50, 60]] -->
</port>
<port id="2" precision="I32"> <!-- start -->
<dim>1</dim> <!-- values: [-25], silently clamped to 0 -->
</port>
<port id="3" precision="I32"> <!-- stop -->
<dim>1</dim> <!-- values: [25], silently clamped to 5 -->
</port>
<port id="4" precision="I32"> <!-- step -->
<dim>1</dim> <!-- values: [2] -->
</port>
<port id="5" precision="I32"> <!-- axes -->
<dim>1</dim> <!-- values: [1] -->
</port>
</input>
<output>
<port id="6" precision="FP32">
<dim>2</dim>
<dim>5</dim> <!-- values: [[10, 1, 20, 3, 30], [40, 6, 50, 8, 60]] -->
</port>
</output>
</layer>
Example 3: Update every second value over both axes with different slice starts.
<layer ... type="SliceScatter">
<input>
<port id="0" precision="FP32"> <!-- data -->
<dim>3</dim>
<dim>5</dim> <!-- values: [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [10, 11, 12, 13, 14]] -->
</port>
<port id="1" precision="FP32"> <!-- updates -->
<dim>2</dim>
<dim>2</dim> <!-- values: [[50, 60], [70, 80]] -->
</port>
<port id="2" precision="I32"> <!-- start -->
<dim>1</dim> <!-- values: [0, 1] -->
</port>
<port id="3" precision="I32"> <!-- stop -->
<dim>1</dim> <!-- values: [3, 5] -->
</port>
<port id="4" precision="I32"> <!-- step -->
<dim>1</dim> <!-- values: [2, 2] -->
</port>
</input>
<output>
<port id="5" precision="FP32">
<dim>3</dim>
<dim>5</dim> <!-- values: [[0, 50, 2, 60, 4], [5, 6, 7, 8, 9], [10, 70, 12, 80, 14]] -->
</port>
</output>
</layer>