[LPT] Dequantization constant output precision handling extending (#2987)
* [LPT] moveDequantizationAfter fix * [LPT] ConcatTransformation fix: only intermediate operations are handled
This commit is contained in:
parent
27c97a037f
commit
518c0b6bd7
@ -30,6 +30,7 @@ public:
|
||||
std::unordered_map<std::string, std::shared_ptr<ngraph::Node>> layers;
|
||||
|
||||
private:
|
||||
bool atLeastOneIsIntermediate(const std::shared_ptr<ngraph::Node>& node) const;
|
||||
bool fillSubgraphForQuantization(const std::shared_ptr<ngraph::opset1::FakeQuantize>& fakeQuantize, std::unordered_set<std::string>& handledLayers);
|
||||
bool fillSubgraphForIntermediate(const std::shared_ptr<ngraph::Node>& intermediate, std::unordered_set<std::string>& handledLayers);
|
||||
bool fill(const std::shared_ptr<ngraph::Node>& concat, std::unordered_set<std::string>& handledLayers);
|
||||
|
@ -138,7 +138,7 @@ bool ConcatTransformation::transform(TransformationContext& context, ngraph::pat
|
||||
dequantizationSub,
|
||||
subgraph.quantizationLayers[0]->get_output_element_type(0),
|
||||
subgraph.quantizationLayers[0]->get_output_shape(0),
|
||||
dataPrecision.precision,
|
||||
updatePrecisions ? dataPrecision.precision : subgraph.quantizationLayers[0]->get_output_element_type(0),
|
||||
dataPrecision.min,
|
||||
dataPrecision.max);
|
||||
|
||||
|
@ -951,14 +951,38 @@ NetworkHelper::InsertDequantizationResult NetworkHelper::moveDequantizationAfter
|
||||
parent = std::make_shared<DequantizationConvert>(parent, dequantization.convert->get_output_element_type(0));
|
||||
ngraph::copy_runtime_info({ newOperation, parent }, parent);
|
||||
}
|
||||
|
||||
if (moveSubtract && (dequantization.subtract != nullptr)) {
|
||||
auto subtractConstant = dequantization.subtract->get_input_node_shared_ptr(1);
|
||||
parent = std::make_shared<DequantizationSubtract>(parent, subtractConstant);
|
||||
const element::Type parentPrecision = parent->get_output_element_type(0);
|
||||
if (parentPrecision.bitwidth() < subtractConstant->output(0).get_element_type().bitwidth()) {
|
||||
THROW_IE_LPT_EXCEPTION(*parent) <<
|
||||
"unexpected precisions: on data " << parent->get_friendly_name() << ":" << parentPrecision <<
|
||||
", subtract dequantization constant " << subtractConstant->get_friendly_name() << ":" << subtractConstant->output(0).get_element_type();
|
||||
}
|
||||
|
||||
parent = std::make_shared<DequantizationSubtract>(
|
||||
parent,
|
||||
subtractConstant->output(0).get_element_type() == parentPrecision ?
|
||||
subtractConstant :
|
||||
fold<opset1::Convert>(subtractConstant->output(0), parentPrecision));
|
||||
ngraph::copy_runtime_info({ newOperation, parent }, parent);
|
||||
}
|
||||
|
||||
if (dequantization.multiply != nullptr) {
|
||||
auto multiplyConstant = dequantization.multiply->get_input_node_shared_ptr(1);
|
||||
parent = std::make_shared<DequantizationMultiply>(parent, multiplyConstant);
|
||||
const element::Type parentPrecision = parent->get_output_element_type(0);
|
||||
if (parentPrecision.bitwidth() < multiplyConstant->output(0).get_element_type().bitwidth()) {
|
||||
THROW_IE_LPT_EXCEPTION(*parent) <<
|
||||
"unexpected precisions: on data " << parent->get_friendly_name() << ":" << parentPrecision <<
|
||||
", multiply dequantization constant " << multiplyConstant->get_friendly_name() << ":" << multiplyConstant->output(0).get_element_type();
|
||||
}
|
||||
|
||||
parent = std::make_shared<DequantizationMultiply>(
|
||||
parent,
|
||||
multiplyConstant->output(0).get_element_type() == parentPrecision ?
|
||||
multiplyConstant :
|
||||
fold<opset1::Convert>(multiplyConstant->output(0), parentPrecision));
|
||||
ngraph::copy_runtime_info({ newOperation, parent }, parent);
|
||||
}
|
||||
replace_node(operation, parent);
|
||||
|
@ -36,6 +36,10 @@ bool isQuantizationPerChannel(const std::shared_ptr<ngraph::Node>& node) {
|
||||
const Shape& in = input.get_shape();
|
||||
const Shape& out = node->output(0).get_shape();
|
||||
for (size_t i = 0; i < 2; ++i) {
|
||||
if ((i >= in.size()) || (i >= out.size())) {
|
||||
// all previous dimensions are equal
|
||||
return true;
|
||||
}
|
||||
if (in[i] != out[i]) {
|
||||
return false;
|
||||
}
|
||||
@ -86,6 +90,28 @@ bool Subgraph::fillSubgraphForQuantization(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Subgraph::atLeastOneIsIntermediate(const std::shared_ptr<ngraph::Node>& node) const {
|
||||
for (size_t index = 0; index < node->get_output_size(); ++index) {
|
||||
const auto childInputs = node->get_output_target_inputs(index);
|
||||
for (const auto childInput : childInputs) {
|
||||
auto child = childInput.get_node()->shared_from_this();
|
||||
if (as_type_ptr<opset1::Concat>(child)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!layerTransformationsManager->isPrecisionPreserved(child) || !isQuantizationPerChannel(child)) {
|
||||
// child branch is out of subgraph
|
||||
continue;
|
||||
}
|
||||
|
||||
if (atLeastOneIsIntermediate(child)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Subgraph::fill(const std::shared_ptr<ngraph::Node>& layer, std::unordered_set<std::string>& handledLayers) {
|
||||
// if at least one parent is handled incorrectly then subgraph is not in low precision
|
||||
for (size_t index = 0; index < layer->get_input_size(); ++index) {
|
||||
@ -138,6 +164,11 @@ bool Subgraph::fill(const std::shared_ptr<ngraph::Node>& layer, std::unordered_s
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// check if children branches between Concat operations
|
||||
if (!atLeastOneIsIntermediate(child)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::shared_ptr<ngraph::opset1::FakeQuantize> fakeQuantizeChild = ngraph::as_type_ptr<ngraph::opset1::FakeQuantize>(child);
|
||||
if (fakeQuantizeChild != nullptr) {
|
||||
//
|
||||
@ -175,4 +206,4 @@ bool Subgraph::fillSubgraphForConcat(const std::shared_ptr<ngraph::opset1::Conca
|
||||
|
||||
} // namespace low_precision
|
||||
} // namespace pass
|
||||
} // namespace ngraph
|
||||
} // namespace ngraph
|
||||
|
@ -104,6 +104,11 @@ public:
|
||||
transform.add<ngraph::pass::low_precision::ClampTransformation, ngraph::opset1::Clamp>(testValues.params);
|
||||
transform.transform(actualFunction);
|
||||
|
||||
if (!updatePrecisions) {
|
||||
// there is no Convert operation after MaxPool in FP32
|
||||
testValues.result.dequantizationOperations2.convert = {};
|
||||
}
|
||||
|
||||
referenceFunction = ngraph::builder::subgraph::ConcatFunction::getReferenceWithDifferentPrecisionOnChilds(
|
||||
precision,
|
||||
testValues.inputShape,
|
||||
|
@ -0,0 +1,214 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "layer_transformation.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <transformations/utils/utils.hpp>
|
||||
#include <transformations/init_node_info.hpp>
|
||||
#include <low_precision/transformer.hpp>
|
||||
#include <low_precision/concat.hpp>
|
||||
#include <low_precision/concat_multi_channels.hpp>
|
||||
#include <low_precision/max_pool.hpp>
|
||||
#include <low_precision/reshape.hpp>
|
||||
|
||||
#include "common_test_utils/ngraph_test_utils.hpp"
|
||||
#include "ngraph_functions/low_precision_transformations/concat_function.hpp"
|
||||
#include "ngraph_functions/low_precision_transformations/common/fake_quantize_on_data.hpp"
|
||||
#include "simple_low_precision_transformer.hpp"
|
||||
|
||||
using namespace testing;
|
||||
using namespace ngraph;
|
||||
using namespace ngraph::pass;
|
||||
|
||||
namespace {
|
||||
|
||||
class ConcatTransformationActualValues {
|
||||
public:
|
||||
ngraph::builder::subgraph::FakeQuantizeOnDataWithConstant fakeQuantize1;
|
||||
ngraph::builder::subgraph::FakeQuantizeOnDataWithConstant fakeQuantize2;
|
||||
ngraph::builder::subgraph::FakeQuantizeOnDataWithConstant fakeQuantize3;
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const ConcatTransformationActualValues& values) {
|
||||
return out << "_" << values.fakeQuantize1 << "_" << values.fakeQuantize2;
|
||||
}
|
||||
|
||||
class ConcatTransformationResultValues {
|
||||
public:
|
||||
ngraph::builder::subgraph::FakeQuantizeOnDataWithConstant fakeQuantize1;
|
||||
ngraph::builder::subgraph::FakeQuantizeOnDataWithConstant fakeQuantize2;
|
||||
ngraph::builder::subgraph::FakeQuantizeOnDataWithConstant fakeQuantize3;
|
||||
ngraph::builder::subgraph::DequantizationOperations dequantizationOperations;
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const ConcatTransformationResultValues& values) {
|
||||
return out << "_" << values.fakeQuantize1 << "_" << values.fakeQuantize2 << "_" << values.fakeQuantize3 << "_" << values.dequantizationOperations;
|
||||
}
|
||||
|
||||
class ConcatTransformationTestValues {
|
||||
public:
|
||||
ngraph::pass::low_precision::LayerTransformation::Params params;
|
||||
ConcatTransformationActualValues actual;
|
||||
ConcatTransformationResultValues result;
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const ConcatTransformationTestValues& values) {
|
||||
return out << "_" << values.actual << "_" << values.result;
|
||||
}
|
||||
|
||||
typedef std::tuple <
|
||||
ngraph::element::Type,
|
||||
bool,
|
||||
ngraph::Shape,
|
||||
ConcatTransformationTestValues
|
||||
> ConcatTransformationParams;
|
||||
|
||||
class ConcatWithReshapeAtTheEndTransformation : public LayerTransformation, public testing::WithParamInterface<ConcatTransformationParams> {
|
||||
public:
|
||||
void SetUp() override {
|
||||
const ngraph::element::Type precision = std::get<0>(GetParam());
|
||||
const bool updatePrecisions = std::get<1>(GetParam());
|
||||
const ngraph::Shape shape = std::get<2>(GetParam());
|
||||
ConcatTransformationTestValues testValues = std::get<3>(GetParam());
|
||||
|
||||
testValues.params.updatePrecisions = updatePrecisions;
|
||||
if (!updatePrecisions) {
|
||||
testValues.result.fakeQuantize1.outputPrecision = testValues.actual.fakeQuantize1.outputPrecision;
|
||||
testValues.result.fakeQuantize2.outputPrecision = testValues.actual.fakeQuantize2.outputPrecision;
|
||||
testValues.result.fakeQuantize3.outputPrecision = testValues.actual.fakeQuantize3.outputPrecision;
|
||||
}
|
||||
|
||||
actualFunction = ngraph::builder::subgraph::ConcatFunction::getOriginalWithReshapeAtTheEndTransformation(
|
||||
precision,
|
||||
shape,
|
||||
testValues.actual.fakeQuantize1,
|
||||
testValues.actual.fakeQuantize2,
|
||||
testValues.actual.fakeQuantize3);
|
||||
|
||||
SimpleLowPrecisionTransformer transform;
|
||||
transform.add<ngraph::pass::low_precision::ConcatMultiChannelsTransformation, ngraph::opset1::Concat>(testValues.params);
|
||||
transform.add<ngraph::pass::low_precision::MaxPoolTransformation, ngraph::opset1::MaxPool>(testValues.params);
|
||||
transform.add<ngraph::pass::low_precision::ReshapeTransformation, ngraph::opset1::Reshape>(testValues.params);
|
||||
transform.transform(actualFunction);
|
||||
|
||||
if (!testValues.params.updatePrecisions) {
|
||||
// there is no Convert operation after MaxPool in FP32
|
||||
testValues.result.dequantizationOperations.convert = {};
|
||||
}
|
||||
|
||||
referenceFunction = ngraph::builder::subgraph::ConcatFunction::getReferenceWithReshapeAtTheEndTransformation(
|
||||
precision,
|
||||
shape,
|
||||
testValues.result.fakeQuantize1,
|
||||
testValues.result.fakeQuantize2,
|
||||
testValues.result.fakeQuantize3,
|
||||
testValues.result.dequantizationOperations);
|
||||
}
|
||||
|
||||
static std::string getTestCaseName(testing::TestParamInfo<ConcatTransformationParams> obj) {
|
||||
const ngraph::element::Type precision = std::get<0>(obj.param);
|
||||
const bool updatePrecision = std::get<1>(obj.param);
|
||||
const ngraph::Shape shape = std::get<2>(obj.param);
|
||||
const ConcatTransformationTestValues testValues = std::get<3>(obj.param);
|
||||
|
||||
std::ostringstream result;
|
||||
result <<
|
||||
LayerTransformation::getTestCaseNameByParams(precision, shape, testValues.params) << "_" <<
|
||||
(updatePrecision ? "updatePrecision_" : "notUpdatePrecision_") <<
|
||||
testValues.actual << "_" <<
|
||||
testValues.result << "_";
|
||||
return result.str();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_P(ConcatWithReshapeAtTheEndTransformation, CompareFunctions) {
|
||||
actualFunction->validate_nodes_and_infer_types();
|
||||
auto res = compare_functions(referenceFunction, actualFunction, true, true, true);
|
||||
ASSERT_TRUE(res.first) << res.second;
|
||||
}
|
||||
|
||||
const std::vector<ngraph::element::Type> precisions = {
|
||||
ngraph::element::f32,
|
||||
};
|
||||
|
||||
const std::vector<bool> updatePrecisions = { true, false };
|
||||
|
||||
const std::vector<ConcatTransformationTestValues> testValues = {
|
||||
{
|
||||
LayerTransformation::createParamsU8I8(),
|
||||
{
|
||||
{ 256ul, {}, {0.f}, {2.55f}, {0.f}, {2.55f} },
|
||||
{ 256ul, {}, {0.f}, {2.55f}, {0.f}, {2.55f} },
|
||||
{ 256ul, {}, {0.f}, {2.55f}, {0.f}, {2.55f} },
|
||||
},
|
||||
{
|
||||
{ 256ul, {}, {0.f}, {2.55f}, {0.f}, {255.f}, ngraph::element::u8 },
|
||||
{ 256ul, {}, {0.f}, {2.55f}, {0.f}, {255.f}, ngraph::element::u8 },
|
||||
{ 256ul, {}, {0.f}, {2.55f}, {0.f}, {255.f}, ngraph::element::u8 },
|
||||
{ ngraph::element::f32, {}, { 0.01f } }
|
||||
}
|
||||
},
|
||||
{
|
||||
LayerTransformation::createParamsU8I8(),
|
||||
{
|
||||
{
|
||||
256ul,
|
||||
{{1, 3, 1, 1}, {1, 3, 1, 1}, {1, 3, 1, 1}, {1, 3, 1, 1}},
|
||||
{0.f, 0.f, 0.f}, {2.55f / 1.f, 2.55f / 2.f, 2.55f / 3.f}, {0.f, 0.f, 0.f}, {2.55f / 1.f, 2.55f / 2.f, 2.55f / 3.f}
|
||||
},
|
||||
{
|
||||
256ul,
|
||||
{{1, 3, 1, 1}, {1, 3, 1, 1}, {1, 3, 1, 1}, {1, 3, 1, 1}},
|
||||
{0.f, 0.f, 0.f}, {2.55f / 1.f, 2.55f / 2.f, 2.55f / 3.f}, {0.f, 0.f, 0.f}, {2.55f / 1.f, 2.55f / 2.f, 2.55f / 3.f}
|
||||
},
|
||||
{
|
||||
256ul,
|
||||
{{1, 3, 1, 1}, {1, 3, 1, 1}, {1, 3, 1, 1}, {1, 3, 1, 1}},
|
||||
{0.f, 0.f, 0.f}, {2.55f / 1.f, 2.55f / 2.f, 2.55f / 3.f}, {0.f, 0.f, 0.f}, {2.55f / 1.f, 2.55f / 2.f, 2.55f / 3.f}
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
256ul,
|
||||
{{1, 3, 1, 1}, {1, 3, 1, 1}, {}, {}},
|
||||
{0.f, 0.f, 0.f}, {2.55f / 1.f, 2.55f / 2.f, 2.55f / 3.f}, {0.f}, {255.f}, ngraph::element::u8
|
||||
},
|
||||
{
|
||||
256ul,
|
||||
{{1, 3, 1, 1}, {1, 3, 1, 1}, {}, {}},
|
||||
{0.f, 0.f, 0.f}, {2.55f / 1.f, 2.55f / 2.f, 2.55f / 3.f}, {0.f}, {255.f},
|
||||
ngraph::element::u8
|
||||
},
|
||||
{
|
||||
256ul,
|
||||
{{1, 3, 1, 1}, {1, 3, 1, 1}, {}, {}},
|
||||
{0.f, 0.f, 0.f}, {2.55f / 1.f, 2.55f / 2.f, 2.55f / 3.f}, {0.f}, {255.f},
|
||||
ngraph::element::u8
|
||||
},
|
||||
{ ngraph::element::f32, {}, {{ 0.01f, 0.01f / 2.f, 0.01f / 3.f, 0.01f, 0.01f / 2.f, 0.01f / 3.f, 0.01f, 0.01f / 2.f, 0.01f / 3.f }} }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const std::vector<ngraph::Shape> shapes = {
|
||||
{ 1, 3, 9, 9 },
|
||||
{ 4, 3, 9, 9 }
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
LPT,
|
||||
ConcatWithReshapeAtTheEndTransformation,
|
||||
::testing::Combine(
|
||||
::testing::ValuesIn(precisions),
|
||||
::testing::ValuesIn(updatePrecisions),
|
||||
::testing::ValuesIn(shapes),
|
||||
::testing::ValuesIn(testValues)),
|
||||
ConcatWithReshapeAtTheEndTransformation::getTestCaseName);
|
||||
} // namespace
|
@ -0,0 +1,183 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "layer_transformation.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <utility>
|
||||
#include <transformations/utils/utils.hpp>
|
||||
#include <transformations/init_node_info.hpp>
|
||||
#include <low_precision/network_helper.hpp>
|
||||
|
||||
#include "common_test_utils/ngraph_test_utils.hpp"
|
||||
#include "ngraph_functions/low_precision_transformations/move_dequantization_after_with_int_constant_function.hpp"
|
||||
#include "ngraph_functions/low_precision_transformations/common/dequantization_operations.hpp"
|
||||
|
||||
using namespace testing;
|
||||
using namespace ngraph::pass;
|
||||
using namespace ngraph::builder::subgraph;
|
||||
|
||||
class MoveDequantizationAfterTransformationParams {
|
||||
public:
|
||||
class Actual {
|
||||
public:
|
||||
ngraph::builder::subgraph::DequantizationOperations dequantization;
|
||||
};
|
||||
|
||||
class Expected {
|
||||
public:
|
||||
ngraph::builder::subgraph::DequantizationOperations dequantizationBefore;
|
||||
ngraph::element::Type precisionAfterOperation;
|
||||
ngraph::builder::subgraph::DequantizationOperations dequantizationAfter;
|
||||
};
|
||||
|
||||
ngraph::element::Type originalPrecision;
|
||||
ngraph::pass::low_precision::LayerTransformation::Params params;
|
||||
bool updatePrecision;
|
||||
bool moveSubtract;
|
||||
Actual actual;
|
||||
Expected expected;
|
||||
};
|
||||
|
||||
typedef std::tuple<
|
||||
ngraph::Shape,
|
||||
MoveDequantizationAfterTransformationParams> MoveDequantizationAfterTransformationTestValues;
|
||||
|
||||
class MoveDequantizationAfterWithIntConstantTransformation :
|
||||
public LayerTransformation,
|
||||
public testing::WithParamInterface<MoveDequantizationAfterTransformationTestValues> {
|
||||
public:
|
||||
void SetUp() override {
|
||||
const auto inputShape = std::get<0>(GetParam());
|
||||
const auto testValues = std::get<1>(GetParam());
|
||||
actualFunction = ngraph::builder::subgraph::MoveDequantizationAfterWithIntConstantFunction::getOriginal(
|
||||
testValues.originalPrecision,
|
||||
inputShape,
|
||||
testValues.actual.dequantization);
|
||||
|
||||
const auto targetNode = actualFunction->get_output_op(0)->get_input_node_shared_ptr(0);
|
||||
const auto dequantization = ngraph::pass::low_precision::NetworkHelper::getDequantization(targetNode);
|
||||
ngraph::pass::low_precision::NetworkHelper::moveDequantizationAfter(
|
||||
targetNode,
|
||||
dequantization,
|
||||
testValues.updatePrecision,
|
||||
testValues.moveSubtract);
|
||||
|
||||
referenceFunction = ngraph::builder::subgraph::MoveDequantizationAfterWithIntConstantFunction::getReference(
|
||||
testValues.originalPrecision,
|
||||
inputShape,
|
||||
testValues.expected.dequantizationBefore,
|
||||
testValues.expected.precisionAfterOperation,
|
||||
testValues.expected.dequantizationAfter);
|
||||
}
|
||||
|
||||
static std::string getTestCaseName(testing::TestParamInfo<MoveDequantizationAfterTransformationTestValues> obj) {
|
||||
const auto inputShape = std::get<0>(obj.param);
|
||||
const auto testValues = std::get<1>(obj.param);
|
||||
|
||||
std::ostringstream result;
|
||||
result <<
|
||||
testValues.originalPrecision << "_" <<
|
||||
inputShape << "_" <<
|
||||
testValues.actual.dequantization << "_" <<
|
||||
(testValues.moveSubtract ? "move_subtract_" : "don't_move_subtract_") <<
|
||||
(testValues.updatePrecision ? "updatePrecision" : "don't_update_precision");
|
||||
return result.str();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_P(MoveDequantizationAfterWithIntConstantTransformation, CompareFunctions) {
|
||||
actualFunction->validate_nodes_and_infer_types();
|
||||
auto res = compare_functions(referenceFunction, actualFunction, true, false, true);
|
||||
ASSERT_TRUE(res.first) << res.second;
|
||||
}
|
||||
|
||||
const std::vector<ngraph::Shape> inputShapes = {
|
||||
{ 1, 3, 16, 16 },
|
||||
{ 4, 3, 16, 16 }
|
||||
};
|
||||
|
||||
const std::vector<MoveDequantizationAfterTransformationParams> testValues = {
|
||||
// I8 & I8: Multiply
|
||||
{
|
||||
ngraph::element::i8,
|
||||
LayerTransformation::createParamsU8I8(),
|
||||
false,
|
||||
true,
|
||||
{
|
||||
{ {}, {}, { {10.f}, ngraph::element::f32, {}, true, 1ul, ngraph::element::u8 } },
|
||||
},
|
||||
{
|
||||
{ {}, {}, {} },
|
||||
ngraph::element::f32,
|
||||
{ {}, {}, { 10.f } },
|
||||
},
|
||||
},
|
||||
// I8 & I8: Subtract + Multiply
|
||||
{
|
||||
ngraph::element::i8,
|
||||
LayerTransformation::createParamsU8I8(),
|
||||
false,
|
||||
true,
|
||||
{
|
||||
{
|
||||
{},
|
||||
{ {5.f}, ngraph::element::f32, {}, true, 1ul, ngraph::element::u8 },
|
||||
{ {10.f}, ngraph::element::f32, {}, true, 1ul, ngraph::element::u8 }
|
||||
},
|
||||
},
|
||||
{
|
||||
{ {}, {}, {} },
|
||||
ngraph::element::f32,
|
||||
{ {}, {5.f}, { 10.f } },
|
||||
},
|
||||
},
|
||||
// FP32 & I8: Multiply
|
||||
{
|
||||
ngraph::element::u8,
|
||||
LayerTransformation::createParamsU8I8(),
|
||||
false,
|
||||
true,
|
||||
{
|
||||
{ {ngraph::element::f32}, {}, { {10.f}, ngraph::element::f32, {}, true, 1ul, ngraph::element::i8 } },
|
||||
},
|
||||
{
|
||||
{ {}, {}, {} },
|
||||
ngraph::element::f32,
|
||||
{ {}, {}, { 10.f } },
|
||||
},
|
||||
},
|
||||
// FP32 & I8: Subtract + Multiply
|
||||
{
|
||||
ngraph::element::u8,
|
||||
LayerTransformation::createParamsU8I8(),
|
||||
false,
|
||||
true,
|
||||
{
|
||||
{
|
||||
{ngraph::element::f32},
|
||||
{ {5.f}, ngraph::element::f32, {}, true, 1ul, ngraph::element::i8 },
|
||||
{ {10.f}, ngraph::element::f32, {}, true, 1ul, ngraph::element::i8 }
|
||||
},
|
||||
},
|
||||
{
|
||||
{ {}, {}, {} },
|
||||
ngraph::element::f32,
|
||||
{ {}, {5.f}, { 10.f } },
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
LPT,
|
||||
MoveDequantizationAfterWithIntConstantTransformation,
|
||||
::testing::Combine(
|
||||
::testing::ValuesIn(inputShapes),
|
||||
::testing::ValuesIn(testValues)),
|
||||
MoveDequantizationAfterWithIntConstantTransformation::getTestCaseName);
|
@ -34,7 +34,9 @@ public:
|
||||
const std::vector<float>& values,
|
||||
const ngraph::element::Type outPrecision,
|
||||
const ngraph::Shape& constantShape,
|
||||
const bool addDequantizationAttribute = true);
|
||||
const bool addDequantizationAttribute = true,
|
||||
const size_t constantIndex = 1ul,
|
||||
const ngraph::element::Type constantPrecision = ngraph::element::undefined);
|
||||
bool empty() const noexcept;
|
||||
Subtract& setConstantPrecision(const ngraph::element::Type& precision);
|
||||
|
||||
@ -43,7 +45,9 @@ public:
|
||||
ngraph::Shape constantShape;
|
||||
bool constantShapeIsDefined;
|
||||
bool addDequantizationAttribute;
|
||||
size_t constantIndex = 1ul;
|
||||
ngraph::element::Type constantPrecision = ngraph::element::undefined;
|
||||
|
||||
private:
|
||||
bool isEmpty;
|
||||
};
|
||||
@ -59,7 +63,8 @@ public:
|
||||
const ngraph::element::Type outPrecision,
|
||||
const ngraph::Shape& constantShape,
|
||||
const bool addDequantizationAttribute = true,
|
||||
const size_t constantIndex = 1ul);
|
||||
const size_t constantIndex = 1ul,
|
||||
const ngraph::element::Type constantPrecision = ngraph::element::undefined);
|
||||
bool empty() const noexcept;
|
||||
Multiply& setConstantPrecision(const ngraph::element::Type& precision);
|
||||
|
||||
@ -70,6 +75,7 @@ public:
|
||||
bool addDequantizationAttribute;
|
||||
size_t constantIndex = 1ul;
|
||||
ngraph::element::Type constantPrecision = ngraph::element::undefined;
|
||||
|
||||
private:
|
||||
bool isEmpty;
|
||||
};
|
||||
|
@ -69,6 +69,13 @@ public:
|
||||
const FakeQuantizeOnData& fqOnData1,
|
||||
const FakeQuantizeOnData& fqOnData2);
|
||||
|
||||
static std::shared_ptr<ngraph::Function> getOriginalWithReshapeAtTheEndTransformation(
|
||||
const ngraph::element::Type precision,
|
||||
const ngraph::Shape& inputShape,
|
||||
const FakeQuantizeOnDataWithConstant& fqOnData1,
|
||||
const FakeQuantizeOnDataWithConstant& fqOnData2,
|
||||
const FakeQuantizeOnDataWithConstant& fqOnData3);
|
||||
|
||||
static std::shared_ptr<ngraph::Function> getReference(
|
||||
const ngraph::element::Type precision,
|
||||
const ngraph::Shape& inputShape,
|
||||
@ -138,6 +145,17 @@ public:
|
||||
const ngraph::element::Type precisionAfterOperation,
|
||||
const DequantizationOperations& dequantizationAfter,
|
||||
const ngraph::element::Type precisionAfterDequantization);
|
||||
|
||||
static std::shared_ptr<ngraph::Function> getReferenceWithReshapeAtTheEndTransformation(
|
||||
const ngraph::element::Type precision,
|
||||
const ngraph::Shape& inputShape,
|
||||
const FakeQuantizeOnDataWithConstant& fqOnData1,
|
||||
const FakeQuantizeOnDataWithConstant& fqOnData2,
|
||||
const FakeQuantizeOnDataWithConstant& fqOnData3,
|
||||
const DequantizationOperations& dequantizationOperations);
|
||||
|
||||
private:
|
||||
static std::shared_ptr<Node> makeMaxPool(const Output<Node>& parent, const std::vector<size_t>& kernel);
|
||||
};
|
||||
|
||||
} // namespace subgraph
|
||||
|
@ -0,0 +1,34 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <ngraph/ngraph.hpp>
|
||||
|
||||
#include "ngraph_functions/low_precision_transformations/common/dequantization_operations.hpp"
|
||||
#include "ngraph_functions/subgraph_builders.hpp"
|
||||
|
||||
namespace ngraph {
|
||||
namespace builder {
|
||||
namespace subgraph {
|
||||
|
||||
class MoveDequantizationAfterWithIntConstantFunction {
|
||||
public:
|
||||
static std::shared_ptr<ngraph::Function> getOriginal(
|
||||
const ngraph::element::Type precision,
|
||||
const ngraph::Shape& inputShape,
|
||||
const ngraph::builder::subgraph::DequantizationOperations dequantization);
|
||||
|
||||
static std::shared_ptr<ngraph::Function> getReference(
|
||||
const ngraph::element::Type precision,
|
||||
const ngraph::Shape& inputShape,
|
||||
const ngraph::builder::subgraph::DequantizationOperations dequantizationBefore,
|
||||
const ngraph::element::Type precisionAfterOperation,
|
||||
const ngraph::builder::subgraph::DequantizationOperations dequantizationAfter);
|
||||
};
|
||||
|
||||
} // namespace subgraph
|
||||
} // namespace builder
|
||||
} // namespace ngraph
|
@ -51,8 +51,10 @@ std::shared_ptr<Node> makeDequantization(
|
||||
shape,
|
||||
dequantizationOperations.subtract.values);
|
||||
|
||||
if ((dequantizationOperations.subtract.outPrecision == element::undefined) ||
|
||||
(dequantizationOperations.subtract.outPrecision == parent.get_element_type())) {
|
||||
if (((dequantizationOperations.subtract.outPrecision == element::undefined) ||
|
||||
(dequantizationOperations.subtract.outPrecision == parent.get_element_type())) &&
|
||||
((dequantizationOperations.subtract.constantPrecision == element::undefined) ||
|
||||
(dequantizationOperations.subtract.constantPrecision == parent.get_element_type()))) {
|
||||
subtract = std::make_shared<ngraph::pass::low_precision::DequantizationSubtract>(parent, subtractConst);
|
||||
} else {
|
||||
subtract = std::make_shared<op::TypeRelaxed<ngraph::pass::low_precision::DequantizationSubtract>>(
|
||||
@ -83,10 +85,14 @@ std::shared_ptr<Node> makeDequantization(
|
||||
}
|
||||
|
||||
std::shared_ptr<ngraph::opset1::Multiply> multiply;
|
||||
if ((dequantizationOperations.multiply.outPrecision == element::undefined) ||
|
||||
(dequantizationOperations.multiply.outPrecision == parent.get_element_type())) {
|
||||
if (((dequantizationOperations.multiply.outPrecision == element::undefined) ||
|
||||
(dequantizationOperations.multiply.outPrecision == parent.get_element_type())) &&
|
||||
((dequantizationOperations.multiply.constantPrecision == element::undefined) ||
|
||||
(dequantizationOperations.multiply.constantPrecision == parent.get_element_type()))) {
|
||||
const std::shared_ptr<ngraph::opset1::Constant> constant = std::make_shared<ngraph::opset1::Constant>(
|
||||
parent.get_element_type(),
|
||||
dequantizationOperations.multiply.constantPrecision != element::undefined ?
|
||||
dequantizationOperations.multiply.constantPrecision :
|
||||
parent.get_element_type(),
|
||||
shape,
|
||||
dequantizationOperations.multiply.values);
|
||||
|
||||
|
@ -59,13 +59,17 @@ DequantizationOperations::Subtract::Subtract(
|
||||
const std::vector<float>& values,
|
||||
const ngraph::element::Type outPrecision,
|
||||
const ngraph::Shape& constantShape,
|
||||
const bool addDequantizationAttribute) :
|
||||
const bool addDequantizationAttribute,
|
||||
const size_t constantIndex,
|
||||
const ngraph::element::Type constantPrecision) :
|
||||
isEmpty(false),
|
||||
values(values),
|
||||
outPrecision(outPrecision),
|
||||
constantShape(constantShape),
|
||||
constantShapeIsDefined(true),
|
||||
addDequantizationAttribute(addDequantizationAttribute) {
|
||||
addDequantizationAttribute(addDequantizationAttribute),
|
||||
constantIndex(constantIndex),
|
||||
constantPrecision(constantPrecision) {
|
||||
}
|
||||
|
||||
bool DequantizationOperations::Subtract::empty() const noexcept {
|
||||
@ -109,13 +113,15 @@ DequantizationOperations::Multiply::Multiply(
|
||||
const ngraph::element::Type outPrecision,
|
||||
const ngraph::Shape& constantShape,
|
||||
const bool addDequantizationAttribute,
|
||||
const size_t constantIndex) :
|
||||
const size_t constantIndex,
|
||||
ngraph::element::Type constantPrecision) :
|
||||
isEmpty(false),
|
||||
values(values),
|
||||
outPrecision(outPrecision),
|
||||
constantShape(constantShape),
|
||||
addDequantizationAttribute(addDequantizationAttribute),
|
||||
constantIndex(constantIndex),
|
||||
constantPrecision(constantPrecision),
|
||||
constantShapeIsDefined(true) {
|
||||
}
|
||||
|
||||
|
@ -153,23 +153,9 @@ std::shared_ptr<ngraph::Function> ConcatFunction::getOriginalWithIntermediate(
|
||||
const auto fakeQuantize2 = makeFakeQuantize(input2, precision, fqOnData2);
|
||||
fakeQuantize2->set_friendly_name("fakeQuantize2");
|
||||
|
||||
const std::vector<size_t> kernel = { 3, 3 };
|
||||
const std::vector<size_t> stride = { 1, 1 };
|
||||
const std::vector<size_t> padBegin = { 0, 0 };
|
||||
const std::vector<size_t> padEnd = { 0, 0 };
|
||||
const ngraph::op::PadType padType = ngraph::op::PadType::NOTSET;
|
||||
const ngraph::op::RoundingType roundingType = ngraph::op::RoundingType::FLOOR;
|
||||
std::shared_ptr<ngraph::op::Op> intermediateOp;
|
||||
|
||||
std::shared_ptr<Node> intermediateOp;
|
||||
if (transparentIntermediate) {
|
||||
intermediateOp = std::make_shared<ngraph::opset1::MaxPool>(
|
||||
fakeQuantize2->output(0),
|
||||
stride,
|
||||
padBegin,
|
||||
padEnd,
|
||||
kernel,
|
||||
roundingType,
|
||||
padType);
|
||||
intermediateOp = makeMaxPool(fakeQuantize2->output(0), { 3, 3 });
|
||||
} else {
|
||||
auto weights = ngraph::opset1::Constant::create(
|
||||
precision,
|
||||
@ -307,23 +293,9 @@ std::shared_ptr<ngraph::Function> ConcatFunction::getOriginalSelectionWithInterm
|
||||
const auto fakeQuantize2 = makeFakeQuantize(input2, precision, fqOnData2);
|
||||
fakeQuantize2->set_friendly_name("fakeQuantize2");
|
||||
|
||||
const std::vector<size_t> kernel = { 3, 3 };
|
||||
const std::vector<size_t> stride = { 1, 1 };
|
||||
const std::vector<size_t> padBegin = { 0, 0 };
|
||||
const std::vector<size_t> padEnd = { 0, 0 };
|
||||
const ngraph::op::PadType padType = ngraph::op::PadType::NOTSET;
|
||||
const ngraph::op::RoundingType roundingType = ngraph::op::RoundingType::FLOOR;
|
||||
std::shared_ptr<ngraph::op::Op> intermediateOp;
|
||||
|
||||
std::shared_ptr<Node> intermediateOp;
|
||||
if (transparentIntermediate) {
|
||||
intermediateOp = std::make_shared<ngraph::opset1::MaxPool>(
|
||||
fakeQuantize2->output(0),
|
||||
stride,
|
||||
padBegin,
|
||||
padEnd,
|
||||
kernel,
|
||||
roundingType,
|
||||
padType);
|
||||
intermediateOp = makeMaxPool(fakeQuantize2->output(0), { 3, 3 });
|
||||
} else {
|
||||
auto weights = ngraph::opset1::Constant::create(
|
||||
precision,
|
||||
@ -451,21 +423,7 @@ std::shared_ptr<ngraph::Function> ConcatFunction::getOriginalWithIntermediateWit
|
||||
std::shared_ptr<ngraph::op::Op> intermediateOp;
|
||||
|
||||
if (transparentIntermediate) {
|
||||
const std::vector<size_t> kernel = { 3, 3 };
|
||||
const std::vector<size_t> stride = { 1, 1 };
|
||||
const std::vector<size_t> padBegin = { 0, 0 };
|
||||
const std::vector<size_t> padEnd = { 0, 0 };
|
||||
const ngraph::op::PadType padType = ngraph::op::PadType::NOTSET;
|
||||
const ngraph::op::RoundingType roundingType = ngraph::op::RoundingType::FLOOR;
|
||||
|
||||
const auto pooling = std::make_shared<ngraph::opset1::MaxPool>(
|
||||
fakeQuantize1->output(0),
|
||||
stride,
|
||||
padBegin,
|
||||
padEnd,
|
||||
kernel,
|
||||
roundingType,
|
||||
padType);
|
||||
const auto pooling = makeMaxPool(fakeQuantize1->output(0), { 3, 3 });
|
||||
|
||||
ngraph::op::v0::InterpolateAttrs attributes;
|
||||
attributes.axes = ngraph::AxisSet{ 2, 3 };
|
||||
@ -502,6 +460,55 @@ std::shared_ptr<ngraph::Function> ConcatFunction::getOriginalWithIntermediateWit
|
||||
return function;
|
||||
}
|
||||
|
||||
std::shared_ptr<ngraph::Function> ConcatFunction::getOriginalWithReshapeAtTheEndTransformation(
|
||||
const ngraph::element::Type precision,
|
||||
const ngraph::Shape& inputShape,
|
||||
const FakeQuantizeOnDataWithConstant& fqOnData1,
|
||||
const FakeQuantizeOnDataWithConstant& fqOnData2,
|
||||
const FakeQuantizeOnDataWithConstant& fqOnData3) {
|
||||
const auto input1 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape));
|
||||
input1->set_friendly_name("input1");
|
||||
const auto fakeQuantize1 = makeFakeQuantizeTypeRelaxed(input1, precision, fqOnData1);
|
||||
fakeQuantize1->set_friendly_name("fakeQuantize1");
|
||||
|
||||
const auto input2 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape));
|
||||
input2->set_friendly_name("input2");
|
||||
const auto fakeQuantize2 = makeFakeQuantizeTypeRelaxed(input2, precision, fqOnData2);
|
||||
fakeQuantize2->set_friendly_name("fakeQuantize2");
|
||||
|
||||
const std::shared_ptr<ngraph::opset1::Concat> concat1 = std::make_shared<ngraph::opset1::Concat>(
|
||||
ngraph::OutputVector{ fakeQuantize1->output(0), fakeQuantize2->output(0) }, 1);
|
||||
concat1->set_friendly_name("concat1");
|
||||
|
||||
const std::shared_ptr<Node> intermediate = makeMaxPool(concat1->output(0), {1ul, 1ul});
|
||||
|
||||
const auto input3 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape));
|
||||
input3->set_friendly_name("input3");
|
||||
const auto fakeQuantize3 = makeFakeQuantizeTypeRelaxed(input3, precision, fqOnData3);
|
||||
fakeQuantize3->set_friendly_name("fakeQuantize3");
|
||||
|
||||
const std::shared_ptr<ngraph::opset1::Concat> concat2 = std::make_shared<ngraph::opset1::Concat>(ngraph::OutputVector{ fakeQuantize3, intermediate }, 1);
|
||||
concat2->set_friendly_name("concat2");
|
||||
|
||||
const Shape concat2Shape = concat2->output(0).get_shape();
|
||||
const std::shared_ptr<Node> maxPool = makeMaxPool(concat2->output(0), {concat2Shape[2], concat2Shape[3]});
|
||||
const std::shared_ptr<Node> reshape = std::make_shared<ngraph::opset1::Reshape>(
|
||||
maxPool,
|
||||
std::make_shared<ngraph::opset1::Constant>(ngraph::element::i64, ngraph::Shape{2ul}, std::vector<size_t>{0, 0}),
|
||||
true);
|
||||
reshape->set_friendly_name("output");
|
||||
|
||||
|
||||
ngraph::ResultVector results{std::make_shared<ngraph::opset1::Result>(reshape)};
|
||||
|
||||
std::shared_ptr<ngraph::Function> function = std::make_shared<ngraph::Function>(
|
||||
results,
|
||||
ngraph::ParameterVector{ input1, input2, input3 },
|
||||
"OriginalWithReshapeAtTheEndTransformation");
|
||||
|
||||
return function;
|
||||
}
|
||||
|
||||
std::shared_ptr<ngraph::Function> ConcatFunction::getReference(
|
||||
const ngraph::element::Type precision,
|
||||
const ngraph::Shape& inputShape,
|
||||
@ -706,23 +713,9 @@ std::shared_ptr<ngraph::Function> ConcatFunction::getReferenceWithIntermediate(
|
||||
const auto fakeQuantize2 = makeFakeQuantizeTypeRelaxed(input2, precision, fqOnData2);
|
||||
fakeQuantize2->set_friendly_name("fakeQuantize2");
|
||||
|
||||
const std::vector<size_t> kernel = { 3, 3 };
|
||||
const std::vector<size_t> stride = { 1, 1 };
|
||||
const std::vector<size_t> padBegin = { 0, 0 };
|
||||
const std::vector<size_t> padEnd = { 0, 0 };
|
||||
const ngraph::op::PadType padType = ngraph::op::PadType::NOTSET;
|
||||
const ngraph::op::RoundingType roundingType = ngraph::op::RoundingType::FLOOR;
|
||||
std::shared_ptr<Node> intermediateOp;
|
||||
|
||||
if (transparentIntermediate) {
|
||||
intermediateOp = std::make_shared<ngraph::opset1::MaxPool>(
|
||||
fakeQuantize2->output(0),
|
||||
stride,
|
||||
padBegin,
|
||||
padEnd,
|
||||
kernel,
|
||||
roundingType,
|
||||
padType);
|
||||
intermediateOp = makeMaxPool(fakeQuantize2->output(0), { 3, 3 });
|
||||
} else {
|
||||
auto weights = ngraph::opset1::Constant::create(
|
||||
precision,
|
||||
@ -926,23 +919,9 @@ std::shared_ptr<ngraph::Function> ConcatFunction::getReferenceSelectionWithInter
|
||||
const auto fakeQuantize2 = makeFakeQuantizeTypeRelaxed(input2, precision, fqOnData2);
|
||||
fakeQuantize2->set_friendly_name("fakeQuantize2");
|
||||
|
||||
const std::vector<size_t> kernel = { 3, 3 };
|
||||
const std::vector<size_t> stride = { 1, 1 };
|
||||
const std::vector<size_t> padBegin = { 0, 0 };
|
||||
const std::vector<size_t> padEnd = { 0, 0 };
|
||||
const ngraph::op::PadType padType = ngraph::op::PadType::NOTSET;
|
||||
const ngraph::op::RoundingType roundingType = ngraph::op::RoundingType::FLOOR;
|
||||
std::shared_ptr<ngraph::op::Op> intermediateOp;
|
||||
|
||||
std::shared_ptr<Node> intermediateOp;
|
||||
if (transparentIntermediate) {
|
||||
intermediateOp = std::make_shared<ngraph::opset1::MaxPool>(
|
||||
fakeQuantize2->output(0),
|
||||
stride,
|
||||
padBegin,
|
||||
padEnd,
|
||||
kernel,
|
||||
roundingType,
|
||||
padType);
|
||||
intermediateOp = makeMaxPool(fakeQuantize2->output(0), { 3, 3 });
|
||||
} else {
|
||||
auto weights = ngraph::opset1::Constant::create(
|
||||
precision,
|
||||
@ -1135,21 +1114,7 @@ std::shared_ptr<ngraph::Function> ConcatFunction::getReferenceWithIntermediateWi
|
||||
|
||||
if (transparentIntermediate) {
|
||||
const auto deqBefore = makeDequantization(fakeQuantize1->output(0), dequantizationBefore);
|
||||
const std::vector<size_t> kernel = { 3, 3 };
|
||||
const std::vector<size_t> stride = { 1, 1 };
|
||||
const std::vector<size_t> padBegin = { 0, 0 };
|
||||
const std::vector<size_t> padEnd = { 0, 0 };
|
||||
const ngraph::op::PadType padType = ngraph::op::PadType::NOTSET;
|
||||
const ngraph::op::RoundingType roundingType = ngraph::op::RoundingType::FLOOR;
|
||||
|
||||
const auto pooling = std::make_shared<ngraph::opset1::MaxPool>(
|
||||
fakeQuantize1->output(0),
|
||||
stride,
|
||||
padBegin,
|
||||
padEnd,
|
||||
kernel,
|
||||
roundingType,
|
||||
padType);
|
||||
const auto pooling = makeMaxPool(fakeQuantize1->output(0), { 3, 3 });
|
||||
|
||||
ngraph::op::v0::InterpolateAttrs attributes;
|
||||
attributes.axes = ngraph::AxisSet{ 2, 3 };
|
||||
@ -1192,6 +1157,75 @@ std::shared_ptr<ngraph::Function> ConcatFunction::getReferenceWithIntermediateWi
|
||||
return function;
|
||||
}
|
||||
|
||||
std::shared_ptr<ngraph::Function> ConcatFunction::getReferenceWithReshapeAtTheEndTransformation(
|
||||
const ngraph::element::Type precision,
|
||||
const ngraph::Shape& inputShape,
|
||||
const FakeQuantizeOnDataWithConstant& fqOnData1,
|
||||
const FakeQuantizeOnDataWithConstant& fqOnData2,
|
||||
const FakeQuantizeOnDataWithConstant& fqOnData3,
|
||||
const DequantizationOperations& dequantizationOperations) {
|
||||
const auto input1 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape));
|
||||
input1->set_friendly_name("input1");
|
||||
const auto fakeQuantize1 = makeFakeQuantizeTypeRelaxed(input1, precision, fqOnData1);
|
||||
fakeQuantize1->set_friendly_name("fakeQuantize1");
|
||||
|
||||
const auto input2 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape));
|
||||
input2->set_friendly_name("input2");
|
||||
const auto fakeQuantize2 = makeFakeQuantizeTypeRelaxed(input2, precision, fqOnData2);
|
||||
fakeQuantize2->set_friendly_name("fakeQuantize2");
|
||||
|
||||
const std::shared_ptr<ngraph::opset1::Concat> concat1 = std::make_shared<ngraph::opset1::Concat>(
|
||||
ngraph::OutputVector{ fakeQuantize1->output(0), fakeQuantize2->output(0) }, 1);
|
||||
concat1->set_friendly_name("concat1");
|
||||
|
||||
std::shared_ptr<Node> intermediate = makeMaxPool(concat1->output(0), {1ul, 1ul});
|
||||
|
||||
const auto input3 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape));
|
||||
input3->set_friendly_name("input3");
|
||||
const auto fakeQuantize3 = makeFakeQuantizeTypeRelaxed(input3, precision, fqOnData3);
|
||||
fakeQuantize3->set_friendly_name("fakeQuantize3");
|
||||
|
||||
const std::shared_ptr<ngraph::opset1::Concat> concat2 = std::make_shared<ngraph::opset1::Concat>(ngraph::OutputVector{ fakeQuantize3, intermediate }, 1);
|
||||
concat2->set_friendly_name("concat2");
|
||||
|
||||
const Shape concat2Shape = concat2->output(0).get_shape();
|
||||
const std::shared_ptr<Node> maxPool = makeMaxPool(concat2->output(0), {concat2Shape[2], concat2Shape[3]});
|
||||
const std::shared_ptr<Node> reshape = std::make_shared<ngraph::opset1::Reshape>(
|
||||
maxPool,
|
||||
std::make_shared<ngraph::opset1::Constant>(ngraph::element::i64, ngraph::Shape{2ul}, std::vector<size_t>{0, 0}),
|
||||
true);
|
||||
reshape->set_friendly_name("output_original");
|
||||
|
||||
const auto dequantization = makeDequantization(reshape->output(0), dequantizationOperations);
|
||||
dequantization->set_friendly_name("output");
|
||||
|
||||
ngraph::ResultVector results{std::make_shared<ngraph::opset1::Result>(dequantization)};
|
||||
|
||||
std::shared_ptr<ngraph::Function> function = std::make_shared<ngraph::Function>(
|
||||
results,
|
||||
ngraph::ParameterVector{ input1, input2, input3 },
|
||||
"ReferenceWithReshapeAtTheEndTransformation");
|
||||
|
||||
return function;
|
||||
}
|
||||
|
||||
std::shared_ptr<Node> ConcatFunction::makeMaxPool(const Output<Node>& parent, const std::vector<size_t>& kernel) {
|
||||
const std::vector<size_t> stride = { 1, 1 };
|
||||
const std::vector<size_t> padBegin = { 0, 0 };
|
||||
const std::vector<size_t> padEnd = { 0, 0 };
|
||||
const ngraph::op::PadType padType = ngraph::op::PadType::NOTSET;
|
||||
const ngraph::op::RoundingType roundingType = ngraph::op::RoundingType::FLOOR;
|
||||
const auto pooling = std::make_shared<ngraph::opset1::MaxPool>(
|
||||
parent,
|
||||
stride,
|
||||
padBegin,
|
||||
padEnd,
|
||||
kernel,
|
||||
roundingType,
|
||||
padType);
|
||||
return pooling;
|
||||
}
|
||||
|
||||
} // namespace subgraph
|
||||
} // namespace builder
|
||||
} // namespace ngraph
|
||||
|
@ -0,0 +1,79 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "ngraph_functions/low_precision_transformations/move_dequantization_after_with_int_constant_function.hpp"
|
||||
#include "low_precision/network_helper.hpp"
|
||||
|
||||
#include <ngraph/opsets/opset1.hpp>
|
||||
#include "ngraph_functions/subgraph_builders.hpp"
|
||||
#include "ngraph_functions/low_precision_transformations/common/builders.hpp"
|
||||
|
||||
using namespace ngraph::pass::low_precision;
|
||||
|
||||
namespace ngraph {
|
||||
namespace builder {
|
||||
namespace subgraph {
|
||||
std::shared_ptr<ngraph::Function> MoveDequantizationAfterWithIntConstantFunction::getOriginal(
|
||||
const ngraph::element::Type precision,
|
||||
const ngraph::Shape& inputShape,
|
||||
const ngraph::builder::subgraph::DequantizationOperations dequantization) {
|
||||
const auto input = std::make_shared<ngraph::op::v0::Parameter>(precision, inputShape);
|
||||
|
||||
const auto deq = makeDequantization(input, dequantization);
|
||||
const auto avgPool = std::make_shared<op::TypeRelaxed<opset1::AvgPool>>(
|
||||
ngraph::opset1::AvgPool(
|
||||
deq,
|
||||
Strides{ 1, 1 },
|
||||
Shape{ 1, 1 },
|
||||
Shape{ 0, 0 },
|
||||
Shape{ 2, 2 },
|
||||
true,
|
||||
op::RoundingType::FLOOR),
|
||||
std::vector<element::Type>{ element::f32, element::f32 },
|
||||
std::vector<element::Type>{});
|
||||
|
||||
auto& rtInfo = avgPool->get_rt_info();
|
||||
rtInfo["Variant::std::string"] = std::make_shared<VariantWrapper<std::string>>("targetOp");
|
||||
|
||||
return std::make_shared<ngraph::Function>(
|
||||
ngraph::ResultVector{ std::make_shared<ngraph::opset1::Result>(avgPool) },
|
||||
ngraph::ParameterVector{ input },
|
||||
"MoveDequantizationAfterFunction");
|
||||
}
|
||||
|
||||
std::shared_ptr<ngraph::Function> MoveDequantizationAfterWithIntConstantFunction::getReference(
|
||||
const ngraph::element::Type precision,
|
||||
const ngraph::Shape& inputShape,
|
||||
const ngraph::builder::subgraph::DequantizationOperations dequantizationBefore,
|
||||
const ngraph::element::Type precisionAfterOperation,
|
||||
const ngraph::builder::subgraph::DequantizationOperations dequantizationAfter) {
|
||||
const auto input = std::make_shared<ngraph::op::v0::Parameter>(precision, inputShape);
|
||||
|
||||
const auto deqBefore = makeDequantization(input, dequantizationBefore);
|
||||
const auto targetOp = std::make_shared<op::TypeRelaxed<opset1::AvgPool>>(
|
||||
ngraph::opset1::AvgPool(
|
||||
deqBefore,
|
||||
Strides{ 1, 1 },
|
||||
Shape{ 1, 1 },
|
||||
Shape{ 0, 0 },
|
||||
Shape{ 2, 2 },
|
||||
true,
|
||||
op::RoundingType::FLOOR),
|
||||
std::vector<element::Type>{ element::f32, element::f32 },
|
||||
std::vector<element::Type>{});
|
||||
ngraph::pass::low_precision::NetworkHelper::setOutDataPrecisionForTypeRelaxed(targetOp, precisionAfterOperation);
|
||||
auto& rtInfo = targetOp->get_rt_info();
|
||||
rtInfo["Variant::std::string"] = std::make_shared<VariantWrapper<std::string>>("targetOp");
|
||||
|
||||
const auto deqAfter = makeDequantization(targetOp, dequantizationAfter);
|
||||
|
||||
return std::make_shared<ngraph::Function>(
|
||||
ngraph::ResultVector{ std::make_shared<ngraph::opset1::Result>(deqAfter) },
|
||||
ngraph::ParameterVector{ input },
|
||||
"MoveDequantizationAfterFunction");
|
||||
}
|
||||
|
||||
} // namespace subgraph
|
||||
} // namespace builder
|
||||
} // namespace ngraph
|
Loading…
Reference in New Issue
Block a user