Add FakeQuantize op to ONNX importer (#1099)
This commit is contained in:
parent
bd8a383560
commit
e3e13b9bd8
@ -99,6 +99,8 @@ add_library(onnx_importer SHARED
|
||||
op/expand.cpp
|
||||
op/eye_like.cpp
|
||||
op/eye_like.hpp
|
||||
op/fake_quantize.cpp
|
||||
op/fake_quantize.hpp
|
||||
op/flatten.cpp
|
||||
op/flatten.hpp
|
||||
op/floor.hpp
|
||||
|
51
ngraph/src/ngraph/frontend/onnx_import/op/fake_quantize.cpp
Normal file
51
ngraph/src/ngraph/frontend/onnx_import/op/fake_quantize.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
//*****************************************************************************
|
||||
// Copyright 2017-2020 Intel Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//*****************************************************************************
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "default_opset.hpp"
|
||||
#include "fake_quantize.hpp"
|
||||
|
||||
namespace ngraph
|
||||
{
|
||||
namespace onnx_import
|
||||
{
|
||||
namespace op
|
||||
{
|
||||
namespace set_1
|
||||
{
|
||||
NodeVector fake_quantize(const onnx_import::Node& node)
|
||||
{
|
||||
const auto inputs = node.get_ng_inputs();
|
||||
const auto X = inputs.at(0);
|
||||
const auto input_low = inputs.at(1);
|
||||
const auto input_high = inputs.at(2);
|
||||
const auto output_low = inputs.at(3);
|
||||
const auto output_high = inputs.at(4);
|
||||
|
||||
const auto levels = node.get_attribute_value<std::size_t>("levels");
|
||||
|
||||
return {std::make_shared<default_opset::FakeQuantize>(
|
||||
X, input_low, input_high, output_low, output_high, levels)};
|
||||
}
|
||||
|
||||
} // namespace set_1
|
||||
|
||||
} // namespace op
|
||||
|
||||
} // namespace onnx_import
|
||||
|
||||
} // namespace ngraph
|
38
ngraph/src/ngraph/frontend/onnx_import/op/fake_quantize.hpp
Normal file
38
ngraph/src/ngraph/frontend/onnx_import/op/fake_quantize.hpp
Normal file
@ -0,0 +1,38 @@
|
||||
//*****************************************************************************
|
||||
// Copyright 2017-2020 Intel Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//*****************************************************************************
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/node.hpp"
|
||||
#include "ngraph/node.hpp"
|
||||
|
||||
namespace ngraph
|
||||
{
|
||||
namespace onnx_import
|
||||
{
|
||||
namespace op
|
||||
{
|
||||
namespace set_1
|
||||
{
|
||||
NodeVector fake_quantize(const Node& node);
|
||||
|
||||
} // namespace set_1
|
||||
|
||||
} // namespace op
|
||||
|
||||
} // namespace onnx_import
|
||||
|
||||
} // namespace ngraph
|
@ -57,6 +57,7 @@
|
||||
#include "op/exp.hpp"
|
||||
#include "op/expand.hpp"
|
||||
#include "op/eye_like.hpp"
|
||||
#include "op/fake_quantize.hpp"
|
||||
#include "op/flatten.hpp"
|
||||
#include "op/floor.hpp"
|
||||
#include "op/gather.hpp"
|
||||
@ -392,6 +393,9 @@ namespace ngraph
|
||||
REGISTER_OPERATOR("Upsample", 9, upsample);
|
||||
REGISTER_OPERATOR("Where", 1, where);
|
||||
REGISTER_OPERATOR("Xor", 1, logical_xor);
|
||||
|
||||
// TODO Change the domain
|
||||
m_map[""]["FakeQuantize"].emplace(1, op::set_1::fake_quantize);
|
||||
}
|
||||
|
||||
#undef REGISTER_OPERATOR
|
||||
|
@ -0,0 +1,135 @@
|
||||
ir_version: 7
|
||||
producer_name: "onnx-importer-test"
|
||||
graph {
|
||||
node {
|
||||
output: "input_low"
|
||||
op_type: "Constant"
|
||||
attribute {
|
||||
name: "value"
|
||||
t {
|
||||
dims: 1
|
||||
dims: 1
|
||||
dims: 1
|
||||
dims: 1
|
||||
data_type: 1
|
||||
float_data: 3.0
|
||||
name: "const_tensor"
|
||||
}
|
||||
type: TENSOR
|
||||
}
|
||||
}
|
||||
node {
|
||||
output: "input_high"
|
||||
op_type: "Constant"
|
||||
attribute {
|
||||
name: "value"
|
||||
t {
|
||||
dims: 1
|
||||
dims: 1
|
||||
dims: 1
|
||||
dims: 1
|
||||
data_type: 1
|
||||
float_data: 17.0
|
||||
name: "const_tensor"
|
||||
}
|
||||
type: TENSOR
|
||||
}
|
||||
}
|
||||
node {
|
||||
output: "output_low"
|
||||
op_type: "Constant"
|
||||
attribute {
|
||||
name: "value"
|
||||
t {
|
||||
dims: 1
|
||||
dims: 1
|
||||
dims: 1
|
||||
dims: 1
|
||||
data_type: 1
|
||||
float_data: 2.0
|
||||
name: "const_tensor"
|
||||
}
|
||||
type: TENSOR
|
||||
}
|
||||
}
|
||||
node {
|
||||
output: "output_high"
|
||||
op_type: "Constant"
|
||||
attribute {
|
||||
name: "value"
|
||||
t {
|
||||
dims: 1
|
||||
dims: 1
|
||||
dims: 1
|
||||
dims: 1
|
||||
data_type: 1
|
||||
float_data: 16.0
|
||||
name: "const_tensor"
|
||||
}
|
||||
type: TENSOR
|
||||
}
|
||||
}
|
||||
node {
|
||||
input: "X"
|
||||
input: "input_low"
|
||||
input: "input_high"
|
||||
input: "output_low"
|
||||
input: "output_high"
|
||||
output: "Y"
|
||||
op_type: "FakeQuantize"
|
||||
attribute {
|
||||
name: "levels"
|
||||
i: 5
|
||||
type: INT
|
||||
}
|
||||
}
|
||||
name: "test-model"
|
||||
input {
|
||||
name: "X"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
dim {
|
||||
dim_value: 3
|
||||
}
|
||||
dim {
|
||||
dim_value: 4
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "Y"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
dim {
|
||||
dim_value: 3
|
||||
}
|
||||
dim {
|
||||
dim_value: 4
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
opset_import {
|
||||
domain: ""
|
||||
version: 9
|
||||
}
|
@ -0,0 +1,155 @@
|
||||
ir_version: 7
|
||||
producer_name: "onnx-importer-test"
|
||||
graph {
|
||||
node {
|
||||
input: "X"
|
||||
input: "input_low"
|
||||
input: "input_high"
|
||||
input: "output_low"
|
||||
input: "output_high"
|
||||
output: "Y"
|
||||
op_type: "FakeQuantize"
|
||||
attribute {
|
||||
name: "levels"
|
||||
i: 5
|
||||
type: INT
|
||||
}
|
||||
}
|
||||
name: "test-model"
|
||||
input {
|
||||
name: "X"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
dim {
|
||||
dim_value: 3
|
||||
}
|
||||
dim {
|
||||
dim_value: 4
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
input {
|
||||
name: "input_low"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
input {
|
||||
name: "input_high"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
input {
|
||||
name: "output_low"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
input {
|
||||
name: "output_high"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "Y"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
dim {
|
||||
dim_value: 3
|
||||
}
|
||||
dim {
|
||||
dim_value: 4
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
opset_import {
|
||||
domain: ""
|
||||
version: 9
|
||||
}
|
@ -560,3 +560,62 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_model_matmul_integer_4d_no_zero_point)
|
||||
1606}); // y
|
||||
test_case.run();
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, onnx_model_fake_quantize_import_only)
|
||||
{
|
||||
const auto function = onnx_import::import_onnx_model(file_util::path_join(
|
||||
SERIALIZED_ZOO, "onnx/quantization/fake_quantize_const_inputs.prototxt"));
|
||||
|
||||
const Shape expected_output_shape{1, 2, 3, 4};
|
||||
EXPECT_EQ(function->get_output_size(), 1);
|
||||
EXPECT_EQ(function->get_output_shape(0), expected_output_shape);
|
||||
EXPECT_EQ(count_ops_of_type<op::v0::FakeQuantize>(function), 1);
|
||||
EXPECT_EQ(count_ops_of_type<op::v0::Constant>(function), 4);
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, onnx_model_fake_quantize_const_inputs_infer)
|
||||
{
|
||||
const auto function = onnx_import::import_onnx_model(file_util::path_join(
|
||||
SERIALIZED_ZOO, "onnx/quantization/fake_quantize_const_inputs.prototxt"));
|
||||
|
||||
const Shape data_shape{1, 2, 3, 4};
|
||||
const auto n_elements = shape_size(data_shape);
|
||||
std::vector<float> input_data(n_elements);
|
||||
std::iota(std::begin(input_data), std::end(input_data), 0);
|
||||
|
||||
auto test_case = test::TestCase<TestEngine>(function);
|
||||
test_case.add_input<float>(input_data);
|
||||
test_case.add_expected_output<float>(
|
||||
data_shape, std::vector<float>{2.f, 2.f, 2.f, 2.f, 2.f, 5.5f, 5.5f, 5.5f,
|
||||
5.5f, 9.f, 9.f, 9.f, 12.5f, 12.5f, 12.5f, 12.5f,
|
||||
16.f, 16.f, 16.f, 16.f, 16.f, 16.f, 16.f, 16.f});
|
||||
test_case.run();
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, onnx_model_fake_quantize_nonconst_inputs_infer)
|
||||
{
|
||||
const auto function = onnx_import::import_onnx_model(file_util::path_join(
|
||||
SERIALIZED_ZOO, "onnx/quantization/fake_quantize_nonconst_inputs.prototxt"));
|
||||
|
||||
const Shape data_shape{1, 2, 3, 4};
|
||||
const size_t n_elements = shape_size(data_shape);
|
||||
std::vector<float> input_data(n_elements);
|
||||
std::iota(std::begin(input_data), std::end(input_data), 0);
|
||||
|
||||
auto test_case = test::TestCase<TestEngine>(function);
|
||||
test_case.add_input<float>(input_data);
|
||||
// input_low
|
||||
test_case.add_input<float>({3.f});
|
||||
// input_high
|
||||
test_case.add_input<float>({17.f});
|
||||
// output_low
|
||||
test_case.add_input<float>({2.f});
|
||||
// output_high
|
||||
test_case.add_input<float>({16.f});
|
||||
|
||||
test_case.add_expected_output<float>(
|
||||
data_shape, std::vector<float>{2.f, 2.f, 2.f, 2.f, 2.f, 5.5f, 5.5f, 5.5f,
|
||||
5.5f, 9.f, 9.f, 9.f, 12.5f, 12.5f, 12.5f, 12.5f,
|
||||
16.f, 16.f, 16.f, 16.f, 16.f, 16.f, 16.f, 16.f});
|
||||
test_case.run();
|
||||
}
|
||||
|
@ -162,6 +162,7 @@ onnx_model_conv_with_dynamic_batch
|
||||
|
||||
# Segmentation fault
|
||||
bool_init_and
|
||||
onnx_model_fake_quantize_nonconst_inputs_infer
|
||||
|
||||
# Incorrect number of 'indices_to_squeeze' input dimensions!
|
||||
arg_min_no_keep_dims_dyn_shape
|
||||
@ -1693,5 +1694,8 @@ IE_GPU.matmul_2x3_3x3
|
||||
IE_GPU.matmul_3x2_3x3_transpose
|
||||
IE_GPU.matmul_3x2_2x3_transpose
|
||||
|
||||
IE_GPU.onnx_model_fake_quantize_const_inputs_infer
|
||||
IE_GPU.onnx_model_fake_quantize_nonconst_inputs_infer
|
||||
|
||||
# ONNX Loop
|
||||
onnx_controlflow_loop_2d_add_execution
|
||||
|
Loading…
Reference in New Issue
Block a user