From 4f923247641d75703bac88568dd0e48286aaa9e1 Mon Sep 17 00:00:00 2001 From: PuQing Date: Wed, 27 Sep 2023 16:53:52 +0800 Subject: [PATCH 1/3] add unique --- src/frontends/paddle/src/op/unique.cpp | 41 +++++++++ src/frontends/paddle/src/op_table.cpp | 2 + src/frontends/paddle/tests/op_fuzzy.cpp | 12 ++- .../gen_scripts/generate_unique.py | 90 +++++++++++++++++++ 4 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 src/frontends/paddle/src/op/unique.cpp create mode 100644 src/frontends/paddle/tests/test_models/gen_scripts/generate_unique.py diff --git a/src/frontends/paddle/src/op/unique.cpp b/src/frontends/paddle/src/op/unique.cpp new file mode 100644 index 00000000000000..a69fe304f627af --- /dev/null +++ b/src/frontends/paddle/src/op/unique.cpp @@ -0,0 +1,41 @@ +// Copyright (C) 2018-2023 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "default_opset.hpp" +#include "openvino/frontend/paddle/node_context.hpp" +#include "openvino/opsets/opset10.hpp" + +namespace ov { +namespace frontend { +namespace paddle { +namespace op { +NamedOutputs unique(const NodeContext& node) { + auto x = node.get_input("X"); + + std::vector> outputs; + NamedOutputs named_outputs; + + auto axis = node.get_attribute>("axis"); + + auto dtype_str = node.get_attribute("dtype"); + auto dtype = dtype_str == "int32" ? element::i32 : element::i64; + + if (axis.size() != 0) { + auto axis_node = std::make_shared(element::i32, Shape{}, axis); + outputs = std::make_shared(x, axis_node, true, dtype, dtype)->outputs(); + } else { + outputs = std::make_shared(x, true, dtype, dtype)->outputs(); + } + + named_outputs["Index"] = {outputs[2]}; + named_outputs["Indices"] = {outputs[1]}; + named_outputs["Counts"] = {outputs[3]}; + named_outputs["Out"] = {outputs[0]}; + return named_outputs; +} + +} // namespace op +} // namespace paddle +} // namespace frontend +} // namespace ov diff --git a/src/frontends/paddle/src/op_table.cpp b/src/frontends/paddle/src/op_table.cpp index e3e39ebf2e4ec9..6ba4a63c651688 100644 --- a/src/frontends/paddle/src/op_table.cpp +++ b/src/frontends/paddle/src/op_table.cpp @@ -120,6 +120,7 @@ OP_CONVERTER(top_k_v2); OP_CONVERTER(transpose2); OP_CONVERTER(trilinear_interp_v2); OP_CONVERTER(unsqueeze); +OP_CONVERTER(unique); OP_CONVERTER(where); OP_CONVERTER(while_); OP_CONVERTER(write_to_array); @@ -249,6 +250,7 @@ std::map get_supported_ops() { {"transpose2", op::transpose2}, {"trilinear_interp_v2", op::trilinear_interp_v2}, {"unsqueeze2", op::unsqueeze}, + {"unique", op::unique}, {"where", op::where}, {"while", op::while_}, {"write_to_array", op::write_to_array}, diff --git a/src/frontends/paddle/tests/op_fuzzy.cpp b/src/frontends/paddle/tests/op_fuzzy.cpp index 98c8c1af5970c9..76e0b4a583f8a2 100644 --- a/src/frontends/paddle/tests/op_fuzzy.cpp +++ b/src/frontends/paddle/tests/op_fuzzy.cpp @@ -6,9 +6,9 @@ #include +#include "common_test_utils/test_control.hpp" #include "ngraph/ngraph.hpp" #include "paddle_utils.hpp" -#include "common_test_utils/test_control.hpp" using namespace ngraph; using namespace InferenceEngine; @@ -565,6 +565,16 @@ static const std::vector models{ std::string("trilinear_upsample_scales2/trilinear_upsample_scales2.pdmodel"), std::string("trilinear_upsample_true_0/trilinear_upsample_true_0.pdmodel"), std::string("unsqueeze"), + std::string("unique"), + std::string("unique_ret_index"), + std::string("unique_ret_inverse"), + std::string("unique_ret_counts"), + std::string("unique_ret_index_inverse"), + std::string("unique_ret_index_counts"), + std::string("unique_ret_inverse_counts"), + std::string("unique_ret_index_inverse_counts"), + std::string("unique_ret_index_axis"), + std::string("unique_ret_index_i32"), std::string("where_1"), std::string("where_2"), std::string("where_3"), diff --git a/src/frontends/paddle/tests/test_models/gen_scripts/generate_unique.py b/src/frontends/paddle/tests/test_models/gen_scripts/generate_unique.py new file mode 100644 index 00000000000000..cfedaf1a60fa75 --- /dev/null +++ b/src/frontends/paddle/tests/test_models/gen_scripts/generate_unique.py @@ -0,0 +1,90 @@ +# Copyright (C) 2018-2023 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +# +# unique paddle model generator +# +import numpy as np +from save_model import saveModel +import paddle +import sys + +data_type = "float32" + + +def unique( + name: str, + x, + reture_index=False, + reture_inverse=False, + reture_counts=False, + dtype="int64", + axes=None, +): + paddle.enable_static() + + with paddle.static.program_guard(paddle.static.Program(), paddle.static.Program()): + node_x = paddle.static.data(name="x", shape=x.shape, dtype=data_type) + + unique_outs = paddle.unique( + node_x, + return_index=reture_index, + return_inverse=reture_inverse, + return_counts=reture_counts, + dtype=dtype, + axis=axes, + ) + if reture_counts or reture_inverse or reture_index: + outputs = [] + for out in unique_outs: + if out is not None: + if out.dtype == paddle.int64 or out.dtype == paddle.int32: + out = paddle.cast(out, "float32") + outputs.append(out) + else: + outputs = [unique_outs] + + cpu = paddle.static.cpu_places(1) + exe = paddle.static.Executor(cpu[0]) + # startup program will call initializer to initialize the parameters. + exe.run(paddle.static.default_startup_program()) + + fetch_vars = [x for x in outputs if x is not None] + + outs = exe.run(feed={"x": x}, fetch_list=fetch_vars) + + saveModel( + name, + exe, + feedkeys=["x"], + fetchlist=fetch_vars, + inputs=[x], + outputs=outs, + target_dir=sys.argv[1], + ) + + +def main(): + data = np.array([2, 3, 3, 1, 5, 3]).astype(data_type) + unique("unique", data) + unique("unique_ret_index", data, reture_index=True) + unique("unique_ret_inverse", data, reture_inverse=True) + unique("unique_ret_counts", data, reture_counts=True) + unique("unique_ret_index_inverse", data, reture_index=True, reture_inverse=True) + unique("unique_ret_index_counts", data, reture_index=True, reture_counts=True) + unique("unique_ret_inverse_counts", data, reture_inverse=True, reture_counts=True) + unique( + "unique_ret_index_inverse_counts", + data, + reture_index=True, + reture_inverse=True, + reture_counts=True, + ) + + data = np.array([[2, 1, 3], [3, 0, 1], [2, 1, 3]]).astype(data_type) + unique("unique_ret_index_axis", data, reture_index=True, axes=0) + unique("unique_ret_index_i32", data, reture_index=True, dtype="int32") + + +if __name__ == "__main__": + main() From c5b1a3414cd21821057ecc642f4af5293f34e824 Mon Sep 17 00:00:00 2001 From: PuQing Date: Mon, 6 Nov 2023 11:45:21 +0800 Subject: [PATCH 2/3] fix args --- .../gen_scripts/generate_unique.py | 43 ++++++------------- 1 file changed, 14 insertions(+), 29 deletions(-) diff --git a/src/frontends/paddle/tests/test_models/gen_scripts/generate_unique.py b/src/frontends/paddle/tests/test_models/gen_scripts/generate_unique.py index cfedaf1a60fa75..a3debea527db15 100644 --- a/src/frontends/paddle/tests/test_models/gen_scripts/generate_unique.py +++ b/src/frontends/paddle/tests/test_models/gen_scripts/generate_unique.py @@ -12,29 +12,14 @@ data_type = "float32" -def unique( - name: str, - x, - reture_index=False, - reture_inverse=False, - reture_counts=False, - dtype="int64", - axes=None, -): +def unique(name: str, x, **op_args): paddle.enable_static() with paddle.static.program_guard(paddle.static.Program(), paddle.static.Program()): node_x = paddle.static.data(name="x", shape=x.shape, dtype=data_type) - unique_outs = paddle.unique( - node_x, - return_index=reture_index, - return_inverse=reture_inverse, - return_counts=reture_counts, - dtype=dtype, - axis=axes, - ) - if reture_counts or reture_inverse or reture_index: + unique_outs = paddle.unique(node_x, **op_args) + if isinstance(unique_outs, tuple): outputs = [] for out in unique_outs: if out is not None: @@ -67,23 +52,23 @@ def unique( def main(): data = np.array([2, 3, 3, 1, 5, 3]).astype(data_type) unique("unique", data) - unique("unique_ret_index", data, reture_index=True) - unique("unique_ret_inverse", data, reture_inverse=True) - unique("unique_ret_counts", data, reture_counts=True) - unique("unique_ret_index_inverse", data, reture_index=True, reture_inverse=True) - unique("unique_ret_index_counts", data, reture_index=True, reture_counts=True) - unique("unique_ret_inverse_counts", data, reture_inverse=True, reture_counts=True) + unique("unique_ret_index", data, return_index=True) + unique("unique_ret_inverse", data, return_inverse=True) + unique("unique_ret_counts", data, return_counts=True) + unique("unique_ret_index_inverse", data, return_index=True, return_inverse=True) + unique("unique_ret_index_counts", data, return_index=True, return_counts=True) + unique("unique_ret_inverse_counts", data, return_inverse=True, return_counts=True) unique( "unique_ret_index_inverse_counts", data, - reture_index=True, - reture_inverse=True, - reture_counts=True, + return_index=True, + return_inverse=True, + return_counts=True, ) data = np.array([[2, 1, 3], [3, 0, 1], [2, 1, 3]]).astype(data_type) - unique("unique_ret_index_axis", data, reture_index=True, axes=0) - unique("unique_ret_index_i32", data, reture_index=True, dtype="int32") + unique("unique_ret_index_axis", data, return_index=True, axis=0) + unique("unique_ret_index_i32", data, return_index=True, dtype="int32") if __name__ == "__main__": From d6ad32ab950ab6acedd724b95f5bfab3afe5b034 Mon Sep 17 00:00:00 2001 From: PuQing Date: Mon, 4 Dec 2023 18:31:58 +0800 Subject: [PATCH 3/3] Refactor unique() function to handle dtype correctly --- src/frontends/paddle/src/op/unique.cpp | 16 ++++++---------- .../test_models/gen_scripts/generate_unique.py | 9 ++++++--- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/frontends/paddle/src/op/unique.cpp b/src/frontends/paddle/src/op/unique.cpp index a69fe304f627af..7f168c47d1d01a 100644 --- a/src/frontends/paddle/src/op/unique.cpp +++ b/src/frontends/paddle/src/op/unique.cpp @@ -14,25 +14,21 @@ NamedOutputs unique(const NodeContext& node) { auto x = node.get_input("X"); std::vector> outputs; - NamedOutputs named_outputs; auto axis = node.get_attribute>("axis"); - - auto dtype_str = node.get_attribute("dtype"); - auto dtype = dtype_str == "int32" ? element::i32 : element::i64; + auto dtype = node.get_attribute("dtype"); if (axis.size() != 0) { - auto axis_node = std::make_shared(element::i32, Shape{}, axis); + auto axis_node = std::make_shared(dtype, Shape{}, axis); outputs = std::make_shared(x, axis_node, true, dtype, dtype)->outputs(); } else { outputs = std::make_shared(x, true, dtype, dtype)->outputs(); } - named_outputs["Index"] = {outputs[2]}; - named_outputs["Indices"] = {outputs[1]}; - named_outputs["Counts"] = {outputs[3]}; - named_outputs["Out"] = {outputs[0]}; - return named_outputs; + return NamedOutputs{{"Out", {outputs[0]}}, + {"Indices", {outputs[1]}}, + {"Index", {outputs[2]}}, + {"Counts", {outputs[3]}}}; } } // namespace op diff --git a/src/frontends/paddle/tests/test_models/gen_scripts/generate_unique.py b/src/frontends/paddle/tests/test_models/gen_scripts/generate_unique.py index a3debea527db15..f8a3a6029c6946 100644 --- a/src/frontends/paddle/tests/test_models/gen_scripts/generate_unique.py +++ b/src/frontends/paddle/tests/test_models/gen_scripts/generate_unique.py @@ -21,10 +21,13 @@ def unique(name: str, x, **op_args): unique_outs = paddle.unique(node_x, **op_args) if isinstance(unique_outs, tuple): outputs = [] - for out in unique_outs: + for i, out in enumerate(unique_outs): + if i == 0: + outputs.append(out) + continue if out is not None: - if out.dtype == paddle.int64 or out.dtype == paddle.int32: - out = paddle.cast(out, "float32") + if out.dtype == paddle.int64: + out = paddle.cast(out, "int32") outputs.append(out) else: outputs = [unique_outs]