BatchToSpace#

Versioned name: BatchToSpace-2

Category: Data movement

Short description: BatchToSpace operation permutes the batch dimension on a given input data into blocks in the spatial dimensions specified by block_shape input. The spatial dimensions are then optionally cropped according to crops_begin and crops_end inputs to produce the output.

Detailed description

BatchToSpace operation is equivalent to the following operation steps on the input data with shape [batch, D_1, D_2, ..., D_{N-1}] and block_shape, crops_begin, crops_end inputs with shape [N] to produce the output tensor y.

  1. Reshape data input to produce a tensor of shape [B1,,BN1,batch(B1××BN1),D1,D2,,DN1]

x=reshape(data,[B1,,BN1,batch(B1××BN1),D1,D2,,DN1])
  1. Permute dimensions of x to produce a tensor of shape [batch(B1××BN1),D1,B1,D2,B2,,DN1,BN1]

x=transpose(x,[N,N+1,0,N+2,1,,N+N1,N1])
  1. Reshape x to produce a tensor of shape [batch(B1××BN1),D1×B1,D2×B2,,DN1×BN1]

x=reshape(x,[batch(B1××BN1),D1×B1,D2×B2,,DN1×BN1])
  1. Crop the start and end of spatial dimensions of x according to crops_begin and crops_end inputs to produce the output y of shape:

[batch(B1××BN1),crop(D1×B1,CB1,CE1),crop(D2×B2,CB2,CE2),,crop(DN1×BN1,CBN1,CEN1)]

Where

  • Bi = block_shape[i]

  • B0 is expected to be 1

  • CBi = crops_begin[i]

  • CEi = crops_end[i]

  • CB0 and CE0 are expected to be 0

  • CBi+CEiDi×Bi

BatchToSpace operation is the reverse of SpaceToBatch operation.

Attributes: BatchToSpace operation has no attributes.

Inputs

  • 1: data - A tensor of type T and rank greater than or equal to 2. Layout is [batch, D_1, D_2 ... D_{N-1}] (number of batches, spatial axes). Required.

  • 2: block_shape - Specifies the block sizes of batch axis of data input which are moved to the corresponding spatial axes. A 1D tensor of type T_INT and shape [N]. All element values must be greater than or equal to 1. block_shape[0] is expected to be 1. Required.

  • 3: crops_begin - Specifies the amount to crop from the beginning along each axis of data input. A 1D tensor of type T_INT and shape [N]. All element values must be greater than or equal to 0. crops_begin[0] is expected to be 0. Required.

  • 4: crops_end - Specifies the amount to crop from the ending along each axis of data input. A 1D tensor of type T_INT and shape [N]. All element values must be greater than or equal to 0. crops_end[0] is expected to be 0. Required.

  • Note: N corresponds to the rank of data input.

  • Note: batch axis of data input must be evenly divisible by the cumulative product of block_shape elements.

  • Note: It is required that crops_begin[i] + crops_end[i] <= block_shape[i] * input_shape[i].

Outputs

  • 1: Permuted tensor of type T with the same rank as data input tensor, and shape [batch / (block_shape[0] * block_shape[1] * ... * block_shape[N - 1]), D_1 * block_shape[1] - crops_begin[1] - crops_end[1], D_2 * block_shape[2] - crops_begin[2] - crops_end[2], ..., D_{N - 1} * block_shape[N - 1] - crops_begin[N - 1] - crops_end[N - 1].

Types

  • T: any supported type.

  • T_INT: any supported integer type.

Examples

Example: 2D input tensor data

<layer type="BatchToSpace" ...>
    <input>
        <port id="0">       <!-- data -->
            <dim>10</dim>   <!-- batch -->
            <dim>2</dim>    <!-- spatial dimension 1 -->
        </port>
        <port id="1">       <!-- block_shape value: [1, 5] -->
            <dim>2</dim>
        </port>
        <port id="2">       <!-- crops_begin value: [0, 2] -->
            <dim>2</dim>
        </port>
        <port id="3">       <!-- crops_end value: [0, 0] -->
            <dim>2</dim>
        </port>
    </input>
    <output>
        <port id="3">
            <dim>2</dim>    <!-- data.shape[0] / (block_shape.shape[0] * block_shape.shape[1]) -->
            <dim>8</dim>    <!-- data.shape[1] * block_shape.shape[1] - crops_begin[1] - crops_end[1]-->
        </port>
    </output>
</layer>

Example: 5D input tensor data

<layer type="BatchToSpace" ...>
    <input>
        <port id="0">       <!-- data -->
            <dim>48</dim>   <!-- batch -->
            <dim>3</dim>    <!-- spatial dimension 1 -->
            <dim>3</dim>    <!-- spatial dimension 2 -->
            <dim>1</dim>    <!-- spatial dimension 3 -->
            <dim>3</dim>    <!-- spatial dimension 4 -->
        </port>
        <port id="1">       <!-- block_shape value: [1, 2, 4, 3, 1] -->
            <dim>5</dim>
        </port>
        <port id="2">       <!-- crops_begin value: [0, 0, 1, 0, 0] -->
            <dim>5</dim>
        </port>
        <port id="3">       <!-- crops_end value: [0, 0, 1, 0, 0] -->
            <dim>5</dim>
        </port>
    </input>
    <output>
        <port id="3">
            <dim>2</dim>    <!-- data.shape[0] / (block_shape.shape[0] * block_shape.shape[1] * ... * block_shape.shape[4]) -->
            <dim>6</dim>    <!-- data.shape[1] * block_shape.shape[1] - crops_begin[1] - crops_end[1]-->
            <dim>10</dim>   <!-- data.shape[2] * block_shape.shape[2] - crops_begin[2] - crops_end[2] -->
            <dim>3</dim>    <!-- data.shape[3] * block_shape.shape[3] - crops_begin[3] - crops_end[3] -->
            <dim>3</dim>    <!-- data.shape[4] * block_shape.shape[4] - crops_begin[4] - crops_end[4] -->
        </port>
    </output>
</layer>