Skip to content

Commit

Permalink
Update Clip in opset 11 to support min/max as inputs instead of attri…
Browse files Browse the repository at this point in the history
…butes (#2096)

Update Clip in opset 11 to support min/max as inputs instead of attributes.
  • Loading branch information
BowenBao authored and ebarsoum committed Aug 7, 2019
1 parent a25e138 commit 4eb737c
Show file tree
Hide file tree
Showing 27 changed files with 176 additions and 95 deletions.
35 changes: 35 additions & 0 deletions docs/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -10335,6 +10335,41 @@ This version of the operator has been available since version 11 of the default
<dd>Constrain input and output types to integer tensors.</dd>
</dl>

### <a name="Clip-11"></a>**Clip-11**</a>

Clip operator limits the given input within an interval. The interval is
specified by the inputs 'min' and 'max'. They default to
numeric_limits::lowest() and numeric_limits::max(), respectively.

#### Version

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

#### Inputs (1 - 3)

<dl>
<dt><tt>input</tt> : T</dt>
<dd>Input tensor whose elements to be clipped</dd>
<dt><tt>min</tt> (optional) : T</dt>
<dd>Minimum value, under which element is replaced by min. It must be a scalar(tensor of empty shape).</dd>
<dt><tt>max</tt> (optional) : T</dt>
<dd>Maximum value, above which element is replaced by max. It must be a scalar(tensor of empty shape).</dd>
</dl>

#### Outputs

<dl>
<dt><tt>output</tt> : T</dt>
<dd>Output tensor with clipped input elements</dd>
</dl>

#### Type Constraints

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

### <a name="CumSum-11"></a>**CumSum-11**</a>

Performs cumulative sum of the input elements along the given axis.
Expand Down
71 changes: 35 additions & 36 deletions docs/Operators.md
Original file line number Diff line number Diff line change
Expand Up @@ -2029,29 +2029,24 @@ expect(node, inputs=[x], outputs=[y],
### <a name="Clip"></a><a name="clip">**Clip**</a>

Clip operator limits the given input within an interval. The interval is
specified with arguments 'min' and 'max'. They default to
numeric_limits::lowest() and numeric_limits::max() respectively.
specified by the inputs 'min' and 'max'. They default to
numeric_limits::lowest() and numeric_limits::max(), respectively.

#### Version

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

Other versions of this operator: <a href="Changelog.md#Clip-1">Clip-1</a>
Other versions of this operator: <a href="Changelog.md#Clip-1">Clip-1</a>, <a href="Changelog.md#Clip-6">Clip-6</a>

#### Attributes

<dl>
<dt><tt>max</tt> : float (default is 3.4028234663852886e+38)</dt>
<dd>Maximum value, above which element is replaced by max</dd>
<dt><tt>min</tt> : float (default is -3.4028234663852886e+38)</dt>
<dd>Minimum value, under which element is replaced by min</dd>
</dl>

#### Inputs
#### Inputs (1 - 3)

<dl>
<dt><tt>input</tt> : T</dt>
<dd>Input tensor whose elements to be clipped</dd>
<dt><tt>min</tt> (optional) : T</dt>
<dd>Minimum value, under which element is replaced by min. It must be a scalar(tensor of empty shape).</dd>
<dt><tt>max</tt> (optional) : T</dt>
<dd>Maximum value, above which element is replaced by max. It must be a scalar(tensor of empty shape).</dd>
</dl>

#### Outputs
Expand All @@ -2077,42 +2072,43 @@ Other versions of this operator: <a href="Changelog.md#Clip-1">Clip-1</a>
```python
node = onnx.helper.make_node(
'Clip',
inputs=['x'],
inputs=['x', 'min', 'max'],
outputs=['y'],
min=-1.0,
max=1.0
)

x = np.array([-2, 0, 2]).astype(np.float32)
y = np.clip(x, -1, 1) # expected output [-1., 0., 1.]
expect(node, inputs=[x], outputs=[y],
min_val = np.float32(-1)
max_val = np.float32(1)
y = np.clip(x, min_val, max_val) # expected output [-1., 0., 1.]
expect(node, inputs=[x, min_val, max_val], outputs=[y],
name='test_clip_example')

x = np.random.randn(3, 4, 5).astype(np.float32)
y = np.clip(x, -1.0, 1.0)
expect(node, inputs=[x], outputs=[y],
y = np.clip(x, min_val, max_val)
expect(node, inputs=[x, min_val, max_val], outputs=[y],
name='test_clip')
node = onnx.helper.make_node(
'Clip',
inputs=['x'],
inputs=['x', 'min', 'max'],
outputs=['y'],
min=-5.0,
max=5.0,
)

min_val = np.float32(-5)
max_val = np.float32(5)

x = np.array([-1, 0, 1]).astype(np.float32)
y = np.array([-1, 0, 1]).astype(np.float32)
expect(node, inputs=[x], outputs=[y],
expect(node, inputs=[x, min_val, max_val], outputs=[y],
name='test_clip_inbounds')

x = np.array([-6, 0, 6]).astype(np.float32)
y = np.array([-5, 0, 5]).astype(np.float32)
expect(node, inputs=[x], outputs=[y],
expect(node, inputs=[x, min_val, max_val], outputs=[y],
name='test_clip_outbounds')

x = np.array([-1, 0, 6]).astype(np.float32)
y = np.array([-1, 0, 5]).astype(np.float32)
expect(node, inputs=[x], outputs=[y],
expect(node, inputs=[x, min_val, max_val], outputs=[y],
name='test_clip_splitbounds')
```

Expand All @@ -2125,28 +2121,31 @@ expect(node, inputs=[x], outputs=[y],
```python
node = onnx.helper.make_node(
'Clip',
inputs=['x'],
inputs=['x', 'min'],
outputs=['y'],
min=0.0
)
min_val = np.float32(0)
x = np.random.randn(3, 4, 5).astype(np.float32)
y = np.clip(x, 0.0, np.inf)
expect(node, inputs=[x], outputs=[y],
y = np.clip(x, min_val, np.inf)
expect(node, inputs=[x, min_val], outputs=[y],
name='test_clip_default_min')

no_min = "" # optional input, not supplied
node = onnx.helper.make_node(
'Clip',
inputs=['x'],
inputs=['x', no_min, 'max'],
outputs=['y'],
max=0.0
)
max_val = np.float32(0)
x = np.random.randn(3, 4, 5).astype(np.float32)
y = np.clip(x, -np.inf, 0.0)
expect(node, inputs=[x], outputs=[y],
y = np.clip(x, -np.inf, max_val)
expect(node, inputs=[x, max_val], outputs=[y],
name='test_clip_default_max')

no_max = "" # optional input, not supplied
node = onnx.helper.make_node(
'Clip',
inputs=['x'],
inputs=['x', no_min, no_max],
outputs=['y'],
)

Expand Down
48 changes: 26 additions & 22 deletions docs/TestCoverage.md
Original file line number Diff line number Diff line change
Expand Up @@ -1167,42 +1167,43 @@ There are 2 test cases, listed as following:
```python
node = onnx.helper.make_node(
'Clip',
inputs=['x'],
inputs=['x', 'min', 'max'],
outputs=['y'],
min=-1.0,
max=1.0
)

x = np.array([-2, 0, 2]).astype(np.float32)
y = np.clip(x, -1, 1) # expected output [-1., 0., 1.]
expect(node, inputs=[x], outputs=[y],
min_val = np.float32(-1)
max_val = np.float32(1)
y = np.clip(x, min_val, max_val) # expected output [-1., 0., 1.]
expect(node, inputs=[x, min_val, max_val], outputs=[y],
name='test_clip_example')

x = np.random.randn(3, 4, 5).astype(np.float32)
y = np.clip(x, -1.0, 1.0)
expect(node, inputs=[x], outputs=[y],
y = np.clip(x, min_val, max_val)
expect(node, inputs=[x, min_val, max_val], outputs=[y],
name='test_clip')
node = onnx.helper.make_node(
'Clip',
inputs=['x'],
inputs=['x', 'min', 'max'],
outputs=['y'],
min=-5.0,
max=5.0,
)

min_val = np.float32(-5)
max_val = np.float32(5)

x = np.array([-1, 0, 1]).astype(np.float32)
y = np.array([-1, 0, 1]).astype(np.float32)
expect(node, inputs=[x], outputs=[y],
expect(node, inputs=[x, min_val, max_val], outputs=[y],
name='test_clip_inbounds')

x = np.array([-6, 0, 6]).astype(np.float32)
y = np.array([-5, 0, 5]).astype(np.float32)
expect(node, inputs=[x], outputs=[y],
expect(node, inputs=[x, min_val, max_val], outputs=[y],
name='test_clip_outbounds')

x = np.array([-1, 0, 6]).astype(np.float32)
y = np.array([-1, 0, 5]).astype(np.float32)
expect(node, inputs=[x], outputs=[y],
expect(node, inputs=[x, min_val, max_val], outputs=[y],
name='test_clip_splitbounds')
```

Expand All @@ -1213,28 +1214,31 @@ expect(node, inputs=[x], outputs=[y],
```python
node = onnx.helper.make_node(
'Clip',
inputs=['x'],
inputs=['x', 'min'],
outputs=['y'],
min=0.0
)
min_val = np.float32(0)
x = np.random.randn(3, 4, 5).astype(np.float32)
y = np.clip(x, 0.0, np.inf)
expect(node, inputs=[x], outputs=[y],
y = np.clip(x, min_val, np.inf)
expect(node, inputs=[x, min_val], outputs=[y],
name='test_clip_default_min')

no_min = "" # optional input, not supplied
node = onnx.helper.make_node(
'Clip',
inputs=['x'],
inputs=['x', no_min, 'max'],
outputs=['y'],
max=0.0
)
max_val = np.float32(0)
x = np.random.randn(3, 4, 5).astype(np.float32)
y = np.clip(x, -np.inf, 0.0)
expect(node, inputs=[x], outputs=[y],
y = np.clip(x, -np.inf, max_val)
expect(node, inputs=[x, max_val], outputs=[y],
name='test_clip_default_max')

no_max = "" # optional input, not supplied
node = onnx.helper.make_node(
'Clip',
inputs=['x'],
inputs=['x', no_min, no_max],
outputs=['y'],
)

Expand Down
48 changes: 26 additions & 22 deletions onnx/backend/test/case/node/clip.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,70 +16,74 @@ class Clip(Base):
def export(): # type: () -> None
node = onnx.helper.make_node(
'Clip',
inputs=['x'],
inputs=['x', 'min', 'max'],
outputs=['y'],
min=-1.0,
max=1.0
)

x = np.array([-2, 0, 2]).astype(np.float32)
y = np.clip(x, -1, 1) # expected output [-1., 0., 1.]
expect(node, inputs=[x], outputs=[y],
min_val = np.float32(-1)
max_val = np.float32(1)
y = np.clip(x, min_val, max_val) # expected output [-1., 0., 1.]
expect(node, inputs=[x, min_val, max_val], outputs=[y],
name='test_clip_example')

x = np.random.randn(3, 4, 5).astype(np.float32)
y = np.clip(x, -1.0, 1.0)
expect(node, inputs=[x], outputs=[y],
y = np.clip(x, min_val, max_val)
expect(node, inputs=[x, min_val, max_val], outputs=[y],
name='test_clip')
node = onnx.helper.make_node(
'Clip',
inputs=['x'],
inputs=['x', 'min', 'max'],
outputs=['y'],
min=-5.0,
max=5.0,
)

min_val = np.float32(-5)
max_val = np.float32(5)

x = np.array([-1, 0, 1]).astype(np.float32)
y = np.array([-1, 0, 1]).astype(np.float32)
expect(node, inputs=[x], outputs=[y],
expect(node, inputs=[x, min_val, max_val], outputs=[y],
name='test_clip_inbounds')

x = np.array([-6, 0, 6]).astype(np.float32)
y = np.array([-5, 0, 5]).astype(np.float32)
expect(node, inputs=[x], outputs=[y],
expect(node, inputs=[x, min_val, max_val], outputs=[y],
name='test_clip_outbounds')

x = np.array([-1, 0, 6]).astype(np.float32)
y = np.array([-1, 0, 5]).astype(np.float32)
expect(node, inputs=[x], outputs=[y],
expect(node, inputs=[x, min_val, max_val], outputs=[y],
name='test_clip_splitbounds')

@staticmethod
def export_clip_default(): # type: () -> None
node = onnx.helper.make_node(
'Clip',
inputs=['x'],
inputs=['x', 'min'],
outputs=['y'],
min=0.0
)
min_val = np.float32(0)
x = np.random.randn(3, 4, 5).astype(np.float32)
y = np.clip(x, 0.0, np.inf)
expect(node, inputs=[x], outputs=[y],
y = np.clip(x, min_val, np.inf)
expect(node, inputs=[x, min_val], outputs=[y],
name='test_clip_default_min')

no_min = "" # optional input, not supplied
node = onnx.helper.make_node(
'Clip',
inputs=['x'],
inputs=['x', no_min, 'max'],
outputs=['y'],
max=0.0
)
max_val = np.float32(0)
x = np.random.randn(3, 4, 5).astype(np.float32)
y = np.clip(x, -np.inf, 0.0)
expect(node, inputs=[x], outputs=[y],
y = np.clip(x, -np.inf, max_val)
expect(node, inputs=[x, max_val], outputs=[y],
name='test_clip_default_max')

no_max = "" # optional input, not supplied
node = onnx.helper.make_node(
'Clip',
inputs=['x'],
inputs=['x', no_min, no_max],
outputs=['y'],
)

Expand Down
Binary file modified onnx/backend/test/data/node/test_clip/model.onnx
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified onnx/backend/test/data/node/test_clip_default_max/model.onnx
Binary file not shown.
Binary file not shown.
Binary file modified onnx/backend/test/data/node/test_clip_default_min/model.onnx
Binary file not shown.
Binary file not shown.
Binary file modified onnx/backend/test/data/node/test_clip_example/model.onnx
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified onnx/backend/test/data/node/test_clip_inbounds/model.onnx
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified onnx/backend/test/data/node/test_clip_outbounds/model.onnx
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified onnx/backend/test/data/node/test_clip_splitbounds/model.onnx
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading

0 comments on commit 4eb737c

Please sign in to comment.