Skip to content

Commit

Permalink
Add MaxUnpool op to ONNX. (#1494)
Browse files Browse the repository at this point in the history
* Add MaxUnpool op to ONNX.

* Fixed bug in shape inference for MaxUnpool.

* Removing whitespaces to fix CI failure.

* Updating stale files.

* Clarified doc about row-storage for input indices.
  • Loading branch information
spandantiwari authored and houseroad committed Oct 16, 2018
1 parent c4f7043 commit 96758c9
Show file tree
Hide file tree
Showing 15 changed files with 515 additions and 1 deletion.
63 changes: 63 additions & 0 deletions docs/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -8733,6 +8733,69 @@ This version of the operator has been available since version 9 of the default O
<dd>Constrain input and output types to float/int tensors.</dd>
</dl>

### <a name="MaxUnpool-9"></a>**MaxUnpool-9**</a>

MaxUnpool essentially computes the partial inverse of the MaxPool op.
The input information to this op is typically the the output information from a MaxPool op. The first
input tensor X is the tensor that needs to be unpooled, which is typically the pooled tensor (first output)
from MaxPool. The second input tensor, I, contains the indices to the (locally maximal) elements corrsponding
to the elements in the first input tensor X. Input tensor I is typically the second output of the MaxPool op.
The third (optional) input is a tensor that specifies the output size of the unpooling operation.

MaxUnpool is intended to do 'partial' inverse of the MaxPool op. 'Partial' because all the non-maximal
values from the original input to MaxPool are set to zero in the output of the MaxUnpool op. Pooling
the result of an unpooling operation should give back the original input to the unpooling op.

MaxUnpool can produce the same output size for several input sizes, which makes unpooling op ambiguous.
The third input argument, output_size, is meant to disambiguate the op and produce output tensor of
known/predictable size.

In addition to the inputs, MaxUnpool takes three attributes, namely kernel_shape, strides, and pads,
which define the exact unpooling op. The attributes typically have the same values as the corrsponding
pooling op that the unpooling op is trying to invert.

#### Version

This version of the operator has been available since version 9 of the default ONNX operator set.

#### Attributes

<dl>
<dt><tt>kernel_shape</tt> : list of ints (required)</dt>
<dd>The size of the kernel along each axis.</dd>
<dt><tt>pads</tt> : list of ints</dt>
<dd>Padding for the beginning and ending along each axis, it can take any value greater than or equal to 0. The value represent the number of pixels added to the beginning and end part of the corresponding axis. `pads` format should be as follow [x1_begin, x2_begin...x1_end, x2_end,...], where xi_begin the number of pixels added at the beginning of axis `i` and xi_end, the number of pixels added at the end of axis `i`. This attribute cannot be used simultaneously with auto_pad attribute. If not present, the padding defaults to 0 along start and end of each axis.</dd>
<dt><tt>strides</tt> : list of ints</dt>
<dd>Stride along each axis.</dd>
</dl>

#### Inputs (2 - 3)

<dl>
<dt><tt>X</tt> : T1</dt>
<dd>Input data tensor that has to be unpooled. This tensor is typically the first output of the MaxPool op.Dimensions for image case are (N x C x H x W), where N is the batch size, C is the number of channels, and H and W are the height and the width of the data. For non-image case, the dimensions are in the form of (N x C x D1 x D2 ... Dn), where N is the batch size. Optionally, if dimension denotation is in effect, the operation expects the input data tensor to arrive with the dimension denotation of [DATA_BATCH, DATA_CHANNEL, DATA_FEATURE, DATA_FEATURE ...].</dd>
<dt><tt>I</tt> : T2</dt>
<dd>Input data tensor containing the indices corresponding to elements in the first input tensor X.This tensor is typically the second output of the MaxPool op.Dimensions must be the same as input tensor X. The indices are linear, i.e. computed considering the tensor as flattened 1-D tensor, assuming row-major storage. Also, the linear indices should not consider padding. So the values in indices are in the range [0, N x C x D1 x ... x Dn).</dd>
<dt><tt>output_shape</tt> (optional) : T2</dt>
<dd>The shape of the output can be explicitly set which will cause pads values to be auto generated. If 'output_shape' is specified, 'pads' values are ignored.</dd>
</dl>

#### Outputs

<dl>
<dt><tt>output</tt> : T2</dt>
<dd>Output data tensor that contains the result of the unpooling.</dd>
</dl>

#### Type Constraints

<dl>
<dt><tt>T1</tt> : tensor(float16), tensor(float), tensor(double)</dt>
<dd>Constrain input and output types to float tensors.</dd>
<dt><tt>T2</tt> : tensor(int64)</dt>
<dd>Constrain index tensor to int64</dd>
</dl>

### <a name="PRelu-9"></a>**PRelu-9**</a>

PRelu takes input data (Tensor<T>) and slope tensor as input, and produces one
Expand Down
119 changes: 119 additions & 0 deletions docs/Operators.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
* <a href="#Max">Max</a>
* <a href="#MaxPool">MaxPool</a>
* <a href="#MaxRoiPool">MaxRoiPool</a>
* <a href="#MaxUnpool">MaxUnpool</a>
* <a href="#Mean">Mean</a>
* <a href="#Min">Min</a>
* <a href="#Mul">Mul</a>
Expand Down Expand Up @@ -6116,6 +6117,124 @@ This version of the operator has been available since version 1 of the default O
</dl>


### <a name="MaxUnpool"></a><a name="maxunpool">**MaxUnpool**</a>

MaxUnpool essentially computes the partial inverse of the MaxPool op.
The input information to this op is typically the the output information from a MaxPool op. The first
input tensor X is the tensor that needs to be unpooled, which is typically the pooled tensor (first output)
from MaxPool. The second input tensor, I, contains the indices to the (locally maximal) elements corrsponding
to the elements in the first input tensor X. Input tensor I is typically the second output of the MaxPool op.
The third (optional) input is a tensor that specifies the output size of the unpooling operation.

MaxUnpool is intended to do 'partial' inverse of the MaxPool op. 'Partial' because all the non-maximal
values from the original input to MaxPool are set to zero in the output of the MaxUnpool op. Pooling
the result of an unpooling operation should give back the original input to the unpooling op.

MaxUnpool can produce the same output size for several input sizes, which makes unpooling op ambiguous.
The third input argument, output_size, is meant to disambiguate the op and produce output tensor of
known/predictable size.

In addition to the inputs, MaxUnpool takes three attributes, namely kernel_shape, strides, and pads,
which define the exact unpooling op. The attributes typically have the same values as the corrsponding
pooling op that the unpooling op is trying to invert.

#### Version

This version of the operator has been available since version 9 of the default ONNX operator set.

#### Attributes

<dl>
<dt><tt>kernel_shape</tt> : list of ints (required)</dt>
<dd>The size of the kernel along each axis.</dd>
<dt><tt>pads</tt> : list of ints</dt>
<dd>Padding for the beginning and ending along each axis, it can take any value greater than or equal to 0. The value represent the number of pixels added to the beginning and end part of the corresponding axis. `pads` format should be as follow [x1_begin, x2_begin...x1_end, x2_end,...], where xi_begin the number of pixels added at the beginning of axis `i` and xi_end, the number of pixels added at the end of axis `i`. This attribute cannot be used simultaneously with auto_pad attribute. If not present, the padding defaults to 0 along start and end of each axis.</dd>
<dt><tt>strides</tt> : list of ints</dt>
<dd>Stride along each axis.</dd>
</dl>

#### Inputs (2 - 3)

<dl>
<dt><tt>X</tt> : T1</dt>
<dd>Input data tensor that has to be unpooled. This tensor is typically the first output of the MaxPool op.Dimensions for image case are (N x C x H x W), where N is the batch size, C is the number of channels, and H and W are the height and the width of the data. For non-image case, the dimensions are in the form of (N x C x D1 x D2 ... Dn), where N is the batch size. Optionally, if dimension denotation is in effect, the operation expects the input data tensor to arrive with the dimension denotation of [DATA_BATCH, DATA_CHANNEL, DATA_FEATURE, DATA_FEATURE ...].</dd>
<dt><tt>I</tt> : T2</dt>
<dd>Input data tensor containing the indices corresponding to elements in the first input tensor X.This tensor is typically the second output of the MaxPool op.Dimensions must be the same as input tensor X. The indices are linear, i.e. computed considering the tensor as flattened 1-D tensor, assuming row-major storage. Also, the linear indices should not consider padding. So the values in indices are in the range [0, N x C x D1 x ... x Dn).</dd>
<dt><tt>output_shape</tt> (optional) : T2</dt>
<dd>The shape of the output can be explicitly set which will cause pads values to be auto generated. If 'output_shape' is specified, 'pads' values are ignored.</dd>
</dl>

#### Outputs

<dl>
<dt><tt>output</tt> : T2</dt>
<dd>Output data tensor that contains the result of the unpooling.</dd>
</dl>

#### Type Constraints

<dl>
<dt><tt>T1</tt> : tensor(float16), tensor(float), tensor(double)</dt>
<dd>Constrain input and output types to float tensors.</dd>
<dt><tt>T2</tt> : tensor(int64)</dt>
<dd>Constrain index tensor to int64</dd>
</dl>


#### Examples

<details>
<summary>with_output_shape</summary>

```python
node = onnx.helper.make_node(
'MaxUnpool',
inputs=['xT', 'xI', 'output_shape'],
outputs=['y'],
kernel_shape=[2, 2],
strides=[2, 2]
)
xT = np.array([[[[5, 6],
[7, 8]]]], dtype=np.float32)
xI = np.array([[[[5, 7],
[13, 15]]]], dtype=np.int64)
output_shape = np.array((1, 1, 5, 5), dtype=np.int64)
y = np.array([[[[0, 0, 0, 0, 0],
[0, 5, 0, 6, 0],
[0, 0, 0, 0, 0],
[0, 7, 0, 8, 0],
[0, 0, 0, 0, 0]]]], dtype=np.float32)
expect(node, inputs=[xT, xI, output_shape], outputs=[y], name='test_maxunpool_export_with_output_shape')
```

</details>


<details>
<summary>without_output_shape</summary>

```python
node = onnx.helper.make_node(
'MaxUnpool',
inputs=['xT', 'xI'],
outputs=['y'],
kernel_shape=[2, 2],
strides=[2, 2]
)
xT = np.array([[[[1, 2],
[3, 4]]]], dtype=np.float32)
xI = np.array([[[[5, 7],
[13, 15]]]], dtype=np.int64)
y = np.array([[[[0, 0, 0, 0],
[0, 1, 0, 2],
[0, 0, 0, 0],
[0, 3, 0, 4]]]], dtype=np.float32)
expect(node, inputs=[xT, xI], outputs=[y], name='test_maxunpool_export_without_output_shape')
```

</details>


### <a name="Mean"></a><a name="mean">**Mean**</a>

Element-wise mean of each of the input tensors (with Numpy-style broadcasting support).
Expand Down
54 changes: 53 additions & 1 deletion docs/TestCoverage.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* [Overall Test Coverage](#overall-test-coverage)
# Node Test Coverage
## Summary
Node tests have covered 93/101 (92.08%, 5 generators excluded) common operators.
Node tests have covered 94/102 (92.16%, 5 generators excluded) common operators.

Node tests have covered 2/12 (16.67%, 0 generators excluded) experimental operators.

Expand Down Expand Up @@ -3247,6 +3247,58 @@ expect(node, inputs=[x], outputs=[y, z], name='test_maxpool_with_argmax_2d_preco
</details>


### MaxUnpool
There are 2 test cases, listed as following:
<details>
<summary>with_output_shape</summary>

```python
node = onnx.helper.make_node(
'MaxUnpool',
inputs=['xT', 'xI', 'output_shape'],
outputs=['y'],
kernel_shape=[2, 2],
strides=[2, 2]
)
xT = np.array([[[[5, 6],
[7, 8]]]], dtype=np.float32)
xI = np.array([[[[5, 7],
[13, 15]]]], dtype=np.int64)
output_shape = np.array((1, 1, 5, 5), dtype=np.int64)
y = np.array([[[[0, 0, 0, 0, 0],
[0, 5, 0, 6, 0],
[0, 0, 0, 0, 0],
[0, 7, 0, 8, 0],
[0, 0, 0, 0, 0]]]], dtype=np.float32)
expect(node, inputs=[xT, xI, output_shape], outputs=[y], name='test_maxunpool_export_with_output_shape')
```

</details>
<details>
<summary>without_output_shape</summary>

```python
node = onnx.helper.make_node(
'MaxUnpool',
inputs=['xT', 'xI'],
outputs=['y'],
kernel_shape=[2, 2],
strides=[2, 2]
)
xT = np.array([[[[1, 2],
[3, 4]]]], dtype=np.float32)
xI = np.array([[[[5, 7],
[13, 15]]]], dtype=np.int64)
y = np.array([[[[0, 0, 0, 0],
[0, 1, 0, 2],
[0, 0, 0, 0],
[0, 3, 0, 4]]]], dtype=np.float32)
expect(node, inputs=[xT, xI], outputs=[y], name='test_maxunpool_export_without_output_shape')
```

</details>


### Mean
There are 1 test cases, listed as following:
<details>
Expand Down
53 changes: 53 additions & 0 deletions onnx/backend/test/case/node/maxunpool.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

import numpy as np # type: ignore

import onnx
from ..base import Base
from . import expect


class MaxUnpool(Base):

@staticmethod
def export_without_output_shape(): # type: () -> None
node = onnx.helper.make_node(
'MaxUnpool',
inputs=['xT', 'xI'],
outputs=['y'],
kernel_shape=[2, 2],
strides=[2, 2]
)
xT = np.array([[[[1, 2],
[3, 4]]]], dtype=np.float32)
xI = np.array([[[[5, 7],
[13, 15]]]], dtype=np.int64)
y = np.array([[[[0, 0, 0, 0],
[0, 1, 0, 2],
[0, 0, 0, 0],
[0, 3, 0, 4]]]], dtype=np.float32)
expect(node, inputs=[xT, xI], outputs=[y], name='test_maxunpool_export_without_output_shape')

@staticmethod
def export_with_output_shape(): # type: () -> None
node = onnx.helper.make_node(
'MaxUnpool',
inputs=['xT', 'xI', 'output_shape'],
outputs=['y'],
kernel_shape=[2, 2],
strides=[2, 2]
)
xT = np.array([[[[5, 6],
[7, 8]]]], dtype=np.float32)
xI = np.array([[[[5, 7],
[13, 15]]]], dtype=np.int64)
output_shape = np.array((1, 1, 5, 5), dtype=np.int64)
y = np.array([[[[0, 0, 0, 0, 0],
[0, 5, 0, 6, 0],
[0, 0, 0, 0, 0],
[0, 7, 0, 8, 0],
[0, 0, 0, 0, 0]]]], dtype=np.float32)
expect(node, inputs=[xT, xI, output_shape], outputs=[y], name='test_maxunpool_export_with_output_shape')
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
 backend-test:�
M
xT
xI
output_shapey" MaxUnpool*
kernel_shape@@�*
strides@@�'test_maxunpool_export_with_output_shapeZ
xT




Z
xI




Z
output_shape


b
y




B
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
 backend-test:�
?
xT
xIy" MaxUnpool*
kernel_shape@@�*
strides@@�*test_maxunpool_export_without_output_shapeZ
xT




Z
xI




b
y




B
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading

0 comments on commit 96758c9

Please sign in to comment.