[LPT] FuseFakeQuantizeAndScaleShift transformation for last layer fix (#1291)

* [LPT] FuseFakeQuantizeAndScaleShift transformation for last layer fix

* [LPT] refactoring

* [LPT] FuseFakeQuantizeAndScaleShift test: last layer name validation was added
This commit is contained in:
Edward Shogulin 2020-07-14 18:55:06 +03:00 committed by GitHub
parent 0607b7b0f7
commit d791962464
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 286 additions and 1 deletions

View File

@ -38,6 +38,7 @@ void FuseFakeQuantizeAndScaleShiftTransformation::transform(
}
auto dScaleShift = dScaleShiftsVector[0];
const Blob::Ptr scalesBlob = CNNNetworkHelper::getBlob(dScaleShift, "weights");
auto scalesBufferPtr = CNNNetworkHelper::getFloatData(scalesBlob);
@ -55,9 +56,21 @@ void FuseFakeQuantizeAndScaleShiftTransformation::transform(
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);
@ -144,4 +157,9 @@ void FuseFakeQuantizeAndScaleShiftTransformation::transform(
auto ssPrecision = dScaleShiftsVector[0]->outData[0]->getPrecision();
fakeQuantizeLayer.outData[0]->setPrecision(ssPrecision);
}
if (dScaleShiftIsLastLayer) {
CNNNetworkHelper::renameLayer(context.network, fakeQuantizeLayer.name, dScaleShift->name);
}
}

View File

@ -0,0 +1,43 @@
// 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

View File

@ -21,7 +21,7 @@ std::vector<std::string> disabledTestPatterns() {
R"(.*(QuantGroupConv2D).*)",
R"(.*(QuantGroupConv3D).*)",
// TODO: Issue 31845
R"(.*(FakeQuantize).*)",
R"(.*(FakeQuantizeLayerTest).*)",
R"(.*(EltwiseLayerTest).*IS=\(.*\..*\..*\..*\..*\).*secondaryInputType=PARAMETER.*opType=SCALAR.*)",
// TODO: Issue 32756
R"(.*Transpose.*inputOrder=\(\).*)",

View File

@ -0,0 +1,43 @@
// 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

View File

@ -0,0 +1,34 @@
// 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

View File

@ -0,0 +1,79 @@
// 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

View File

@ -0,0 +1,26 @@
// 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

View File

@ -0,0 +1,42 @@
// 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