Remove obsoleted v0::QuantizedConvolution op (#2958)

This commit is contained in:
Mateusz Tabaka
2020-11-05 07:10:51 +01:00
committed by GitHub
parent 5d7f83f399
commit 43d47d780e
10 changed files with 0 additions and 1308 deletions

View File

@@ -130,7 +130,6 @@ NGRAPH_OP(PriorBox, ngraph::op::v0, 0)
NGRAPH_OP(PriorBoxClustered, ngraph::op::v0, 0)
NGRAPH_OP(Proposal, ngraph::op::v0, 0)
NGRAPH_OP(Quantize, ngraph::op::v0, 0)
NGRAPH_OP(QuantizedConvolution, ngraph::op::v0, 0)
NGRAPH_OP(QuantizedDot, ngraph::op::v0, 0)
NGRAPH_OP(RNNCell, ngraph::op::v0, 0)
NGRAPH_OP(ROIPooling, ngraph::op::v0, 0)

View File

@@ -1,116 +0,0 @@
//*****************************************************************************
// 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 "ngraph/coordinate_diff.hpp"
#include "ngraph/op/op.hpp"
namespace ngraph
{
namespace op
{
namespace v0
{
class NGRAPH_DEPRECATED(
"This operation is deprecated and will be removed soon. Please do not use it.")
NGRAPH_API QuantizedConvolution : public Op
{
NGRAPH_SUPPRESS_DEPRECATED_START
public:
static constexpr NodeTypeInfo type_info{"QuantizedConvolution", 0};
const NodeTypeInfo& get_type_info() const override { return type_info; }
/// \brief Constructs a quantized convolution operation.
///
/// \param input The node producing the input data batch tensor.
/// \param filters The node producing the filters tensor.
/// \param window_movement_strides The window movement strides.
/// \param window_dilation_strides The window dilation strides.
/// \param padding_below The padding-below sizes.
/// \param padding_above The padding-above sizes.
/// \param data_dilation_strides The data dilation strides.
/// \param input_scale Scale to transform the input
/// \param input_zero_point Zero point used for mapping
/// \param filter_scale Scale to transform the filters
/// \param filter_zero_point Zero point used for mapping
/// \param output_scale Scale to transform the output
/// \param output_zero_point Zero point used for mapping
/// \param output_type Output element type
/// \param input_axes Input axes set for channel wise quantization
/// \param filter_axes Filter axes set for channel wise quantization
/// \param output_axes Output axes set for channel wise quantization
QuantizedConvolution(const Output<Node>& input,
const Output<Node>& filters,
const Strides& window_movement_strides,
const Strides& window_dilation_strides,
const CoordinateDiff& padding_below,
const CoordinateDiff& padding_above,
const Strides& data_dilation_strides,
const Output<Node>& input_scale,
const Output<Node>& input_zero_point,
const Output<Node>& filter_scale,
const Output<Node>& filter_zero_point,
const Output<Node>& output_scale,
const Output<Node>& output_zero_point,
const ngraph::element::Type& output_type,
const ngraph::AxisSet& input_axes = ngraph::AxisSet{},
const ngraph::AxisSet& filter_axes = ngraph::AxisSet{},
const ngraph::AxisSet& output_axes = ngraph::AxisSet{});
QuantizedConvolution() = default;
const Strides& get_window_movement_strides() const
{
return m_window_movement_strides;
}
const Strides& get_window_dilation_strides() const
{
return m_window_dilation_strides;
}
const CoordinateDiff& get_padding_below() const { return m_padding_below; }
const CoordinateDiff& get_padding_above() const { return m_padding_above; }
const Strides& get_data_dilation_strides() const { return m_data_dilation_strides; }
std::shared_ptr<Node> get_filters() { return input_value(1).get_node_shared_ptr(); }
std::shared_ptr<Node> get_data_batch()
{
return input_value(0).get_node_shared_ptr();
}
const ngraph::element::Type& get_output_type() const { return m_output_type; }
const ngraph::AxisSet& get_input_axes() const { return m_input_axes; }
const ngraph::AxisSet& get_filter_axes() const { return m_filter_axes; }
const ngraph::AxisSet& get_output_axes() const { return m_output_axes; }
void validate_and_infer_types() override;
virtual std::shared_ptr<Node>
clone_with_new_inputs(const OutputVector& new_args) const override;
protected:
Strides m_window_movement_strides;
Strides m_window_dilation_strides;
CoordinateDiff m_padding_below;
CoordinateDiff m_padding_above;
Strides m_data_dilation_strides;
ngraph::element::Type m_output_type;
ngraph::AxisSet m_input_axes;
ngraph::AxisSet m_filter_axes;
ngraph::AxisSet m_output_axes;
NGRAPH_SUPPRESS_DEPRECATED_END
};
}
NGRAPH_SUPPRESS_DEPRECATED_START
using v0::QuantizedConvolution;
NGRAPH_SUPPRESS_DEPRECATED_END
}
}

View File

@@ -112,7 +112,6 @@
#include "ngraph/op/proposal.hpp"
#include "ngraph/op/psroi_pooling.hpp"
#include "ngraph/op/quantize.hpp"
#include "ngraph/op/quantized_convolution.hpp"
#include "ngraph/op/quantized_dot.hpp"
#include "ngraph/op/range.hpp"
#include "ngraph/op/read_value.hpp"

View File

@@ -1,196 +0,0 @@
//*****************************************************************************
// 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 "quantized_convolution.hpp"
#include "ngraph/coordinate_diff.hpp"
#include "ngraph/validation_util.hpp"
NGRAPH_SUPPRESS_DEPRECATED_START
using namespace std;
using namespace ngraph;
constexpr NodeTypeInfo op::QuantizedConvolution::type_info;
op::QuantizedConvolution::QuantizedConvolution(const Output<Node>& input,
const Output<Node>& filters,
const Strides& window_movement_strides,
const Strides& window_dilation_strides,
const CoordinateDiff& padding_below,
const CoordinateDiff& padding_above,
const Strides& data_dilation_strides,
const Output<Node>& input_scale,
const Output<Node>& input_zero_point,
const Output<Node>& filter_scale,
const Output<Node>& filter_zero_point,
const Output<Node>& output_scale,
const Output<Node>& output_zero_point,
const element::Type& output_type,
const AxisSet& input_axes,
const AxisSet& filter_axes,
const AxisSet& output_axes)
: Op({input,
filters,
input_scale,
input_zero_point,
filter_scale,
filter_zero_point,
output_scale,
output_zero_point})
, m_window_movement_strides(window_movement_strides)
, m_window_dilation_strides(window_dilation_strides)
, m_padding_below(padding_below)
, m_padding_above(padding_above)
, m_data_dilation_strides(data_dilation_strides)
, m_output_type(output_type)
, m_input_axes(input_axes)
, m_filter_axes(filter_axes)
, m_output_axes(output_axes)
{
constructor_validate_and_infer_types();
}
void op::QuantizedConvolution::validate_and_infer_types()
{
enum
{
INPUT,
FILTER,
INPUT_SCALE,
INPUT_ZERO_POINT,
FILTER_SCALE,
FILTER_ZERO_POINT,
OUTPUT_SCALE,
OUTPUT_ZERO_POINT
};
NODE_VALIDATION_CHECK(
this, m_output_type.is_static(), "Output element type must not be dynamic");
NODE_VALIDATION_CHECK(this,
m_output_type.is_quantized(),
"Output element type (",
m_output_type,
") must be a quantized type");
NODE_VALIDATION_CHECK(this,
get_input_element_type(INPUT).is_quantized(),
"Input element type (",
get_input_element_type(INPUT),
") must be a quantized type");
NODE_VALIDATION_CHECK(this,
get_input_element_type(FILTER).is_quantized(),
"Filter element type (",
get_input_element_type(FILTER),
") must be a quantized type");
NODE_VALIDATION_CHECK(this,
get_input_element_type(INPUT_SCALE).is_real() ||
get_input_element_type(INPUT_SCALE).is_dynamic() ||
get_input_element_type(FILTER_SCALE).is_real() ||
get_input_element_type(FILTER_SCALE).is_dynamic() ||
get_input_element_type(OUTPUT_SCALE).is_real() ||
get_input_element_type(OUTPUT_SCALE).is_dynamic(),
"Scale must be a floating point number");
NODE_VALIDATION_CHECK(
this,
get_input_element_type(0).compatible(get_input_element_type(INPUT_ZERO_POINT)),
"Input Zero point element type (",
get_input_element_type(INPUT_ZERO_POINT),
") must match input element type (",
get_input_element_type(0),
")");
NODE_VALIDATION_CHECK(
this,
get_input_element_type(1).compatible(get_input_element_type(FILTER_ZERO_POINT)),
"Filter Zero point element type (",
get_input_element_type(FILTER_ZERO_POINT),
") must match filter element type (",
get_input_element_type(1),
")");
// TODO Remove these checks once we support channelwise and vector of scales
NODE_VALIDATION_CHECK(this,
get_input_partial_shape(2).compatible(PartialShape{}) &&
get_input_partial_shape(3).compatible(PartialShape{}),
"Input scale and input zero point shape must be same and 1");
NODE_VALIDATION_CHECK(this,
get_input_partial_shape(4).compatible(PartialShape{}) &&
get_input_partial_shape(5).compatible(PartialShape{}),
"Filter scale and filter zero point shape must be same and 1");
NODE_VALIDATION_CHECK(this,
get_input_partial_shape(6).compatible(PartialShape{}) &&
get_input_partial_shape(7).compatible(PartialShape{}),
"Output scale and output zero point shape must be same and 1");
// AxisSet should be empty till we support channel wise quantization
NODE_VALIDATION_CHECK(this,
m_input_axes == AxisSet{} && m_filter_axes == AxisSet{} &&
m_output_axes == AxisSet{},
"Input, filter and output AxisSet should be empty");
const PartialShape& input_shape = get_input_partial_shape(0);
const PartialShape& filters_shape = get_input_partial_shape(1);
PartialShape result_shape;
result_shape = infer_convolution_forward(this,
input_shape,
m_data_dilation_strides,
m_padding_below,
m_padding_above,
filters_shape,
m_window_movement_strides,
m_window_dilation_strides);
NODE_VALIDATION_CHECK(
this,
get_output_element_type(0).compatible(get_input_element_type(OUTPUT_ZERO_POINT)),
"Output Zero point element type (",
get_input_element_type(OUTPUT_ZERO_POINT),
") must match output element type (",
get_output_element_type(0),
")");
set_output_type(0, m_output_type, result_shape);
}
shared_ptr<Node> op::QuantizedConvolution::clone_with_new_inputs(const OutputVector& new_args) const
{
check_new_args_count(this, new_args);
return shared_ptr<Node>(new QuantizedConvolution(new_args.at(0),
new_args.at(1),
get_window_movement_strides(),
get_window_dilation_strides(),
get_padding_below(),
get_padding_above(),
get_data_dilation_strides(),
new_args.at(2),
new_args.at(3),
new_args.at(4),
new_args.at(5),
new_args.at(6),
new_args.at(7),
m_output_type,
m_input_axes,
m_filter_axes,
m_output_axes));
}

View File

@@ -152,7 +152,6 @@ set(SRC
type_prop/prelu.cpp
type_prop/proposal.cpp
type_prop/quantize.cpp
type_prop/quantized_convolution.cpp
type_prop/quantized_dot.cpp
type_prop/range.cpp
type_prop/read_value.cpp
@@ -317,7 +316,6 @@ set(MULTI_TEST_SRC
backend/parameter_as_output.in.cpp
backend/power.in.cpp
backend/quantize_dequantize.in.cpp
backend/quantized_convolution.in.cpp
backend/quantized_dot.in.cpp
backend/range.in.cpp
backend/reduce_max.in.cpp

View File

@@ -1,83 +0,0 @@
//*****************************************************************************
// 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 "gtest/gtest.h"
#include "ngraph/ngraph.hpp"
#include "ngraph/runtime/tensor.hpp"
#include "runtime/backend.hpp"
#include "util/all_close.hpp"
#include "util/all_close_f.hpp"
#include "util/known_element_types.hpp"
#include "util/ndarray.hpp"
#include "util/test_control.hpp"
#include "util/test_tools.hpp"
NGRAPH_SUPPRESS_DEPRECATED_START
using namespace std;
using namespace ngraph;
static string s_manifest = "${MANIFEST}";
NGRAPH_TEST(${BACKEND_NAME}, quantized_conv_int32_output)
{
Shape shape_a{1, 1, 3, 4};
Shape shape_b{1, 1, 3, 3};
Shape shape_r{1, 1, 3, 4};
vector<uint8_t> a_data = {1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4};
vector<uint8_t> b_data = {1, 2, 3, 4, 5, 0, 0, 1, 2};
auto A = make_shared<op::Parameter>(element::u8, shape_a);
auto B = make_shared<op::Parameter>(element::u8, shape_b);
auto C = make_shared<op::Parameter>(element::f32, Shape{});
auto D = op::Constant::create(element::u8, Shape{}, {0});
auto E = make_shared<op::Parameter>(element::f32, Shape{});
auto F = op::Constant::create(element::u8, Shape{}, {0});
auto G = make_shared<op::Parameter>(element::f32, Shape{});
auto H = op::Constant::create(element::i32, Shape{}, {0});
auto CV = make_shared<op::QuantizedConvolution>(A,
B,
Strides{1, 1},
Strides{1, 1},
CoordinateDiff{1, 1},
CoordinateDiff{1, 1},
Strides{1, 1},
C,
D,
E,
F,
G,
H,
element::i32);
auto f = make_shared<Function>(NodeVector{CV}, ParameterVector{A, B, C, E, G});
auto backend = runtime::Backend::create("${BACKEND_NAME}");
// Create some tensors for input/output
auto a = backend->create_tensor(element::u8, shape_a);
copy_data(a, a_data);
auto b = backend->create_tensor(element::u8, shape_b);
copy_data(b, b_data);
auto c = backend->create_tensor(element::f32, Shape{});
copy_data(c, vector<float>{1.0f});
auto d = backend->create_tensor(element::f32, Shape{});
copy_data(d, vector<float>{1.0f});
auto e = backend->create_tensor(element::f32, Shape{});
copy_data(e, vector<float>{1.0f});
auto result = backend->create_tensor(element::i32, shape_r);
auto handle = backend->compile(f);
handle->call_with_validate({result}, {a, b, c, d, e});
EXPECT_EQ((vector<int32_t>{22, 34, 30, 32, 38, 72, 90, 43, 33, 52, 43, 39}),
read_vector<int32_t>(result));
}

View File

@@ -605,15 +605,6 @@ namespace
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_QuantizedConvolution()
{
op::QuantizedConvolution node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_QuantizedDot()
{
op::QuantizedDot node;

View File

@@ -1028,114 +1028,6 @@ protected:
break;
}
case OP_TYPEID::QuantizedConvolution:
{
const op::QuantizedConvolution* qc =
static_cast<const op::QuantizedConvolution*>(&node);
auto input_element_type = qc->get_input_element_type(0);
auto filter_element_type = qc->get_input_element_type(1);
auto output_element_type = qc->get_output_element_type(0);
if (input_element_type == element::u8 && filter_element_type == element::i8 &&
output_element_type == element::i8)
{
reference::convolution<uint8_t, int8_t, int8_t, int32_t>(
args[0]->get_data_ptr<const uint8_t>(),
args[1]->get_data_ptr<const int8_t>(),
out[0]->get_data_ptr<int8_t>(),
node.get_input_shape(0),
node.get_input_shape(1),
node.get_output_shape(0),
qc->get_window_movement_strides(),
qc->get_window_dilation_strides(),
qc->get_padding_below(),
qc->get_padding_above(),
qc->get_data_dilation_strides(),
args[2]->get_data_ptr<const float>(),
args[3]->get_data_ptr<const uint8_t>(),
args[4]->get_data_ptr<const float>(),
args[5]->get_data_ptr<const int8_t>(),
args[6]->get_data_ptr<const float>(),
args[7]->get_data_ptr<const int8_t>());
}
else if (input_element_type == element::u8 && filter_element_type == element::u8 &&
output_element_type == element::u8)
{
reference::convolution<uint8_t, uint8_t, uint8_t, int32_t>(
args[0]->get_data_ptr<const uint8_t>(),
args[1]->get_data_ptr<const uint8_t>(),
out[0]->get_data_ptr<uint8_t>(),
node.get_input_shape(0),
node.get_input_shape(1),
node.get_output_shape(0),
qc->get_window_movement_strides(),
qc->get_window_dilation_strides(),
qc->get_padding_below(),
qc->get_padding_above(),
qc->get_data_dilation_strides(),
args[2]->get_data_ptr<const float>(),
args[3]->get_data_ptr<const uint8_t>(),
args[4]->get_data_ptr<const float>(),
args[5]->get_data_ptr<const uint8_t>(),
args[6]->get_data_ptr<const float>(),
args[7]->get_data_ptr<const uint8_t>());
}
else if (input_element_type == element::u8 && filter_element_type == element::i8 &&
output_element_type == element::i32)
{
reference::convolution<uint8_t, int8_t, int32_t, int32_t>(
args[0]->get_data_ptr<const uint8_t>(),
args[1]->get_data_ptr<const int8_t>(),
out[0]->get_data_ptr<int32_t>(),
node.get_input_shape(0),
node.get_input_shape(1),
node.get_output_shape(0),
qc->get_window_movement_strides(),
qc->get_window_dilation_strides(),
qc->get_padding_below(),
qc->get_padding_above(),
qc->get_data_dilation_strides(),
args[2]->get_data_ptr<const float>(),
args[3]->get_data_ptr<const uint8_t>(),
args[4]->get_data_ptr<const float>(),
args[5]->get_data_ptr<const int8_t>(),
args[6]->get_data_ptr<const float>(),
args[7]->get_data_ptr<const int32_t>());
}
else if (input_element_type == element::u8 && filter_element_type == element::u8 &&
output_element_type == element::i32)
{
reference::convolution<uint8_t, uint8_t, int32_t, int32_t>(
args[0]->get_data_ptr<const uint8_t>(),
args[1]->get_data_ptr<const uint8_t>(),
out[0]->get_data_ptr<int32_t>(),
node.get_input_shape(0),
node.get_input_shape(1),
node.get_output_shape(0),
qc->get_window_movement_strides(),
qc->get_window_dilation_strides(),
qc->get_padding_below(),
qc->get_padding_above(),
qc->get_data_dilation_strides(),
args[2]->get_data_ptr<const float>(),
args[3]->get_data_ptr<const uint8_t>(),
args[4]->get_data_ptr<const float>(),
args[5]->get_data_ptr<const uint8_t>(),
args[6]->get_data_ptr<const float>(),
args[7]->get_data_ptr<const int32_t>());
}
else
{
std::stringstream ss;
ss << "unsupported element type";
throw std::runtime_error(ss.str());
}
break;
}
case OP_TYPEID::QuantizedDot:
{
const op::QuantizedDot* qd = static_cast<const op::QuantizedDot*>(&node);

View File

@@ -104,7 +104,6 @@ NGRAPH_OP(Power, ngraph::op)
NGRAPH_OP(PRelu, ngraph::op)
NGRAPH_OP(PriorBox, ngraph::op)
NGRAPH_OP(Quantize, ngraph::op)
NGRAPH_OP(QuantizedConvolution, ngraph::op)
NGRAPH_OP(QuantizedDot, ngraph::op)
NGRAPH_OP(Range, ngraph::op)
NGRAPH_OP(Relu, ngraph::op)

View File

@@ -1,791 +0,0 @@
//*****************************************************************************
// 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 "gtest/gtest.h"
#include "ngraph/ngraph.hpp"
#include "util/type_prop.hpp"
NGRAPH_SUPPRESS_DEPRECATED_START
using namespace std;
using namespace ngraph;
TEST(type_prop, quantized_conv_8_bit_output)
{
auto strides = Strides{1, 1};
auto dilation = Strides{1, 1};
auto padding_below = CoordinateDiff{1, 1};
auto padding_above = CoordinateDiff{1, 1};
element::Type f32 = element::f32;
element::Type i8 = element::i8;
element::Type u8 = element::u8;
element::Type input_type = u8;
element::Type filter_type = i8;
element::Type output_type = i8;
element::Type scale_type = f32;
element::Type input_zero_point_type = u8;
element::Type filter_zero_point_type = i8;
element::Type output_zero_point_type = i8;
Shape output_shape{64, 64, 220, 220};
AxisSet axes{};
auto input = make_shared<op::Parameter>(input_type, Shape{64, 3, 224, 224});
auto filter = make_shared<op::Parameter>(filter_type, Shape{64, 3, 7, 7});
auto scale = make_shared<op::Parameter>(scale_type, Shape{});
auto i8_zero_point = make_shared<op::Parameter>(element::i8, Shape{});
auto u8_zero_point = make_shared<op::Parameter>(element::u8, Shape{});
auto quant_conv = make_shared<op::QuantizedConvolution>(input,
filter,
strides,
dilation,
padding_below,
padding_above,
dilation,
scale,
u8_zero_point,
scale,
i8_zero_point,
scale,
i8_zero_point,
output_type,
axes,
axes,
axes);
ASSERT_EQ(quant_conv->get_element_type(), output_type);
ASSERT_EQ(quant_conv->get_shape(), output_shape);
}
TEST(type_prop, quantized_conv_32_bit_output)
{
auto strides = Strides{1, 1};
auto dilation = Strides{1, 1};
auto padding_below = CoordinateDiff{1, 1};
auto padding_above = CoordinateDiff{1, 1};
element::Type f32 = element::f32;
element::Type i8 = element::i8;
element::Type u8 = element::u8;
element::Type i32 = element::i32;
element::Type input_type = u8;
element::Type filter_type = i8;
element::Type output_type = i32;
element::Type scale_type = f32;
element::Type input_zero_point_type = u8;
element::Type filter_zero_point_type = i8;
element::Type output_zero_point_type = i8;
Shape output_shape{64, 64, 220, 220};
AxisSet axes{};
auto input = make_shared<op::Parameter>(input_type, Shape{64, 3, 224, 224});
auto filter = make_shared<op::Parameter>(filter_type, Shape{64, 3, 7, 7});
auto scale = make_shared<op::Parameter>(scale_type, Shape{});
auto i8_zero_point = make_shared<op::Parameter>(element::i8, Shape{});
auto u8_zero_point = make_shared<op::Parameter>(element::u8, Shape{});
auto quant_conv = make_shared<op::QuantizedConvolution>(input,
filter,
strides,
dilation,
padding_below,
padding_above,
dilation,
scale,
u8_zero_point,
scale,
i8_zero_point,
scale,
i8_zero_point,
output_type,
axes,
axes,
axes);
ASSERT_EQ(quant_conv->get_element_type(), output_type);
ASSERT_EQ(quant_conv->get_shape(), output_shape);
}
TEST(type_prop, quantized_conv_non_quantized_input_fails)
{
auto strides = Strides{1, 1};
auto dilation = Strides{1, 1};
auto padding_below = CoordinateDiff{1, 1};
auto padding_above = CoordinateDiff{1, 1};
element::Type f32 = element::f32;
element::Type i8 = element::i8;
element::Type u8 = element::u8;
element::Type input_type = f32;
element::Type filter_type = i8;
element::Type output_type = i8;
element::Type scale_type = f32;
element::Type input_zero_point_type = u8;
element::Type filter_zero_point_type = i8;
element::Type output_zero_point_type = i8;
Shape output_shape{64, 64, 220, 220};
AxisSet axes{};
auto input = make_shared<op::Parameter>(input_type, Shape{64, 3, 224, 224});
auto filter = make_shared<op::Parameter>(filter_type, Shape{64, 3, 7, 7});
auto scale = make_shared<op::Parameter>(scale_type, Shape{});
auto i8_zero_point = make_shared<op::Parameter>(element::i8, Shape{});
auto u8_zero_point = make_shared<op::Parameter>(element::u8, Shape{});
try
{
auto quant_conv = make_shared<op::QuantizedConvolution>(input,
filter,
strides,
dilation,
padding_below,
padding_above,
dilation,
scale,
u8_zero_point,
scale,
i8_zero_point,
scale,
i8_zero_point,
output_type,
axes,
axes,
axes);
FAIL() << "Attempt to use non-quantized input not detected";
}
catch (const NodeValidationFailure& error)
{
EXPECT_HAS_SUBSTRING(error.what(), "Input element type (f32) must be a quantized type");
}
catch (...)
{
FAIL() << "Deduced type check failed for unexpected reason";
}
}
TEST(type_prop, quantized_conv_non_quantized_filter_fails)
{
auto strides = Strides{1, 1};
auto dilation = Strides{1, 1};
auto padding_below = CoordinateDiff{1, 1};
auto padding_above = CoordinateDiff{1, 1};
element::Type f32 = element::f32;
element::Type i8 = element::i8;
element::Type u8 = element::u8;
element::Type input_type = u8;
element::Type filter_type = f32;
element::Type output_type = i8;
element::Type scale_type = f32;
element::Type input_zero_point_type = u8;
element::Type filter_zero_point_type = i8;
element::Type output_zero_point_type = i8;
Shape output_shape{64, 64, 220, 220};
AxisSet axes{};
auto input = make_shared<op::Parameter>(input_type, Shape{64, 3, 224, 224});
auto filter = make_shared<op::Parameter>(filter_type, Shape{64, 3, 7, 7});
auto scale = make_shared<op::Parameter>(scale_type, Shape{});
auto i8_zero_point = make_shared<op::Parameter>(element::i8, Shape{});
auto u8_zero_point = make_shared<op::Parameter>(element::u8, Shape{});
try
{
auto quant_conv = make_shared<op::QuantizedConvolution>(input,
filter,
strides,
dilation,
padding_below,
padding_above,
dilation,
scale,
u8_zero_point,
scale,
i8_zero_point,
scale,
i8_zero_point,
output_type,
axes,
axes,
axes);
FAIL() << "Attempt to use non-quantized filter not detected";
}
catch (const NodeValidationFailure& error)
{
EXPECT_HAS_SUBSTRING(error.what(), "Filter element type (f32) must be a quantized type");
}
catch (...)
{
FAIL() << "Deduced type check failed for unexpected reason";
}
}
TEST(type_prop, quantized_conv_dyn_output_fails)
{
auto strides = Strides{1, 1};
auto dilation = Strides{1, 1};
auto padding_below = CoordinateDiff{1, 1};
auto padding_above = CoordinateDiff{1, 1};
element::Type f32 = element::f32;
element::Type i8 = element::i8;
element::Type u8 = element::u8;
element::Type input_type = u8;
element::Type filter_type = f32;
element::Type output_type = element::dynamic;
element::Type scale_type = f32;
element::Type input_zero_point_type = u8;
element::Type filter_zero_point_type = i8;
element::Type output_zero_point_type = i8;
Shape output_shape{64, 64, 220, 220};
AxisSet axes{};
auto input = make_shared<op::Parameter>(input_type, Shape{64, 3, 224, 224});
auto filter = make_shared<op::Parameter>(filter_type, Shape{64, 3, 7, 7});
auto scale = make_shared<op::Parameter>(scale_type, Shape{});
auto i8_zero_point = make_shared<op::Parameter>(element::i8, Shape{});
auto u8_zero_point = make_shared<op::Parameter>(element::u8, Shape{});
try
{
auto quant_conv = make_shared<op::QuantizedConvolution>(input,
filter,
strides,
dilation,
padding_below,
padding_above,
dilation,
scale,
u8_zero_point,
scale,
i8_zero_point,
scale,
i8_zero_point,
output_type,
axes,
axes,
axes);
FAIL() << "Attempt to use dynamic output type not detected";
}
catch (const NodeValidationFailure& error)
{
EXPECT_HAS_SUBSTRING(error.what(), "Output element type must not be dynamic");
}
catch (...)
{
FAIL() << "Deduced type check failed for unexpected reason";
}
}
TEST(type_prop, quantized_conv_non_floating_point_scale_fails)
{
auto strides = Strides{1, 1};
auto dilation = Strides{1, 1};
auto padding_below = CoordinateDiff{1, 1};
auto padding_above = CoordinateDiff{1, 1};
element::Type f32 = element::f32;
element::Type i8 = element::i8;
element::Type u8 = element::u8;
element::Type input_type = u8;
element::Type filter_type = i8;
element::Type output_type = i8;
element::Type scale_type = i8;
element::Type input_zero_point_type = u8;
element::Type filter_zero_point_type = i8;
element::Type output_zero_point_type = i8;
Shape output_shape{64, 64, 220, 220};
AxisSet axes{};
auto input = make_shared<op::Parameter>(input_type, Shape{64, 3, 224, 224});
auto filter = make_shared<op::Parameter>(filter_type, Shape{64, 3, 7, 7});
auto scale = make_shared<op::Parameter>(scale_type, Shape{});
auto i8_zero_point = make_shared<op::Parameter>(element::i8, Shape{});
auto u8_zero_point = make_shared<op::Parameter>(element::u8, Shape{});
try
{
auto quant_conv = make_shared<op::QuantizedConvolution>(input,
filter,
strides,
dilation,
padding_below,
padding_above,
dilation,
scale,
u8_zero_point,
scale,
i8_zero_point,
scale,
i8_zero_point,
output_type,
axes,
axes,
axes);
FAIL() << "Attempt to use non floating point scale not detected";
}
catch (const NodeValidationFailure& error)
{
EXPECT_HAS_SUBSTRING(error.what(), "Scale must be a floating point number");
}
catch (...)
{
FAIL() << "Deduced type check failed for unexpected reason";
}
}
TEST(type_prop, quantized_conv_input_zero_point_type_mismatch_fails)
{
auto strides = Strides{1, 1};
auto dilation = Strides{1, 1};
auto padding_below = CoordinateDiff{1, 1};
auto padding_above = CoordinateDiff{1, 1};
element::Type f32 = element::f32;
element::Type i8 = element::i8;
element::Type u8 = element::u8;
element::Type input_type = u8;
element::Type filter_type = i8;
element::Type output_type = i8;
element::Type scale_type = f32;
element::Type input_zero_point_type = i8;
element::Type filter_zero_point_type = i8;
element::Type output_zero_point_type = i8;
Shape output_shape{64, 64, 220, 220};
AxisSet axes{};
auto input = make_shared<op::Parameter>(input_type, Shape{64, 3, 224, 224});
auto filter = make_shared<op::Parameter>(filter_type, Shape{64, 3, 7, 7});
auto scale = make_shared<op::Parameter>(scale_type, Shape{});
auto input_zero_point = make_shared<op::Parameter>(input_zero_point_type, Shape{});
auto filter_zero_point = make_shared<op::Parameter>(filter_zero_point_type, Shape{});
auto output_zero_point = make_shared<op::Parameter>(output_zero_point_type, Shape{});
try
{
auto quant_conv = make_shared<op::QuantizedConvolution>(input,
filter,
strides,
dilation,
padding_below,
padding_above,
dilation,
scale,
input_zero_point,
scale,
filter_zero_point,
scale,
output_zero_point,
output_type,
axes,
axes,
axes);
FAIL() << "Attempt to use zero point type different from input type not detected";
}
catch (const NodeValidationFailure& error)
{
EXPECT_HAS_SUBSTRING(
error.what(), "Input Zero point element type (i8) must match input element type (u8)");
}
catch (...)
{
FAIL() << "Deduced type check failed for unexpected reason";
}
}
TEST(type_prop, quantized_conv_filter_zero_point_type_mismatch_fails)
{
auto strides = Strides{1, 1};
auto dilation = Strides{1, 1};
auto padding_below = CoordinateDiff{1, 1};
auto padding_above = CoordinateDiff{1, 1};
element::Type f32 = element::f32;
element::Type i8 = element::i8;
element::Type u8 = element::u8;
element::Type input_type = u8;
element::Type filter_type = i8;
element::Type output_type = i8;
element::Type scale_type = f32;
element::Type input_zero_point_type = u8;
element::Type filter_zero_point_type = u8;
element::Type output_zero_point_type = i8;
Shape output_shape{64, 64, 220, 220};
AxisSet axes{};
auto input = make_shared<op::Parameter>(input_type, Shape{64, 3, 224, 224});
auto filter = make_shared<op::Parameter>(filter_type, Shape{64, 3, 7, 7});
auto scale = make_shared<op::Parameter>(scale_type, Shape{});
auto input_zero_point = make_shared<op::Parameter>(input_zero_point_type, Shape{});
auto filter_zero_point = make_shared<op::Parameter>(filter_zero_point_type, Shape{});
auto output_zero_point = make_shared<op::Parameter>(output_zero_point_type, Shape{});
try
{
auto quant_conv = make_shared<op::QuantizedConvolution>(input,
filter,
strides,
dilation,
padding_below,
padding_above,
dilation,
scale,
input_zero_point,
scale,
filter_zero_point,
scale,
output_zero_point,
output_type,
axes,
axes,
axes);
FAIL() << "Attempt to use zero point type different from filter type not detected";
}
catch (const NodeValidationFailure& error)
{
EXPECT_HAS_SUBSTRING(
error.what(),
"Filter Zero point element type (u8) must match filter element type (i8)");
}
catch (...)
{
FAIL() << "Deduced type check failed for unexpected reason";
}
}
TEST(type_prop, quantized_conv_non_scalar_input_zero_point_fails)
{
auto strides = Strides{1, 1};
auto dilation = Strides{1, 1};
auto padding_below = CoordinateDiff{1, 1};
auto padding_above = CoordinateDiff{1, 1};
element::Type f32 = element::f32;
element::Type i8 = element::i8;
element::Type u8 = element::u8;
element::Type input_type = u8;
element::Type filter_type = i8;
element::Type output_type = i8;
element::Type scale_type = f32;
element::Type input_zero_point_type = u8;
element::Type filter_zero_point_type = i8;
element::Type output_zero_point_type = i8;
Shape output_shape{64, 64, 220, 220};
AxisSet axes{};
auto input = make_shared<op::Parameter>(input_type, Shape{64, 3, 224, 224});
auto filter = make_shared<op::Parameter>(filter_type, Shape{64, 3, 7, 7});
auto scale = make_shared<op::Parameter>(scale_type, Shape{});
auto input_zero_point = make_shared<op::Parameter>(input_zero_point_type, Shape{1, 2});
auto filter_zero_point = make_shared<op::Parameter>(filter_zero_point_type, Shape{});
auto output_zero_point = make_shared<op::Parameter>(output_zero_point_type, Shape{});
try
{
auto quant_conv = make_shared<op::QuantizedConvolution>(input,
filter,
strides,
dilation,
padding_below,
padding_above,
dilation,
scale,
input_zero_point,
scale,
filter_zero_point,
scale,
output_zero_point,
output_type,
axes,
axes,
axes);
FAIL() << "Attempt to use non scalar input zero point not detected";
}
catch (const NodeValidationFailure& error)
{
EXPECT_HAS_SUBSTRING(error.what(),
"Input scale and input zero point shape must be same and 1");
}
catch (...)
{
FAIL() << "Deduced type check failed for unexpected reason";
}
}
TEST(type_prop, quantized_conv_non_scalar_filter_zero_point_fails)
{
auto strides = Strides{1, 1};
auto dilation = Strides{1, 1};
auto padding_below = CoordinateDiff{1, 1};
auto padding_above = CoordinateDiff{1, 1};
element::Type f32 = element::f32;
element::Type i8 = element::i8;
element::Type u8 = element::u8;
element::Type input_type = u8;
element::Type filter_type = i8;
element::Type output_type = i8;
element::Type scale_type = f32;
element::Type input_zero_point_type = u8;
element::Type filter_zero_point_type = i8;
element::Type output_zero_point_type = i8;
Shape output_shape{64, 64, 220, 220};
AxisSet axes{};
auto input = make_shared<op::Parameter>(input_type, Shape{64, 3, 224, 224});
auto filter = make_shared<op::Parameter>(filter_type, Shape{64, 3, 7, 7});
auto scale = make_shared<op::Parameter>(scale_type, Shape{});
auto input_zero_point = make_shared<op::Parameter>(input_zero_point_type, Shape{});
auto filter_zero_point = make_shared<op::Parameter>(filter_zero_point_type, Shape{1, 2});
auto output_zero_point = make_shared<op::Parameter>(output_zero_point_type, Shape{});
try
{
auto quant_conv = make_shared<op::QuantizedConvolution>(input,
filter,
strides,
dilation,
padding_below,
padding_above,
dilation,
scale,
input_zero_point,
scale,
filter_zero_point,
scale,
output_zero_point,
output_type,
axes,
axes,
axes);
FAIL() << "Attempt to use non scalar filter zero point not detected";
}
catch (const NodeValidationFailure& error)
{
EXPECT_HAS_SUBSTRING(error.what(),
"Filter scale and filter zero point shape must be same and 1");
}
catch (...)
{
FAIL() << "Deduced type check failed for unexpected reason";
}
}
TEST(type_prop, quantized_conv_non_scalar_output_zero_point_fails)
{
auto strides = Strides{1, 1};
auto dilation = Strides{1, 1};
auto padding_below = CoordinateDiff{1, 1};
auto padding_above = CoordinateDiff{1, 1};
element::Type f32 = element::f32;
element::Type i8 = element::i8;
element::Type u8 = element::u8;
element::Type input_type = u8;
element::Type filter_type = i8;
element::Type output_type = i8;
element::Type scale_type = f32;
element::Type input_zero_point_type = u8;
element::Type filter_zero_point_type = i8;
element::Type output_zero_point_type = i8;
Shape output_shape{64, 64, 220, 220};
AxisSet axes{};
auto input = make_shared<op::Parameter>(input_type, Shape{64, 3, 224, 224});
auto filter = make_shared<op::Parameter>(filter_type, Shape{64, 3, 7, 7});
auto scale = make_shared<op::Parameter>(scale_type, Shape{});
auto input_zero_point = make_shared<op::Parameter>(input_zero_point_type, Shape{});
auto filter_zero_point = make_shared<op::Parameter>(filter_zero_point_type, Shape{});
auto output_zero_point = make_shared<op::Parameter>(output_zero_point_type, Shape{1, 2});
try
{
auto quant_conv = make_shared<op::QuantizedConvolution>(input,
filter,
strides,
dilation,
padding_below,
padding_above,
dilation,
scale,
input_zero_point,
scale,
filter_zero_point,
scale,
output_zero_point,
output_type,
axes,
axes,
axes);
FAIL() << "Attempt to use non scalar output zero point not detected";
}
catch (const NodeValidationFailure& error)
{
EXPECT_HAS_SUBSTRING(error.what(),
"Output scale and output zero point shape must be same and 1");
}
catch (...)
{
FAIL() << "Deduced type check failed for unexpected reason";
}
}
TEST(type_prop, quantized_conv_non_empty_input_axes)
{
auto strides = Strides{1, 1};
auto dilation = Strides{1, 1};
auto padding_below = CoordinateDiff{1, 1};
auto padding_above = CoordinateDiff{1, 1};
element::Type f32 = element::f32;
element::Type i8 = element::i8;
element::Type u8 = element::u8;
element::Type input_type = u8;
element::Type filter_type = i8;
element::Type output_type = i8;
element::Type scale_type = f32;
element::Type input_zero_point_type = u8;
element::Type filter_zero_point_type = i8;
element::Type output_zero_point_type = i8;
Shape output_shape{64, 64, 220, 220};
AxisSet axes{};
auto input = make_shared<op::Parameter>(input_type, Shape{64, 3, 224, 224});
auto filter = make_shared<op::Parameter>(filter_type, Shape{64, 3, 7, 7});
auto scale = make_shared<op::Parameter>(scale_type, Shape{});
auto input_zero_point = make_shared<op::Parameter>(input_zero_point_type, Shape{});
auto filter_zero_point = make_shared<op::Parameter>(filter_zero_point_type, Shape{});
auto output_zero_point = make_shared<op::Parameter>(output_zero_point_type, Shape{});
try
{
auto quant_conv = make_shared<op::QuantizedConvolution>(input,
filter,
strides,
dilation,
padding_below,
padding_above,
dilation,
scale,
input_zero_point,
scale,
filter_zero_point,
scale,
output_zero_point,
output_type,
AxisSet{1},
axes,
axes);
FAIL() << "Attempt to use non empty input axes not detected";
}
catch (const NodeValidationFailure& error)
{
EXPECT_HAS_SUBSTRING(error.what(), "Input, filter and output AxisSet should be empty");
}
catch (...)
{
FAIL() << "Deduced type check failed for unexpected reason";
}
}
TEST(type_prop, quantized_conv_non_empty_filter_axes)
{
auto strides = Strides{1, 1};
auto dilation = Strides{1, 1};
auto padding_below = CoordinateDiff{1, 1};
auto padding_above = CoordinateDiff{1, 1};
element::Type f32 = element::f32;
element::Type i8 = element::i8;
element::Type u8 = element::u8;
element::Type input_type = u8;
element::Type filter_type = i8;
element::Type output_type = i8;
element::Type scale_type = f32;
element::Type input_zero_point_type = u8;
element::Type filter_zero_point_type = i8;
element::Type output_zero_point_type = i8;
Shape output_shape{64, 64, 220, 220};
AxisSet axes{};
auto input = make_shared<op::Parameter>(input_type, Shape{64, 3, 224, 224});
auto filter = make_shared<op::Parameter>(filter_type, Shape{64, 3, 7, 7});
auto scale = make_shared<op::Parameter>(scale_type, Shape{});
auto input_zero_point = make_shared<op::Parameter>(input_zero_point_type, Shape{});
auto filter_zero_point = make_shared<op::Parameter>(filter_zero_point_type, Shape{});
auto output_zero_point = make_shared<op::Parameter>(output_zero_point_type, Shape{});
try
{
auto quant_conv = make_shared<op::QuantizedConvolution>(input,
filter,
strides,
dilation,
padding_below,
padding_above,
dilation,
scale,
input_zero_point,
scale,
filter_zero_point,
scale,
output_zero_point,
output_type,
axes,
AxisSet{1},
axes);
FAIL() << "Attempt to use non empty filter axes not detected";
}
catch (const NodeValidationFailure& error)
{
EXPECT_HAS_SUBSTRING(error.what(), "Input, filter and output AxisSet should be empty");
}
catch (...)
{
FAIL() << "Deduced type check failed for unexpected reason";
}
}
TEST(type_prop, quantized_conv_non_empty_output_axes)
{
auto strides = Strides{1, 1};
auto dilation = Strides{1, 1};
auto padding_below = CoordinateDiff{1, 1};
auto padding_above = CoordinateDiff{1, 1};
element::Type f32 = element::f32;
element::Type i8 = element::i8;
element::Type u8 = element::u8;
element::Type input_type = u8;
element::Type filter_type = i8;
element::Type output_type = i8;
element::Type scale_type = f32;
element::Type input_zero_point_type = u8;
element::Type filter_zero_point_type = i8;
element::Type output_zero_point_type = i8;
Shape output_shape{64, 64, 220, 220};
AxisSet axes{};
auto input = make_shared<op::Parameter>(input_type, Shape{64, 3, 224, 224});
auto filter = make_shared<op::Parameter>(filter_type, Shape{64, 3, 7, 7});
auto scale = make_shared<op::Parameter>(scale_type, Shape{});
auto input_zero_point = make_shared<op::Parameter>(input_zero_point_type, Shape{});
auto filter_zero_point = make_shared<op::Parameter>(filter_zero_point_type, Shape{});
auto output_zero_point = make_shared<op::Parameter>(output_zero_point_type, Shape{});
try
{
auto quant_conv = make_shared<op::QuantizedConvolution>(input,
filter,
strides,
dilation,
padding_below,
padding_above,
dilation,
scale,
input_zero_point,
scale,
filter_zero_point,
scale,
output_zero_point,
output_type,
axes,
axes,
AxisSet{1});
FAIL() << "Attempt to use non empty output axes not detected";
}
catch (const NodeValidationFailure& error)
{
EXPECT_HAS_SUBSTRING(error.what(), "Input, filter and output AxisSet should be empty");
}
catch (...)
{
FAIL() << "Deduced type check failed for unexpected reason";
}
}