From 97f020481aa0b42b2205d0349016a9902ea14afb Mon Sep 17 00:00:00 2001 From: Tomasz Socha Date: Mon, 24 May 2021 11:04:11 +0200 Subject: [PATCH] [ONNX][ONNX Editor] Generate an input with unknown shape and type for operators without schema. (#5531) --- .../src/detail/subgraph_extraction.cpp | 26 ++-- .../unknown_input_value_info.prototxt | 73 ++++++++++ .../unknown_input_value_info.prototxt | 132 ++++++++++++++++++ ngraph/test/onnx/onnx_editor.cpp | 15 ++ 4 files changed, 238 insertions(+), 8 deletions(-) create mode 100644 ngraph/test/models/onnx/model_editor/reference/unknown_input_value_info.prototxt create mode 100644 ngraph/test/models/onnx/model_editor/unknown_input_value_info.prototxt diff --git a/ngraph/frontend/onnx_editor/src/detail/subgraph_extraction.cpp b/ngraph/frontend/onnx_editor/src/detail/subgraph_extraction.cpp index a00618c21d02af..c42f8f15424c47 100644 --- a/ngraph/frontend/onnx_editor/src/detail/subgraph_extraction.cpp +++ b/ngraph/frontend/onnx_editor/src/detail/subgraph_extraction.cpp @@ -105,7 +105,7 @@ namespace /// \brief Looks up a descriptor for a given tensor name. This descriptor contains inferred /// shape information which is required to create new inputs and outputs in the graph. - const ONNX_NAMESPACE::ValueInfoProto& + const ONNX_NAMESPACE::ValueInfoProto find_tensor_descriptor(const ONNX_NAMESPACE::GraphProto& graph, const std::string& tensor_name) { @@ -113,13 +113,23 @@ namespace std::end(graph.value_info()), name_equals(tensor_name)); - NGRAPH_CHECK(it != std::end(graph.value_info()), - "Could not find a tensor descriptor for tensor '", - tensor_name, - "'. It's not possible to add a new input to the graph without the type and " - "shape information of the intermediate tensor."); - - return *it; + if (it != std::end(graph.value_info())) + { + return *it; + } + else + { + // If tensor descriptor couldn't be found value info has to be specified as fully dynamic: + // - Fully dynamic shape + // - Unknown data type + auto dynamic_value_info = ONNX_NAMESPACE::ValueInfoProto(); + dynamic_value_info.set_name(tensor_name); + auto type = dynamic_value_info.mutable_type(); + auto tensor_type = type->mutable_tensor_type(); + tensor_type->set_elem_type( + ONNX_NAMESPACE::TensorProto_DataType::TensorProto_DataType_UNDEFINED); + return dynamic_value_info; + } } std::string get_input_tensor_name(const ONNX_NAMESPACE::GraphProto& graph, diff --git a/ngraph/test/models/onnx/model_editor/reference/unknown_input_value_info.prototxt b/ngraph/test/models/onnx/model_editor/reference/unknown_input_value_info.prototxt new file mode 100644 index 00000000000000..c6f6674d03ec04 --- /dev/null +++ b/ngraph/test/models/onnx/model_editor/reference/unknown_input_value_info.prototxt @@ -0,0 +1,73 @@ +ir_version: 7 +producer_name: "test_data_generator" +graph { + name: "No name" + node { + input: "X" + output: "X2" + name: "" + op_type: "Relu" + } + node { + input: "X2" + output: "Y" + name: "" + op_type: "MaxPool" + attribute { + name: "strides" + ints: 2 + ints: 2 + type: INTS + } + attribute { + name: "pads" + ints: 0 + ints: 0 + ints: 0 + ints: 0 + type: INTS + } + attribute { + name: "kernel_shape" + ints: 3 + ints: 3 + type: INTS + } + } + + input { + name: "X" + type { + tensor_type { + elem_type: 0 + } + } + } + + output { + name: "Y" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 64 + } + dim { + dim_value: 55 + } + dim { + dim_value: 55 + } + } + } + } + } +} + +opset_import { + version: 13 +} diff --git a/ngraph/test/models/onnx/model_editor/unknown_input_value_info.prototxt b/ngraph/test/models/onnx/model_editor/unknown_input_value_info.prototxt new file mode 100644 index 00000000000000..7c983d31347594 --- /dev/null +++ b/ngraph/test/models/onnx/model_editor/unknown_input_value_info.prototxt @@ -0,0 +1,132 @@ +ir_version: 7 +producer_name: "test_data_generator" +graph { + name: "No_name" + node { + input: "A" + input: "B" + input: "C" + output: "X" + name: "" + op_type: "Bongo" + } + node { + input: "X" + output: "X2" + name: "" + op_type: "Relu" + } + node { + input: "X2" + output: "Y" + name: "" + op_type: "MaxPool" + attribute { + name: "strides" + ints: 2 + ints: 2 + type: INTS + } + attribute { + name: "pads" + ints: 0 + ints: 0 + ints: 0 + ints: 0 + type: INTS + } + attribute { + name: "kernel_shape" + ints: 3 + ints: 3 + type: INTS + } + } + + input { + name: "A" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 3 + } + dim { + dim_value: 224 + } + dim { + dim_value: 224 + } + } + } + } + } + + input { + name: "B" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 64 + } + dim { + dim_value: 3 + } + dim { + dim_value: 7 + } + dim { + dim_value: 7 + } + } + } + } + } + + input { + name: "C" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 64 + } + } + } + } + } + + output { + name: "Y" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 64 + } + dim { + dim_value: 55 + } + dim { + dim_value: 55 + } + } + } + } + } +} + +opset_import { + version: 13 +} diff --git a/ngraph/test/onnx/onnx_editor.cpp b/ngraph/test/onnx/onnx_editor.cpp index 6abd97cbf63bf6..c6d3241a057649 100644 --- a/ngraph/test/onnx/onnx_editor.cpp +++ b/ngraph/test/onnx/onnx_editor.cpp @@ -1447,3 +1447,18 @@ NGRAPH_TEST(onnx_editor, combined__cut_and_replace_shape) EXPECT_TRUE( find_input(graph_inputs, "conv1/7x7_s2_1")->get_partial_shape().same_scheme(new_shape)); } + +NGRAPH_TEST(onnx_editor, cut_operator_with_no_schema) +{ + ONNXModelEditor editor{file_util::path_join( + SERIALIZED_ZOO, "onnx/model_editor/unknown_input_value_info.prototxt")}; + + editor.cut_graph_fragment({{InputEdge(1, "X")}}, {}); + + const auto ref_model = file_util::path_join( + SERIALIZED_ZOO, "onnx/model_editor/reference/unknown_input_value_info.prototxt"); + + const auto result = compare_onnx_models(editor.model_string(), ref_model); + + EXPECT_TRUE(result.is_ok) << result.error_message; +}