From f9ac55585748b8fd1eb1515f51a36899645de50e Mon Sep 17 00:00:00 2001 From: Edward Shogulin Date: Fri, 5 Jun 2020 10:54:38 +0300 Subject: [PATCH] [LPT] Output layers update fix (#754) --- .../low_precision_transformations/concat.hpp | 1 + .../low_precision_transformations/src/concat.cpp | 6 +- .../src/concat_multi_channels.cpp | 22 ++- .../src/network_helper.cpp | 5 - ...yers_handling_in_transformations_for_concat.cpp | 32 ++++ ...in_transformations_for_concat_multi_channel.cpp | 32 ++++ ...yers_handling_in_transformations_for_concat.cpp | 29 ++++ ...in_transformations_for_concat_multi_channel.cpp | 29 ++++ ...yers_handling_in_transformations_for_concat.hpp | 28 ++++ ...in_transformations_for_concat_multi_channel.hpp | 35 +++++ .../output_layers_handling_in_transformations.cpp | 103 +++++------- ...yers_handling_in_transformations_for_concat.cpp | 172 +++++++++++++++++++++ ...in_transformations_for_concat_multi_channel.cpp | 152 ++++++++++++++++++ 13 files changed, 572 insertions(+), 74 deletions(-) create mode 100644 inference-engine/tests/functional/plugin/cpu/shared_tests_instances/low_precision_transformations/output_layers_handling_in_transformations_for_concat.cpp create mode 100644 inference-engine/tests/functional/plugin/cpu/shared_tests_instances/low_precision_transformations/output_layers_handling_in_transformations_for_concat_multi_channel.cpp create mode 100644 inference-engine/tests/functional/plugin/gpu/shared_tests_instances/low_precision_transformations/output_layers_handling_in_transformations_for_concat.cpp create mode 100644 inference-engine/tests/functional/plugin/gpu/shared_tests_instances/low_precision_transformations/output_layers_handling_in_transformations_for_concat_multi_channel.cpp create mode 100644 inference-engine/tests/functional/plugin/shared/include/low_precision_transformations/output_layers_handling_in_transformations_for_concat.hpp create mode 100644 inference-engine/tests/functional/plugin/shared/include/low_precision_transformations/output_layers_handling_in_transformations_for_concat_multi_channel.hpp create mode 100644 inference-engine/tests/functional/plugin/shared/src/low_precision_transformations/output_layers_handling_in_transformations_for_concat.cpp create mode 100644 inference-engine/tests/functional/plugin/shared/src/low_precision_transformations/output_layers_handling_in_transformations_for_concat_multi_channel.cpp diff --git a/inference-engine/src/low_precision_transformations/include/low_precision_transformations/concat.hpp b/inference-engine/src/low_precision_transformations/include/low_precision_transformations/concat.hpp index 7dc29da..6895a11 100644 --- a/inference-engine/src/low_precision_transformations/include/low_precision_transformations/concat.hpp +++ b/inference-engine/src/low_precision_transformations/include/low_precision_transformations/concat.hpp @@ -29,6 +29,7 @@ protected: Subgraph& subgraph, std::function& dequantizationScales, std::vector& dequantizationShifts)> getLayerDequantizationCallback) const; diff --git a/inference-engine/src/low_precision_transformations/src/concat.cpp b/inference-engine/src/low_precision_transformations/src/concat.cpp index f3d7b22..bbb0d3d 100644 --- a/inference-engine/src/low_precision_transformations/src/concat.cpp +++ b/inference-engine/src/low_precision_transformations/src/concat.cpp @@ -207,6 +207,7 @@ void ConcatTransformation::transform(TransformationContext& context, CNNLayer& c auto dequantizationValuesCallback = [&]( const CNNLayer& layer, + const std::string& originalLayerName, std::vector& layerDequantizationScales, std::vector& layerDequantizationShifts ) { @@ -231,6 +232,7 @@ void ConcatTransformation::addDequantizationLayers( Subgraph& subgraph, std::function& dequantizationScales, std::vector& dequantizationShifts)> getLayerDequantizationCallback) const { OutputsDataMap outputs; @@ -249,7 +251,7 @@ void ConcatTransformation::addDequantizationLayers( for (const CNNLayerPtr& child : children) { if (subgraph.layers.find(child->name) == subgraph.layers.end()) { if (layerDequantizationScales.size() == 0ul) { - getLayerDequantizationCallback(*layer, layerDequantizationScales, layerDequantizationShifts); + getLayerDequantizationCallback(*layer, layer->name, layerDequantizationScales, layerDequantizationShifts); } CNNLayerPtr dequantizationLayer = CNNNetworkHelper::addScaleShiftBetween( @@ -271,7 +273,7 @@ void ConcatTransformation::addDequantizationLayers( subgraph.layers[layer->name] = layer; if (layerDequantizationScales.size() == 0ul) { - getLayerDequantizationCallback(*layer, layerDequantizationScales, layerDequantizationShifts); + getLayerDequantizationCallback(*layer, originalName, layerDequantizationScales, layerDequantizationShifts); } CNNLayerPtr dequantizationLayer = CNNNetworkHelper::addScaleShiftBetween( diff --git a/inference-engine/src/low_precision_transformations/src/concat_multi_channels.cpp b/inference-engine/src/low_precision_transformations/src/concat_multi_channels.cpp index ffad5f9..d6c5937 100644 --- a/inference-engine/src/low_precision_transformations/src/concat_multi_channels.cpp +++ b/inference-engine/src/low_precision_transformations/src/concat_multi_channels.cpp @@ -120,10 +120,26 @@ void ConcatMultiChannelsTransformation::transform(TransformationContext& context } auto dequantizationValuesCallback = [&]( - const CNNLayer& layer, - std::vector& dequantizationScales, - std::vector& dequantizationShifts + const CNNLayer& layer, + const std::string originalLayerName, + std::vector& dequantizationScales, + std::vector& dequantizationShifts ) { + if (layer.name != originalLayerName) { + const auto update = []( + const std::string& originalLayerName, + const std::string& newLayerName, + std::unordered_map>& dequantizationLayers) { + auto it = dequantizationLayers.find(originalLayerName); + if (it != dequantizationLayers.end()) { + dequantizationLayers.emplace(newLayerName, it->second); + dequantizationLayers.erase(it); + } + }; + update(originalLayerName, layer.name, dequantizationScalesLayers); + update(originalLayerName, layer.name, dequantizationShiftsLayers); + } + fillDequantization( layer, dequantizationScalesLayers, dequantizationShiftsLayers, diff --git a/inference-engine/src/low_precision_transformations/src/network_helper.cpp b/inference-engine/src/low_precision_transformations/src/network_helper.cpp index d718736..06347ec 100644 --- a/inference-engine/src/low_precision_transformations/src/network_helper.cpp +++ b/inference-engine/src/low_precision_transformations/src/network_helper.cpp @@ -1318,11 +1318,6 @@ size_t CNNNetworkHelper::disconnectLayers(CNNNetworkImpl* network, const CNNLaye THROW_IE_EXCEPTION << "Output layer for '" << parentLayer->name << "'is absent"; } if (currentChildLayer->name == childLayer->name) { - const DataPtr dataToRemove = network->getData(data->getName().c_str()); - if (!dataToRemove) { - THROW_IE_EXCEPTION << "there is not data to remove"; - } - data->getInputTo().erase(inputIt); wasFound = true; break; diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/low_precision_transformations/output_layers_handling_in_transformations_for_concat.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/low_precision_transformations/output_layers_handling_in_transformations_for_concat.cpp new file mode 100644 index 0000000..6b2c04c --- /dev/null +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/low_precision_transformations/output_layers_handling_in_transformations_for_concat.cpp @@ -0,0 +1,32 @@ +// Copyright (C) 2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "low_precision_transformations/output_layers_handling_in_transformations_for_concat.hpp" +#include "common_test_utils/test_constants.hpp" + +using namespace LayerTestsDefinitions; +using namespace InferenceEngine::details; + +namespace { +const std::vector netPrecisions = { + InferenceEngine::Precision::FP32, + InferenceEngine::Precision::FP16 +}; + +const std::vector trasformationParamValues = { + LayerTestsUtils::LayerTransformationParamsFactory::createParams(), + LayerTestsUtils::LayerTransformationParamsFactory::createParamsI8I8(), + LayerTestsUtils::LayerTransformationParamsFactory::createParamsU8I8() +}; + +INSTANTIATE_TEST_CASE_P(LPT, OutputLayersHandlingInTransformationsForConcat, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(InferenceEngine::SizeVector({ 1, 3, 16, 16 })), + ::testing::Values(CommonTestUtils::DEVICE_CPU), + ::testing::ValuesIn(trasformationParamValues)), + OutputLayersHandlingInTransformationsForConcat::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/low_precision_transformations/output_layers_handling_in_transformations_for_concat_multi_channel.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/low_precision_transformations/output_layers_handling_in_transformations_for_concat_multi_channel.cpp new file mode 100644 index 0000000..e85b5a6 --- /dev/null +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/low_precision_transformations/output_layers_handling_in_transformations_for_concat_multi_channel.cpp @@ -0,0 +1,32 @@ +// Copyright (C) 2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "low_precision_transformations/output_layers_handling_in_transformations_for_concat_multi_channel.hpp" +#include "common_test_utils/test_constants.hpp" + +using namespace LayerTestsDefinitions; +using namespace InferenceEngine::details; + +namespace { +const std::vector netPrecisions = { + InferenceEngine::Precision::FP32, + InferenceEngine::Precision::FP16 +}; + +const std::vector trasformationParamValues = { + LayerTestsUtils::LayerTransformationParamsFactory::createParams(), + LayerTestsUtils::LayerTransformationParamsFactory::createParamsI8I8(), + LayerTestsUtils::LayerTransformationParamsFactory::createParamsU8I8() +}; + +INSTANTIATE_TEST_CASE_P(LPT, OutputLayersHandlingInTransformationsForConcatMultiChannel, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(InferenceEngine::SizeVector({ 1, 3, 16, 16 })), + ::testing::Values(CommonTestUtils::DEVICE_CPU), + ::testing::ValuesIn(trasformationParamValues)), + OutputLayersHandlingInTransformationsForConcatMultiChannel::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/low_precision_transformations/output_layers_handling_in_transformations_for_concat.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/low_precision_transformations/output_layers_handling_in_transformations_for_concat.cpp new file mode 100644 index 0000000..1e8a80d --- /dev/null +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/low_precision_transformations/output_layers_handling_in_transformations_for_concat.cpp @@ -0,0 +1,29 @@ +// Copyright (C) 2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "low_precision_transformations/output_layers_handling_in_transformations.hpp" +#include "common_test_utils/test_constants.hpp" + +using namespace LayerTestsDefinitions; +using namespace InferenceEngine::details; + +namespace { +const std::vector netPrecisions = { + InferenceEngine::Precision::FP32 +}; + +const std::vector trasformationParamValues = { + LayerTestsUtils::LayerTransformationParamsFactory::createParams() +}; + +INSTANTIATE_TEST_CASE_P(LPT, OutputLayersHandlingInTransformations, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(InferenceEngine::SizeVector({ 1, 3, 16, 16 })), + ::testing::Values(CommonTestUtils::DEVICE_GPU), + ::testing::ValuesIn(trasformationParamValues)), + OutputLayersHandlingInTransformations::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/low_precision_transformations/output_layers_handling_in_transformations_for_concat_multi_channel.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/low_precision_transformations/output_layers_handling_in_transformations_for_concat_multi_channel.cpp new file mode 100644 index 0000000..1e8a80d --- /dev/null +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/low_precision_transformations/output_layers_handling_in_transformations_for_concat_multi_channel.cpp @@ -0,0 +1,29 @@ +// Copyright (C) 2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "low_precision_transformations/output_layers_handling_in_transformations.hpp" +#include "common_test_utils/test_constants.hpp" + +using namespace LayerTestsDefinitions; +using namespace InferenceEngine::details; + +namespace { +const std::vector netPrecisions = { + InferenceEngine::Precision::FP32 +}; + +const std::vector trasformationParamValues = { + LayerTestsUtils::LayerTransformationParamsFactory::createParams() +}; + +INSTANTIATE_TEST_CASE_P(LPT, OutputLayersHandlingInTransformations, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(InferenceEngine::SizeVector({ 1, 3, 16, 16 })), + ::testing::Values(CommonTestUtils::DEVICE_GPU), + ::testing::ValuesIn(trasformationParamValues)), + OutputLayersHandlingInTransformations::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/plugin/shared/include/low_precision_transformations/output_layers_handling_in_transformations_for_concat.hpp b/inference-engine/tests/functional/plugin/shared/include/low_precision_transformations/output_layers_handling_in_transformations_for_concat.hpp new file mode 100644 index 0000000..5ee5d73 --- /dev/null +++ b/inference-engine/tests/functional/plugin/shared/include/low_precision_transformations/output_layers_handling_in_transformations_for_concat.hpp @@ -0,0 +1,28 @@ +// Copyright (C) 2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include + +#include "functional_test_utils/low_precision_transformations/layer_transformation.hpp" + +namespace LayerTestsDefinitions { + +class OutputLayersHandlingInTransformationsForConcat : + public testing::WithParamInterface, + public LayerTestsUtils::LayerTransformation { +public: + static std::string getTestCaseName(testing::TestParamInfo obj); + InferenceEngine::Blob::Ptr GenerateInput(const InferenceEngine::InputInfo &info) const override; + +protected: + void SetUp() override; + +private: + void validate(); +}; + +} // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/shared/include/low_precision_transformations/output_layers_handling_in_transformations_for_concat_multi_channel.hpp b/inference-engine/tests/functional/plugin/shared/include/low_precision_transformations/output_layers_handling_in_transformations_for_concat_multi_channel.hpp new file mode 100644 index 0000000..cc75618 --- /dev/null +++ b/inference-engine/tests/functional/plugin/shared/include/low_precision_transformations/output_layers_handling_in_transformations_for_concat_multi_channel.hpp @@ -0,0 +1,35 @@ +// Copyright (C) 2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include + +#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, + bool> OutputLayersHandlingInTransformationsParams; + +class OutputLayersHandlingInTransformationsForConcatMultiChannel : + public testing::WithParamInterface, + public LayerTestsUtils::LayerTransformation { +public: + static std::string getTestCaseName(testing::TestParamInfo obj); + InferenceEngine::Blob::Ptr GenerateInput(const InferenceEngine::InputInfo &info) const override; + +protected: + void SetUp() override; + +private: + void validate(); +}; + +} // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/shared/src/low_precision_transformations/output_layers_handling_in_transformations.cpp b/inference-engine/tests/functional/plugin/shared/src/low_precision_transformations/output_layers_handling_in_transformations.cpp index fddf40a..c86a874 100644 --- a/inference-engine/tests/functional/plugin/shared/src/low_precision_transformations/output_layers_handling_in_transformations.cpp +++ b/inference-engine/tests/functional/plugin/shared/src/low_precision_transformations/output_layers_handling_in_transformations.cpp @@ -21,13 +21,6 @@ namespace LayerTestsDefinitions { -std::pair outputLayersHandlingInTransformationsGetInterval(const std::vector& precisions) { - const bool unsignedInterval = std::find(precisions.begin(), precisions.end(), InferenceEngine::Precision::U8) != precisions.end(); - const float low = unsignedInterval ? 0.f : -128.f; - const float hight = unsignedInterval ? 255.f : 127.f; - return std::make_pair(low, hight); -} - std::string OutputLayersHandlingInTransformations::getTestCaseName(testing::TestParamInfo obj) { InferenceEngine::Precision netPrecision; InferenceEngine::SizeVector inputShapes; @@ -47,69 +40,46 @@ InferenceEngine::Blob::Ptr OutputLayersHandlingInTransformations::GenerateInput( InferenceEngine::details::LayerTransformation::Params params; std::tie(netPrecision, inputShape, targetDevice, params) = this->GetParam(); - if ((info.name() != "input1") && (info.name() != "input2")) { - THROW_IE_EXCEPTION << "unexpected input name " << info.name(); - } - const float k = (info.name() == "input1") ? 1.f : (info.name() == "input2" ? 2.f : 3.f); - - const auto interval = outputLayersHandlingInTransformationsGetInterval(params.precisionsOnActivations); - const float low = interval.first / k; - const float hight = interval.second / k; + const float k = 1.f; + const float low = 0.f / k; + const float hight = 255.f / k; InferenceEngine::Blob::Ptr input = FuncTestUtils::createAndFillBlobConsistently(info.getTensorDesc(), hight - low, static_cast(low), 1ul); const auto buffer = input->buffer().as(); return input; } -/* -* FQ1 FQ2 -* \ / \ -* \ / Output -* Concat -* / \ -* / \ -* Convolution Output -* / -* / -* Output -*/ - void OutputLayersHandlingInTransformations::SetUp() { threshold = 0.05; - InferenceEngine::SizeVector inputShape1; + InferenceEngine::SizeVector inputShape; InferenceEngine::Precision netPrecision; InferenceEngine::details::LayerTransformation::Params params; - std::tie(netPrecision, inputShape1, targetDevice, params) = this->GetParam(); + std::tie(netPrecision, inputShape, targetDevice, params) = this->GetParam(); auto ngPrecision = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); - const auto input1 = std::make_shared(ngPrecision, ngraph::Shape(inputShape1)); - input1->set_friendly_name("input1"); + const auto input = std::make_shared(ngPrecision, ngraph::Shape(inputShape)); + input->set_friendly_name("input"); - const auto fakeQuantize1 = ngraph::builder::makeFakeQuantize(input1->output(0), ngPrecision, 256ul, { 1ul }); - fakeQuantize1->set_friendly_name("fakeQuantize1"); - - ASSERT_EQ(4ul, inputShape1.size()) << "unexpected input layout"; - const InferenceEngine::SizeVector inputShape2 = { inputShape1[0], inputShape1[1] * 2ul, inputShape1[2], inputShape1[3] }; - const auto input2 = std::make_shared(ngPrecision, ngraph::Shape(inputShape2)); - input2->set_friendly_name("input2"); - - const auto fakeQuantize2 = ngraph::builder::makeFakeQuantize(input2->output(0), ngPrecision, 256ul, { 1ul }); - fakeQuantize2->set_friendly_name("fakeQuantize2"); - - const std::shared_ptr concat = std::make_shared( - ngraph::OutputVector{ fakeQuantize1->output(0), fakeQuantize2->output(0)}, 1); - concat->set_friendly_name("concat"); + const float k = 1.f; + const auto fakeQuantizeOnActivations = ngraph::builder::makeFakeQuantize( + input->output(0), ngPrecision, 256ul, { 1ul }, + { 0.f }, { 255.f / k }, { 0.f }, { 255.f / k }); + fakeQuantizeOnActivations->set_friendly_name("fakeQuantizeOnActivations"); const auto weights = ngraph::opset1::Constant::create( ngPrecision, - ngraph::Shape{ inputShape1[1ul] + inputShape2[1ul], inputShape1[1ul] + inputShape2[1ul], 1ul, 1ul }, - std::vector((inputShape1[1ul] + inputShape2[1ul]) * (inputShape1[1ul] + inputShape2[1ul]), 1ul)); + ngraph::Shape{ inputShape[1ul], inputShape[1ul], 1ul, 1ul }, + std::vector(inputShape[1ul] * inputShape[1ul], 1ul)); weights->set_friendly_name("weights"); - - const auto convolution = std::make_shared( - concat->output(0), - weights, + const auto fakeQuantizeOnWeights = ngraph::builder::makeFakeQuantize( + weights, ngPrecision, 256ul, { 1ul }, + { -128.f / k }, { 127.f / k }, { -128.f / k }, { 127.f / k }); + fakeQuantizeOnWeights->set_friendly_name("fakeQuantizeOnWeights"); + + std::shared_ptr convolution = std::make_shared( + fakeQuantizeOnActivations, + fakeQuantizeOnWeights, ngraph::Strides{ 1ul, 1ul }, ngraph::CoordinateDiff{ 0, 0 }, ngraph::CoordinateDiff{ 0, 0 }, @@ -117,12 +87,11 @@ void OutputLayersHandlingInTransformations::SetUp() { convolution->set_friendly_name("convolution"); ngraph::ResultVector results { - std::make_shared(concat), std::make_shared(convolution), - std::make_shared(fakeQuantize2) + std::make_shared(fakeQuantizeOnActivations) }; - function = std::make_shared(results, ngraph::ParameterVector { input1, input2 }, "OutputLayersHandling"); + function = std::make_shared(results, ngraph::ParameterVector { input }, "OutputLayersHandling"); // TODO: move to some another place validate(); @@ -140,15 +109,21 @@ void OutputLayersHandlingInTransformations::validate() { IE_SUPPRESS_DEPRECATED_START InferenceEngine::OutputsDataMap outputs = network.getOutputsInfo(); - EXPECT_EQ(3, outputs.size()); - - const auto concatIt = outputs.find("concat"); - EXPECT_TRUE(concatIt != outputs.end()); - EXPECT_EQ("ScaleShift", concatIt->second->getCreatorLayer().lock()->type); - - const auto fakeQuantize2It = outputs.find("fakeQuantize2"); - EXPECT_TRUE(fakeQuantize2It != outputs.end()); - EXPECT_EQ("ScaleShift", fakeQuantize2It->second->getCreatorLayer().lock()->type); + EXPECT_EQ(2, outputs.size()); + + const auto fakeQuantizeOnActivationsIt = outputs.find("fakeQuantizeOnActivations"); + const auto convolutionIt = outputs.find("convolution"); + EXPECT_TRUE(convolutionIt != outputs.end()); + if (std::any_of( + params.precisionsOnActivations.begin(), + params.precisionsOnActivations.end(), + [](const float value) { return value == InferenceEngine::Precision::U8; })) { + EXPECT_EQ("ScaleShift", fakeQuantizeOnActivationsIt->second->getCreatorLayer().lock()->type); + EXPECT_EQ("ScaleShift", convolutionIt->second->getCreatorLayer().lock()->type); + } else { + EXPECT_EQ("FakeQuantize", fakeQuantizeOnActivationsIt->second->getCreatorLayer().lock()->type); + EXPECT_EQ("Convolution", convolutionIt->second->getCreatorLayer().lock()->type); + } IE_SUPPRESS_DEPRECATED_END } diff --git a/inference-engine/tests/functional/plugin/shared/src/low_precision_transformations/output_layers_handling_in_transformations_for_concat.cpp b/inference-engine/tests/functional/plugin/shared/src/low_precision_transformations/output_layers_handling_in_transformations_for_concat.cpp new file mode 100644 index 0000000..aebcb13 --- /dev/null +++ b/inference-engine/tests/functional/plugin/shared/src/low_precision_transformations/output_layers_handling_in_transformations_for_concat.cpp @@ -0,0 +1,172 @@ +// Copyright (C) 2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "low_precision_transformations/output_layers_handling_in_transformations_for_concat.hpp" + +#include +#include +#include +#include + +#include + +#include "common_test_utils/common_utils.hpp" +#include "functional_test_utils/plugin_cache.hpp" +#include "functional_test_utils/layer_test_utils.hpp" +#include "functional_test_utils/blob_utils.hpp" + +#include "ngraph_functions/pass/convert_prc.hpp" +#include "ngraph_functions/builders.hpp" + +namespace LayerTestsDefinitions { + +std::string OutputLayersHandlingInTransformationsForConcat::getTestCaseName(testing::TestParamInfo obj) { + InferenceEngine::Precision netPrecision; + InferenceEngine::SizeVector inputShapes; + std::string targetDevice; + InferenceEngine::details::LayerTransformation::Params params; + std::tie(netPrecision, inputShapes, targetDevice, params) = obj.param; + + std::ostringstream result; + result << netPrecision.name() << "_" << targetDevice << "_" << toString(params); + return result.str(); +} + +InferenceEngine::Blob::Ptr OutputLayersHandlingInTransformationsForConcat::GenerateInput(const InferenceEngine::InputInfo &info) const { + InferenceEngine::SizeVector inputShape; + InferenceEngine::Precision netPrecision; + std::string targetDevice; + InferenceEngine::details::LayerTransformation::Params params; + std::tie(netPrecision, inputShape, targetDevice, params) = this->GetParam(); + + if ((info.name() != "input1") && (info.name() != "input2")) { + THROW_IE_EXCEPTION << "unexpected input name " << info.name(); + } + const float k = (info.name() == "input1") ? 1.f : 2.f; + + const float low = 0.f / k; + const float hight = 255.f / k; + InferenceEngine::Blob::Ptr input = FuncTestUtils::createAndFillBlobConsistently(info.getTensorDesc(), hight - low, static_cast(low), 1ul); + const auto buffer = input->buffer().as(); + return input; +} + +/* +* FQ1 FQ2 +* \ / \ +* \ / Output +* Concat +* / \ +* / \ +* Convolution Output +* / +* / +* Output +*/ + +void OutputLayersHandlingInTransformationsForConcat::SetUp() { + InferenceEngine::SizeVector inputShape1; + InferenceEngine::Precision netPrecision; + InferenceEngine::details::LayerTransformation::Params params; + std::tie(netPrecision, inputShape1, targetDevice, params) = this->GetParam(); + auto ngPrecision = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); + + const auto input1 = std::make_shared(ngPrecision, ngraph::Shape(inputShape1)); + input1->set_friendly_name("input1"); + + const float low = 0.f; + const float hight = 255.f; + const auto fakeQuantize1 = ngraph::builder::makeFakeQuantize( + input1->output(0), ngPrecision, 256ul, { 1ul }, + { 0.f }, { 255.f }, { 0.f }, { 255.f }); + fakeQuantize1->set_friendly_name("fakeQuantize1"); + + ASSERT_EQ(4ul, inputShape1.size()) << "unexpected input layout"; + const InferenceEngine::SizeVector inputShape2 = { inputShape1[0], inputShape1[1] * 2ul, inputShape1[2], inputShape1[3] }; + const auto input2 = std::make_shared(ngPrecision, ngraph::Shape(inputShape2)); + input2->set_friendly_name("input2"); + + const auto fakeQuantize2 = ngraph::builder::makeFakeQuantize( + input2->output(0), ngPrecision, 256ul, { 1ul }, + { 0.f }, { 255.f / 2.f }, { 0.f }, { 255.f / 2.f }); + fakeQuantize2->set_friendly_name("fakeQuantize2"); + + const std::shared_ptr concat = std::make_shared( + ngraph::OutputVector{ fakeQuantize1->output(0), fakeQuantize2->output(0)}, 1); + concat->set_friendly_name("concat"); + + const float k = 1.f; + const auto weights = ngraph::opset1::Constant::create( + ngPrecision, + ngraph::Shape{ inputShape1[1ul] + inputShape2[1ul], inputShape1[1ul] + inputShape2[1ul], 1ul, 1ul }, + std::vector((inputShape1[1ul] + inputShape2[1ul]) * (inputShape1[1ul] + inputShape2[1ul]), 1ul)); + weights->set_friendly_name("weights"); + const auto fakeQuantizeOnWeights = ngraph::builder::makeFakeQuantize( + weights, ngPrecision, 256ul, { 1ul }, + { -128.f / k }, { 127.f / k }, { -128.f / k }, { 127.f / k }); + fakeQuantizeOnWeights->set_friendly_name("fakeQuantizeOnWeights"); + + const std::shared_ptr convolution = std::make_shared( + concat->output(0), + fakeQuantizeOnWeights, + ngraph::Strides{ 1ul, 1ul }, + ngraph::CoordinateDiff{ 0, 0 }, + ngraph::CoordinateDiff{ 0, 0 }, + ngraph::Strides{ 1ul, 1ul }); + convolution->set_friendly_name("convolution"); + + ngraph::ResultVector results { + std::make_shared(concat), + std::make_shared(convolution), + std::make_shared(fakeQuantize2) + }; + + function = std::make_shared(results, ngraph::ParameterVector { input1, input2 }, "OutputLayersHandling"); + + // TODO: move to some another place + validate(); +} + +void OutputLayersHandlingInTransformationsForConcat::validate() { + InferenceEngine::Precision netPrecision; + InferenceEngine::SizeVector inputShapes; + std::string targetDevice; + InferenceEngine::details::LayerTransformation::Params params; + std::tie(netPrecision, inputShapes, targetDevice, params) = this->GetParam(); + + const InferenceEngine::CNNNetwork network = transform(params); + + IE_SUPPRESS_DEPRECATED_START + + InferenceEngine::OutputsDataMap outputs = network.getOutputsInfo(); + EXPECT_EQ(3, outputs.size()); + + const auto concatIt = outputs.find("concat"); + EXPECT_TRUE(concatIt != outputs.end()); + const auto fakeQuantize2It = outputs.find("fakeQuantize2"); + EXPECT_TRUE(fakeQuantize2It != outputs.end()); + const auto convolutionIt = outputs.find("convolution"); + EXPECT_TRUE(convolutionIt != outputs.end()); + + if (std::any_of( + params.precisionsOnActivations.begin(), + params.precisionsOnActivations.end(), + [](const float value) { return value == InferenceEngine::Precision::U8; })) { + EXPECT_EQ("ScaleShift", concatIt->second->getCreatorLayer().lock()->type); + EXPECT_EQ("ScaleShift", fakeQuantize2It->second->getCreatorLayer().lock()->type); + EXPECT_EQ("ScaleShift", convolutionIt->second->getCreatorLayer().lock()->type); + } else { + EXPECT_EQ("Concat", concatIt->second->getCreatorLayer().lock()->type); + EXPECT_EQ("FakeQuantize", fakeQuantize2It->second->getCreatorLayer().lock()->type); + EXPECT_EQ("Convolution", convolutionIt->second->getCreatorLayer().lock()->type); + } + + IE_SUPPRESS_DEPRECATED_END +} + +TEST_P(OutputLayersHandlingInTransformationsForConcat, CompareWithRefImpl) { + Run(); +}; + +} // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/shared/src/low_precision_transformations/output_layers_handling_in_transformations_for_concat_multi_channel.cpp b/inference-engine/tests/functional/plugin/shared/src/low_precision_transformations/output_layers_handling_in_transformations_for_concat_multi_channel.cpp new file mode 100644 index 0000000..21166ed --- /dev/null +++ b/inference-engine/tests/functional/plugin/shared/src/low_precision_transformations/output_layers_handling_in_transformations_for_concat_multi_channel.cpp @@ -0,0 +1,152 @@ +// Copyright (C) 2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "low_precision_transformations/output_layers_handling_in_transformations_for_concat_multi_channel.hpp" + +#include +#include +#include +#include + +#include + +#include "common_test_utils/common_utils.hpp" +#include "functional_test_utils/plugin_cache.hpp" +#include "functional_test_utils/layer_test_utils.hpp" +#include "functional_test_utils/blob_utils.hpp" + +#include "ngraph_functions/pass/convert_prc.hpp" +#include "ngraph_functions/builders.hpp" + +namespace LayerTestsDefinitions { + +std::pair outputLayersHandlingInTransformationsForConcatMultiChannelGetInterval(const std::vector& precisions) { + const bool unsignedInterval = std::find(precisions.begin(), precisions.end(), InferenceEngine::Precision::U8) != precisions.end(); + const float low = unsignedInterval ? 0.f : -128.f; + const float hight = unsignedInterval ? 255.f : 127.f; + return std::make_pair(low, hight); +} + +std::string OutputLayersHandlingInTransformationsForConcatMultiChannel::getTestCaseName( + testing::TestParamInfo obj) { + InferenceEngine::Precision netPrecision; + InferenceEngine::SizeVector inputShapes; + std::string targetDevice; + InferenceEngine::details::LayerTransformation::Params params; + std::tie(netPrecision, inputShapes, targetDevice, params) = obj.param; + + std::ostringstream result; + result << netPrecision.name() << "_" << targetDevice << "_" << toString(params); + return result.str(); +} + +InferenceEngine::Blob::Ptr OutputLayersHandlingInTransformationsForConcatMultiChannel::GenerateInput(const InferenceEngine::InputInfo &info) const { + InferenceEngine::SizeVector inputShape; + InferenceEngine::Precision netPrecision; + std::string targetDevice; + InferenceEngine::details::LayerTransformation::Params params; + std::tie(netPrecision, inputShape, targetDevice, params) = this->GetParam(); + + if ((info.name() != "input1") && (info.name() != "input2")) { + THROW_IE_EXCEPTION << "unexpected input name " << info.name(); + } + const float k = (info.name() == "input1") ? 1.f : (info.name() == "input2" ? 2.f : 3.f); + + const auto interval = outputLayersHandlingInTransformationsForConcatMultiChannelGetInterval(params.precisionsOnActivations); + const float low = interval.first / k; + const float hight = interval.second / k; + + InferenceEngine::Blob::Ptr input = FuncTestUtils::createAndFillBlobConsistently(info.getTensorDesc(), hight - low, static_cast(low), 1ul); + const auto buffer = input->buffer().as(); + return input; +} + +/* +* FQ1 FQ2 +* \ / \ +* \ / Output +* Concat +* / \ +* / \ +* Convolution/Power Output +* / +* / +* Output +*/ + +void OutputLayersHandlingInTransformationsForConcatMultiChannel::SetUp() { + InferenceEngine::SizeVector inputShape1; + InferenceEngine::Precision netPrecision; + InferenceEngine::details::LayerTransformation::Params params; + std::tie(netPrecision, inputShape1, targetDevice, params) = this->GetParam(); + auto ngPrecision = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); + + const auto input1 = std::make_shared(ngPrecision, ngraph::Shape(inputShape1)); + input1->set_friendly_name("input1"); + + const auto fakeQuantize1 = ngraph::builder::makeFakeQuantize(input1->output(0), ngPrecision, 256ul, { 1ul }); + fakeQuantize1->set_friendly_name("fakeQuantize1"); + + ASSERT_EQ(4ul, inputShape1.size()) << "unexpected input layout"; + const InferenceEngine::SizeVector inputShape2 = { inputShape1[0], inputShape1[1] * 2ul, inputShape1[2], inputShape1[3] }; + const auto input2 = std::make_shared(ngPrecision, ngraph::Shape(inputShape2)); + input2->set_friendly_name("input2"); + + const auto fakeQuantize2 = ngraph::builder::makeFakeQuantize(input2->output(0), ngPrecision, 256ul, { 1ul }); + fakeQuantize2->set_friendly_name("fakeQuantize2"); + + const std::shared_ptr concat = std::make_shared( + ngraph::OutputVector{ fakeQuantize1->output(0), fakeQuantize2->output(0)}, 1); + concat->set_friendly_name("concat"); + + auto const1 = ngraph::opset1::Constant::create(ngPrecision, ngraph::Shape{ 1, 1, 1, 1 }, { 1 }); + std::shared_ptr convolution = std::make_shared(concat, const1); + convolution->set_friendly_name("convolution"); + + ngraph::ResultVector results { + std::make_shared(concat), + std::make_shared(convolution), + std::make_shared(fakeQuantize2) + }; + + function = std::make_shared(results, ngraph::ParameterVector { input1, input2 }, "OutputLayersHandling"); + + // TODO: move to some another place + validate(); +} + +void OutputLayersHandlingInTransformationsForConcatMultiChannel::validate() { + InferenceEngine::Precision netPrecision; + InferenceEngine::SizeVector inputShapes; + std::string targetDevice; + InferenceEngine::details::LayerTransformation::Params params; + std::tie(netPrecision, inputShapes, targetDevice, params) = this->GetParam(); + + const InferenceEngine::CNNNetwork network = transform(params); + + IE_SUPPRESS_DEPRECATED_START + + InferenceEngine::OutputsDataMap outputs = network.getOutputsInfo(); + EXPECT_EQ(3, outputs.size()); + + const auto concatIt = outputs.find("concat"); + EXPECT_TRUE(concatIt != outputs.end()); + EXPECT_EQ("ScaleShift", concatIt->second->getCreatorLayer().lock()->type); + + const auto fakeQuantize2It = outputs.find("fakeQuantize2"); + EXPECT_TRUE(fakeQuantize2It != outputs.end()); + EXPECT_EQ("ScaleShift", fakeQuantize2It->second->getCreatorLayer().lock()->type); + + const auto convolutionIt = outputs.find("convolution"); + EXPECT_TRUE(convolutionIt != outputs.end()); + EXPECT_EQ("ScaleShift", convolutionIt->second->getCreatorLayer().lock()->type); + + IE_SUPPRESS_DEPRECATED_END +} + +TEST_P(OutputLayersHandlingInTransformationsForConcatMultiChannel, CompareWithRefImpl) { + Run(); +}; + +} // namespace LayerTestsDefinitions -- 2.7.4