Add FakeQuantize op to ONNX importer (#1099)

This commit is contained in:
Katarzyna Mitrus 2020-07-03 18:28:33 +02:00 committed by GitHub
parent bd8a383560
commit e3e13b9bd8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 448 additions and 0 deletions

View File

@ -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

View 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

View 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

View File

@ -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

View File

@ -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
}

View File

@ -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
}

View File

@ -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();
}

View File

@ -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