}
auto dScaleShift = dScaleShiftsVector[0];
+
const Blob::Ptr scalesBlob = CNNNetworkHelper::getBlob(dScaleShift, "weights");
auto scalesBufferPtr = CNNNetworkHelper::getFloatData(scalesBlob);
return;
}
+ OutputsDataMap outputs;
+ context.network.getOutputsInfo(outputs);
+ const bool dScaleShiftIsLastLayer = outputs.find(dScaleShift->name) != outputs.end();
+ if (dScaleShiftIsLastLayer && (dScaleShiftsVector.size() > 1ul)) {
+ // not possible to fuse ScaleShifts if at least one is output
+ return;
+ }
+
// All ScaleShifts must be equal
for (size_t i = 1lu; i < dScaleShiftsVector.size(); i++) {
auto ssLayer = dScaleShiftsVector[i];
+ if (outputs.find(ssLayer->name) != outputs.end()) {
+ // not possible to fuse ScaleShifts if at least one is output
+ return;
+ }
const Blob::Ptr scBlob = CNNNetworkHelper::getBlob(ssLayer, "weights");
auto scBufferPtr = CNNNetworkHelper::getFloatData(scBlob);
auto ssPrecision = dScaleShiftsVector[0]->outData[0]->getPrecision();
fakeQuantizeLayer.outData[0]->setPrecision(ssPrecision);
}
+
+
+ if (dScaleShiftIsLastLayer) {
+ CNNNetworkHelper::renameLayer(context.network, fakeQuantizeLayer.name, dScaleShift->name);
+ }
}
--- /dev/null
+// Copyright (C) 2020 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#include <vector>
+
+#include "low_precision_transformations/fuse_fake_quantize_and_scale_shift_transformation.hpp"
+#include "common_test_utils/test_constants.hpp"
+#include "ngraph_functions/low_precision_transformations/fuse_fake_quantize_and_scale_shift_function.hpp"
+
+using namespace LayerTestsDefinitions;
+using namespace InferenceEngine::details;
+
+namespace {
+const std::vector<InferenceEngine::Precision> netPrecisions = {
+ InferenceEngine::Precision::FP32
+};
+
+const std::vector<LayerTransformation::Params> trasformationParamValues = {
+ LayerTestsUtils::LayerTransformationParamsFactory::createParamsU8I8()
+};
+
+const std::vector<ngraph::builder::subgraph::FakeQuantizeOnData> fakeQuantizeOnDataValues = {
+ { 256ul, {}, { 0.f }, { 2.55f }, { 0.f }, { 2.55f } },
+ {
+ 256ul,
+ { 1ul, 3ul, 1ul, 1ul },
+ { 0.f, 0.f, 0.f },
+ { 2.55f / 10.f, 2.55f / 5.f, 2.55f / 2.f },
+ { 0.f, 0.f, 0.f },
+ { 2.55f / 10.f, 2.55f / 5.f, 2.55f / 2.f }
+ },
+};
+
+INSTANTIATE_TEST_CASE_P(LPT, FuseFakeQuantizeAndScaleShiftTransformation,
+ ::testing::Combine(
+ ::testing::ValuesIn(netPrecisions),
+ ::testing::Values(InferenceEngine::SizeVector({ 1, 3, 9, 9 })),
+ ::testing::Values(CommonTestUtils::DEVICE_CPU),
+ ::testing::ValuesIn(trasformationParamValues),
+ ::testing::ValuesIn(fakeQuantizeOnDataValues)),
+ FuseFakeQuantizeAndScaleShiftTransformation::getTestCaseName);
+} // namespace
R"(.*(QuantGroupConv2D).*)",
R"(.*(QuantGroupConv3D).*)",
// TODO: Issue 31845
- R"(.*(FakeQuantize).*)",
+ R"(.*(FakeQuantizeLayerTest).*)",
R"(.*(EltwiseLayerTest).*IS=\(.*\..*\..*\..*\..*\).*secondaryInputType=PARAMETER.*opType=SCALAR.*)",
// TODO: Issue 32756
R"(.*Transpose.*inputOrder=\(\).*)",
--- /dev/null
+// Copyright (C) 2020 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#include <vector>
+
+#include "low_precision_transformations/fuse_fake_quantize_and_scale_shift_transformation.hpp"
+#include "common_test_utils/test_constants.hpp"
+#include "ngraph_functions/low_precision_transformations/fuse_fake_quantize_and_scale_shift_function.hpp"
+
+using namespace LayerTestsDefinitions;
+using namespace InferenceEngine::details;
+
+namespace {
+const std::vector<InferenceEngine::Precision> netPrecisions = {
+ InferenceEngine::Precision::FP32
+};
+
+const std::vector<LayerTransformation::Params> trasformationParamValues = {
+ LayerTestsUtils::LayerTransformationParamsFactory::createParamsU8I8()
+};
+
+const std::vector<ngraph::builder::subgraph::FakeQuantizeOnData> fakeQuantizeOnDataValues = {
+ { 256ul, {}, { 0.f }, { 2.55f }, { 0.f }, { 2.55f } },
+ {
+ 256ul,
+ { 1ul, 3ul, 1ul, 1ul },
+ { 0.f, 0.f, 0.f },
+ { 2.55f / 10.f, 2.55f / 5.f, 2.55f / 2.f },
+ { 0.f, 0.f, 0.f },
+ { 2.55f / 10.f, 2.55f / 5.f, 2.55f / 2.f }
+ },
+};
+
+INSTANTIATE_TEST_CASE_P(LPT, FuseFakeQuantizeAndScaleShiftTransformation,
+ ::testing::Combine(
+ ::testing::ValuesIn(netPrecisions),
+ ::testing::Values(InferenceEngine::SizeVector({ 1, 3, 9, 9 })),
+ ::testing::Values(CommonTestUtils::DEVICE_GPU),
+ ::testing::ValuesIn(trasformationParamValues),
+ ::testing::ValuesIn(fakeQuantizeOnDataValues)),
+ FuseFakeQuantizeAndScaleShiftTransformation::getTestCaseName);
+} // namespace
--- /dev/null
+// Copyright (C) 2020 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#pragma once
+
+#include <string>
+#include <memory>
+#include "ngraph_functions/low_precision_transformations/fuse_fake_quantize_and_scale_shift_function.hpp"
+#include "functional_test_utils/low_precision_transformations/layer_transformation.hpp"
+
+namespace LayerTestsDefinitions {
+
+typedef std::tuple<
+ InferenceEngine::Precision,
+ InferenceEngine::SizeVector,
+ std::string,
+ InferenceEngine::details::LayerTransformation::Params,
+ ngraph::builder::subgraph::FakeQuantizeOnData> FuseFakeQuantizeAndScaleShiftTransformationParams;
+
+class FuseFakeQuantizeAndScaleShiftTransformation :
+ public testing::WithParamInterface<FuseFakeQuantizeAndScaleShiftTransformationParams>,
+ public LayerTestsUtils::LayerTransformation {
+public:
+ static std::string getTestCaseName(testing::TestParamInfo<FuseFakeQuantizeAndScaleShiftTransformationParams> obj);
+
+protected:
+ void SetUp() override;
+
+private:
+ void validate(const std::string& referenceOutputLayerName);
+};
+
+} // namespace LayerTestsDefinitions
--- /dev/null
+// Copyright (C) 2020 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#include "low_precision_transformations/fuse_fake_quantize_and_scale_shift_transformation.hpp"
+
+#include <memory>
+#include <tuple>
+#include <vector>
+#include <string>
+#include <ie_core.hpp>
+
+#include <transformations/init_node_info.hpp>
+
+namespace LayerTestsDefinitions {
+
+std::string FuseFakeQuantizeAndScaleShiftTransformation::getTestCaseName(testing::TestParamInfo<FuseFakeQuantizeAndScaleShiftTransformationParams> obj) {
+ InferenceEngine::Precision netPrecision;
+ InferenceEngine::SizeVector inputShapes;
+ std::string targetDevice;
+ InferenceEngine::details::LayerTransformation::Params params;
+ ngraph::builder::subgraph::FakeQuantizeOnData fakeQuantizeOnData;
+ std::tie(netPrecision, inputShapes, targetDevice, params, fakeQuantizeOnData) = obj.param;
+
+ std::ostringstream result;
+ result << netPrecision << "_" << targetDevice << "_" << fakeQuantizeOnData;
+ return result.str();
+}
+
+void FuseFakeQuantizeAndScaleShiftTransformation::SetUp() {
+ InferenceEngine::SizeVector inputShape;
+ InferenceEngine::Precision netPrecision;
+ InferenceEngine::details::LayerTransformation::Params params;
+ ngraph::builder::subgraph::FakeQuantizeOnData fakeQuantizeOnData;
+ std::tie(netPrecision, inputShape, targetDevice, params, fakeQuantizeOnData) = this->GetParam();
+
+ function = ngraph::builder::subgraph::FuseFakeQuantizeAndScaleShiftFunction::getOriginal(
+ FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision),
+ inputShape,
+ fakeQuantizeOnData);
+
+ ngraph::pass::InitNodeInfo().run_on_function(function);
+
+ EXPECT_EQ(1ul, function->get_output_size());
+ EXPECT_EQ(1ul, function->get_output_op(0)->get_input_size());
+ const std::string referenceOutputLayerName = function->get_output_op(0)->get_input_node_ptr(0)->get_friendly_name();
+
+ validate(referenceOutputLayerName);
+}
+
+void FuseFakeQuantizeAndScaleShiftTransformation::validate(const std::string& referenceOutputLayerName) {
+ InferenceEngine::SizeVector inputShape;
+ InferenceEngine::Precision netPrecision;
+ InferenceEngine::details::LayerTransformation::Params params;
+ ngraph::builder::subgraph::FakeQuantizeOnData fakeQuantizeOnData;
+ std::tie(netPrecision, inputShape, targetDevice, params, fakeQuantizeOnData) = this->GetParam();
+
+ auto transformations = getLowPrecisionTransformations(params);
+ const InferenceEngine::CNNNetwork network = transform(transformations);
+
+ IE_SUPPRESS_DEPRECATED_START
+
+ InferenceEngine::OutputsDataMap outputs = network.getOutputsInfo();
+ EXPECT_EQ(1, outputs.size());
+
+ std::map<std::string, InferenceEngine::DataPtr>::iterator it = outputs.begin();
+ const InferenceEngine::CNNLayerPtr outputLayer = getCreatorLayer(it->second).lock();
+ EXPECT_TRUE(outputLayer != nullptr);
+ EXPECT_EQ("FakeQuantize", outputLayer->type);
+ EXPECT_EQ(referenceOutputLayerName, outputLayer->name);
+
+ IE_SUPPRESS_DEPRECATED_END
+}
+
+TEST_P(FuseFakeQuantizeAndScaleShiftTransformation, CompareWithRefImpl) {
+ Run();
+};
+
+} // namespace LayerTestsDefinitions
--- /dev/null
+// Copyright (C) 2020 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#pragma once
+
+#include <algorithm>
+#include <memory>
+#include <ngraph/ngraph.hpp>
+#include "common/fake_quantize_on_data.hpp"
+
+namespace ngraph {
+namespace builder {
+namespace subgraph {
+
+class FuseFakeQuantizeAndScaleShiftFunction {
+public:
+ static std::shared_ptr<ngraph::Function> getOriginal(
+ const ngraph::element::Type precision,
+ const ngraph::Shape& inputShape,
+ const FakeQuantizeOnData& fakeQuantizeOnData);
+};
+
+} // namespace subgraph
+} // namespace builder
+} // namespace ngraph
--- /dev/null
+// Copyright (C) 2020 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#include "ngraph_functions/low_precision_transformations/fuse_fake_quantize_and_scale_shift_function.hpp"
+
+#include <ngraph/opsets/opset1.hpp>
+#include "ngraph_functions/builders.hpp"
+
+namespace ngraph {
+namespace builder {
+namespace subgraph {
+
+using namespace ngraph::pass;
+
+std::shared_ptr<ngraph::Function> FuseFakeQuantizeAndScaleShiftFunction::getOriginal(
+ const ngraph::element::Type precision,
+ const ngraph::Shape& inputShape,
+ const FakeQuantizeOnData& fakeQuantizeOnData) {
+ const auto input = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape));
+ input->set_friendly_name("input");
+
+ const std::shared_ptr<Node> fakeQuantize = ngraph::builder::makeFakeQuantize(
+ input, precision, fakeQuantizeOnData.quantizationLevel, fakeQuantizeOnData.constantShape,
+ fakeQuantizeOnData.inputLowValues, fakeQuantizeOnData.inputHighValues, fakeQuantizeOnData.outputLowValues, fakeQuantizeOnData.outputHighValues);
+ fakeQuantize->set_friendly_name("fakeQuantize");
+
+ const std::shared_ptr<Node> multiply = std::make_shared<ngraph::opset1::Multiply>(
+ fakeQuantize,
+ std::make_shared<ngraph::opset1::Constant>(precision, Shape{ 1, 1, 1, 1 }, std::vector<float>({ 150 })));
+
+ const std::shared_ptr<Node> add = std::make_shared<ngraph::opset1::Add>(
+ multiply,
+ std::make_shared<ngraph::opset1::Constant>(precision, Shape{ 1, 1, 1, 1 }, std::vector<float>({ 127.5 })));
+
+ const ngraph::ResultVector results{ std::make_shared<ngraph::opset1::Result>(add) };
+ return std::make_shared<ngraph::Function>(results, ngraph::ParameterVector{ input }, "FuseFakeQuantizeAndScaleShiftFunction");
+}
+
+} // namespace subgraph
+} // namespace builder
+} // namespace ngraph