Skip to content

FillEmptyRows-16 operator specification #28046

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

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Changes from 3 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
7d810fc
Initial draft
p-wysocki Dec 12, 2024
e255fc9
Merge branch 'master' of https://github.com/openvinotoolkit/openvino …
p-wysocki Mar 25, 2025
f5f4d8e
Update rst
p-wysocki Mar 25, 2025
2816e14
Update docs/articles_en/documentation/openvino-ir-format/operation-se…
p-wysocki Apr 11, 2025
8415489
Update docs/articles_en/documentation/openvino-ir-format/operation-se…
p-wysocki Apr 11, 2025
06c0dd0
Update docs/articles_en/documentation/openvino-ir-format/operation-se…
p-wysocki Apr 11, 2025
25de91d
Merge remote-tracking branch 'upstream/master' into empty_rows_spec
p-wysocki Apr 11, 2025
0d4c5c2
Apply CR
p-wysocki Apr 11, 2025
ebe5127
Merge branch 'master' of https://github.com/openvinotoolkit/openvino …
p-wysocki Apr 15, 2025
0c9d884
Add sparse prefix
p-wysocki Apr 15, 2025
b3070b7
Update docs/articles_en/documentation/openvino-ir-format/operation-se…
p-wysocki Apr 15, 2025
025966a
Update docs/articles_en/documentation/openvino-ir-format/operation-se…
p-wysocki Apr 18, 2025
8a7ea6b
Merge branch 'master' into empty_rows_spec
p-wysocki Apr 18, 2025
1bd2996
Update docs/articles_en/documentation/openvino-ir-format/operation-se…
p-wysocki Apr 18, 2025
b85c7dc
Merge branch 'master' into empty_rows_spec
p-wysocki Apr 22, 2025
54019ff
Merge branch 'master' into empty_rows_spec
mlukasze Apr 23, 2025
f459a3e
Update docs/articles_en/documentation/openvino-ir-format/operation-se…
p-wysocki Apr 24, 2025
163e33e
Merge branch 'master' into empty_rows_spec
p-wysocki May 5, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
FillEmptyRows
======================


.. meta::
:description: Learn about FillEmptyRows-16 - a sparse operation, which
can be performed on four required input tensors.

**Versioned name**: *FillEmptyRows-16*

**Category**: *Sparse*

**Short description**: Fills empty rows of an input sparse tensor with a default value.

**Detailed description**:

Operation FillEmptyRows is an implementation of ``tf.sparse.fill_empty_rows``.

The input sparse tensor is represented by the three inputs:

* ``indices``
* ``values``
* ``dense_shape``

For each row in the input sparse tensor, this operator checks if the row is empty. If the row is empty, the operator adds an entry with the specified default value at index `[row, 0, ..., 0]`. The input may have empty columns at the end, which will not be affected by this operation.

The output sparse tensor will be in row-major order and will have the same shape as the input, but with updated `output_indices` and `output_values`.

This operator also returns a boolean vector indicating which rows were filled with the default value: ``empty_row_indicator[i] = True`` if row ``i`` was an empty row.

**Attributes**: FillEmptyRows-16 operation has no attributes.

**Inputs**:

* **1**: ``default_value`` a scalar of type *T* to be inserted into the empty rows. **Required.**
* **2**: ``values`` 1D tensor containing the values of type *T* to be inserted at the specified indices. **Required.**
* **3**: ``dense_shape`` 1D tensor of type *T_IDX* indicating the shape of the dense tensor. **Required.**
* **4**: ``indices`` 2D tensor of type *T_IDX* indicating the positions at which ``values`` are placed in the sparse tensor. **Required.**
It is of shape ``[M, N]``, where:

* ``M`` is the same as the length of the ``values`` input.
* ``N`` is equal to the rank of ``dense_shape``.

**Outputs**:

* **1**: ``output_indices`` 2D tensor of type *T_IDX* indicating the positions at which ``output_values`` are placed in the sparse tensor.
It is of shape ``[M', N]``, where:
Copy link
Member

Choose a reason for hiding this comment

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

do we really need generalization of tf.raw_ops.SparseFillEmptyRows? May be to consider only 2D sparse tensor that is only needed by TF?
I think ND case can be converged to 2D case by reshape

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If only 2D is needed, let's limit it. Applied.


* ``M'`` is the length of the updated ``output_values``.
* ``N`` is equal to the rank of ``dense_shape``.
* **2**: ``output_values`` 1D tensor containing the values of type *T* to be inserted at the specified indices.
* **3**: ``empty_row_indicator`` 1D tensor of type ``boolean`` indicating True for rows which were empty before executing the operation.
Copy link
Contributor

Choose a reason for hiding this comment

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

To have the whole sparse tensor representation, shouldn't the dense_shape be an output as well?
On the other hand, assuming it's the same as the input dense_shape maybe it's reduntant.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

tf.raw_ops.SparseFillEmptyRows doesn't return the output SparseTensor at all according to https://www.tensorflow.org/api_docs/python/tf/raw_ops/SparseFillEmptyRows#returns. Do you think we should have it?

That's also interesting because there's tf.sparse.fill_empty_rows and then there's tf.raw_ops.SparseFillEmptyRows, which have quite different outputs:

https://www.tensorflow.org/api_docs/python/tf/sparse/fill_empty_rows
https://www.tensorflow.org/api_docs/python/tf/raw_ops/SparseFillEmptyRows

However the BST model I received is using the raw_ops one and in the graph the SparseTensor is not returned.


**Types**

* *T*: any numeric type.
* *T_IDX*: ``int32`` or ``int64``.

**Example**

*Example 1: sparse tensor input with shape [5, 6].*

Input sparse tensor:

* ``indices = [[0, 1], [0, 3], [2, 0], [3, 1]]``
* ``values = [a, b, c, d]``
* ``dense_shape = [5, 6]``

Rows 1 and 4 are empty. The output sparse tensor will be:

* ``output_indices = [[0, 1], [0, 3], [1, 0], [2, 0], [3, 1], [4, 0]]``
* ``output_values = [a, b, default_value, c, d, default_value]``
* ``empty_row_indicator = [False, True, False, False, True]``

The output sparse tensor will be in row-major order and will have the same shape as the input.

.. code-block:: xml

<layer ... type="FillEmptyRows" ... >
<input>
<port id="0" precision="FP32"> <!-- default_value is: 42 -->
<dim>0</dim>
</port>
<port id="1" precision="FP32"> <!-- values are: [1, 3] -->
<dim>2</dim>
</port>
<port id="2" precision="I32"> <!-- dense_shape value is: [3, 3] -->
<dim>2</dim>
</port>
<port id="3" precision="I32"> <!-- indices value is: [[0, 0], [2, 2]] -->
<dim>2</dim>
<dim>2</dim>
</port>
</input>
<output>
<port id="4" precision="I32"> <!-- output_indices -->
<dim>3</dim>
<dim>2</dim>
</port>
<port id="5" precision="FP32"> <!-- output_values -->
<dim>3</dim>
</port>
<port id="6" precision="BOOL"> <!-- empty_row_indicator -->
<dim>3</dim>
</port>
</output>
</layer>
Loading