Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add squeeze v15 op spec #26989

Merged
merged 14 commits into from
Nov 4, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ Table of Contents
* :doc:`Split <../operation-specs/movement/split-1>`
* :doc:`Sqrt <../operation-specs/arithmetic/sqrt-1>`
* :doc:`SquaredDifference <../operation-specs/arithmetic/squared-difference-1>`
* :doc:`Squeeze <../operation-specs/shape/squeeze-1>`
* :doc:`Squeeze <../operation-specs/shape/squeeze-15>`
* :doc:`STFT <../operation-specs/signals/stft-15>`
* :doc:`StridedSlice <../operation-specs/movement/strided-slice-1>`
* :doc:`StringTensorPack <../operation-specs/type/string-tensor-pack-15>`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ Operation Specifications
Sqrt-1 <operation-specs/arithmetic/sqrt-1>
SquaredDifference-1 <operation-specs/arithmetic/squared-difference-1>
Squeeze-1 <operation-specs/shape/squeeze-1>
Squeeze-15 <operation-specs/shape/squeeze-15>
STFT-15 <operation-specs/signals/stft-15>
StridedSlice-1 <operation-specs/movement/strided-slice-1>
StringTensorPack-15 <operation-specs/type/string-tensor-pack-15>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
Squeeze
=======

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we require such version? Is there similar operation in frameworks like PyTorch, TF, ONNX? Can we refer a link to such operation?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's needed for alignment with torch, more details can be found in the internal ticket: 143585.


.. meta::
:description: Learn about Squeeze-15 - a shape manipulation operation, which
can be performed on one required and one optional input tensor.

**Versioned name**: *Squeeze-15*

**Category**: *Shape manipulation*

**Short description**: *Squeeze* removes dimensions equal to 1 from the first input tensor.

**Detailed description**: *Squeeze* can be used with or without the second input tensor.

* If only the first input is provided, every dimension that is equal to 1 will be removed from it.
* With the second input provided, each value is an index of a dimension from the first tensor that is to be removed. Specified dimension should be equal to 1, otherwise it will be ignored and copied as is.
Dimension indices can be specified directly, or by negative indices (counting dimensions from the end).

.. note::

- If index of the dimension to squeeze is provided as a constant input and it points to a dynamic dimension that might be `1`, and the *allow_axis_skip* attribute is ``false``, then the dimension is considered as squeezable. Therefore the rank of the output shape will be reduced, but not dynamic. If dynamic rank is expected for such case, *allow_axis_skip* attribute need to be set to ``true``.
- If the input with indices is empty or not provided, dynamic dimension compatible with `1` leads to dynamic rank of the output shape.


**Attributes**:

* *allow_axis_skip*
mmikolajcz marked this conversation as resolved.
Show resolved Hide resolved

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we expect exception raised when allow_axis_skip=False and given axis corresponds to dimension that is not squeezable?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be implemented to throw, but the intention is to keep the v0::Squeeze compatible behavior when allow_axis_skip=False.
For model enablement the v0::Squeeze has been already updated to be not so strict for static dimensions, but it was not possible to update the all dynamic cases and keep backward compatibility. Especially previous Squeeze logic assumes that dynamic dim with 1 in range like {-1} or {1-2} is squeezable, and produces static rank.
While the recent request to align with torch is to produce dynamic rank for such case.
In fact allow_axis_skip=False can be understood like assume_dynamic_dim_is_squeezable=True.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks that this mode is also helpful for TF Squeeze op (https://www.tensorflow.org/api_docs/python/tf/raw_ops/Squeeze) when axis = []. For such case, I can compute axes for our Squeeze using ShapeOf and Range ops and set this mode allow_axis_skip=False. This way it will squeeze all dims that are possible to squeeze. So we can squeeze dimension during both conversion/loading and inference, right?

* **Description**: If true, shape inference results in a dynamic rank if selected axis has value 1 in its dimension range.
* **Range of values**: ``false`` or ``true``
* **Type**: ``boolean``
* **Required**: *no*
mmikolajcz marked this conversation as resolved.
Show resolved Hide resolved
* **Default value**: ``false``

**Inputs**:

* **1**: Multidimensional input tensor of type *T*. **Required.**

* **2**: Scalar or 1D tensor of type *T_INT* with indices of dimensions to squeeze. Values could be negative (have to be from range ``[-R, R-1]``, where ``R`` is the rank of the first input). **Optional.**

**Outputs**:

* **1**: Tensor with squeezed values of type *T*.

**Types**

* *T*: any numeric type.

* *T_INT*: any supported integer type.

**Example**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add attribute value to example IR. Consider adding additional examples that will show differences between attribute values and maybe examples of dynamic rank or ignored non-1 dimensions

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


*Example 1: squeeze 4D tensor to a 2D tensor*

.. code-block:: xml
:force:

<layer ... type="Squeeze" version="opset15">
<data allow_axis_skip="false"/>
<input>
<port id="0">
<dim>1</dim>
<dim>3</dim>
<dim>1</dim>
<dim>2</dim>
</port>
</input>
<input>
<port id="1">
<dim>2</dim> <!-- value [0, 2] -->
</port>
</input>
<output>
<port id="2" precision="FP32">
<dim>3</dim>
<dim>2</dim>
</port>
</output>
</layer>

*Example 2: squeeze 1D tensor with 1 element to a 0D tensor (constant)*

.. code-block:: xml
:force:

<layer ... type="Squeeze" version="opset15">
<data allow_axis_skip="false"/>
<input>
<port id="0">
<dim>1</dim>
</port>
</input>
<input>
<port id="1">
<dim>1</dim> <!-- value is [0] -->
</port>
</input>
<output>
<port id="2" precision="FP32">
</port>
</output>
</layer>

*Example 3: squeeze 1D tensor with 1 dynamic shape element to a fully dynamic shape*

.. code-block:: xml
:force:

<layer ... type="Squeeze" version="opset15">
<data allow_axis_skip="true"/>
<input>
<port id="0">
<dim>-1</dim>
</port>
</input>
<input>
<port id="1">
<dim>1</dim> <!-- value is [0] -->
</port>
</input>
<output>
<port id="2" precision="FP32"/> <!-- output with dynamic rank -->
</output>
</layer>

*Example 4: squeeze 2D tensor with dynamic and static shape elements to a static shape output, according to the opset1 rules*

.. code-block:: xml
:force:

<layer ... type="Squeeze" version="opset15">
<data allow_axis_skip="false"/>
<input>
<port id="0">
<dim>2</dim>
<dim>-1</dim>
</port>
</input>
<input>
<port id="1">
<dim>1</dim> <!-- value is [1] -->
</port>
</input>
<output>
<port id="2" precision="FP32">
<dim>2</dim> <!-- assumes: actual value of <dim>-1</dim> is squeezable -->
</port>
</output>
</layer>

*Example 5: squeeze 2D tensor with dynamic and static shape elements to a dynamic shape output, according to the opset15 rules*

.. code-block:: xml
:force:

<layer ... type="Squeeze" version="opset15">
<data allow_axis_skip="true"/>
<input>
<port id="0">
<dim>2</dim>
<dim>-1</dim>
</port>
</input>
<input>
<port id="1">
<dim>1</dim> <!-- value is [1] -->
</port>
</input>
<output>
<port id="2" precision="FP32" /> <!-- Output with dynamic rank. Actual value of <dim>-1</dim> may or may not be squeezable -->
</output>
</layer>
Loading