[LPT] FQ reference implementation reused in foldFakeQuantize function (#17096)

* [LPT] reused reference FQ implementation in fold_fake_quantize

* [LPT] Removed legacy parameters

* Added plugin tests with per-channel FQ for GrConv wo reshape

* Apply folding only in the case when FQ data input is constant

* EliminateFQ fix
This commit is contained in:
Vladislav Golubev authored and GitHub committed 2023-04-25 14:08:01 +01:00
1 parent 43a42fa9cd
commit a8278ba4a6
10 files changed
+243 -181

No files matched your search

@@ -199,7 +199,7 @@ public:
static std::shared_ptr<Node> toScalarIfPossible(std::shared_ptr<Node> node);
static std::shared_ptr<Node> fold_fake_quantize(const std::shared_ptr<opset1::FakeQuantize>& fq);
static std::shared_ptr<Node> fold_fake_quantize(const std::shared_ptr<opset1::FakeQuantize>& fq, const bool roundValues, int outChannelsShapeIndex = 0);
static std::shared_ptr<Node> fold_fake_quantize(const std::shared_ptr<opset1::FakeQuantize>& fq, const bool roundValues);
static FakeQuantizeDequantization foldDequantization(const std::shared_ptr<Node>& node,
const size_t branchIndex,
@@ -256,8 +256,7 @@ private:
static std::shared_ptr<Node> foldFakeQuantize(
const std::shared_ptr<opset1::FakeQuantize>& fq,
const bool roundValues,
const bool roundValuesWasSet,
int outChannelsShapeIndex = 0);
const bool roundValuesWasSet);
// 1 - on weights
// 0 - weightable layer was not found
@@ -214,9 +214,8 @@ bool ConvolutionTransformation::transform(TransformationContext &context, ngraph
NetworkHelper::getDequantization(convolution, defaultPrecisions, 1ul) :
NetworkHelper::getDequantization(reshapeFromWeights, defaultPrecisions);
assert(!dequantization.empty());
if (ov::is_type<opset1::FakeQuantize>(dequantization.data.get_node())) {
const std::shared_ptr<opset1::FakeQuantize> fq = ov::as_type_ptr<opset1::FakeQuantize>(dequantization.data.get_node_shared_ptr());
std::shared_ptr<ngraph::Node> newFQ = NetworkHelper::fold_fake_quantize(fq, true);
if (const auto fq = ov::as_type_ptr<opset1::FakeQuantize>(dequantization.data.get_node_shared_ptr())) {
const auto newFQ = NetworkHelper::fold_fake_quantize(fq, true);
NetworkHelper::copyInfo(fq, newFQ);
replace_node(fq, newFQ);
}
@@ -87,10 +87,7 @@ bool ConvolutionBackpropDataTransformation::transform(TransformationContext &con
return false;
}
std::shared_ptr<ngraph::Node> resultConstant = NetworkHelper::fold_fake_quantize(
fqOnWeights,
false,
(constantShape.rank().get_length() < 2) || constantShape[1] != 1ul ? 1ul : 0ul);
auto resultConstant = NetworkHelper::fold_fake_quantize(fqOnWeights, false);
if (reshapeFromWeights != nullptr) {
resultConstant = fold_reshape<opset1::Reshape>(
resultConstant,
@@ -147,16 +144,14 @@ bool ConvolutionBackpropDataTransformation::transform(TransformationContext &con
decomposeFakeQuantizeForWeightsPath(convolutionBackpropData, 1ul);
dequantization = NetworkHelper::getDequantization(convolutionBackpropData, defaultPrecisions, 1ul);
if (ov::is_type<opset1::FakeQuantize>(dequantization.data.get_node())) {
const std::shared_ptr<opset1::FakeQuantize> fq = ov::as_type_ptr<opset1::FakeQuantize>(dequantization.data.get_node_shared_ptr());
std::shared_ptr<ngraph::Node> newFQ = NetworkHelper::fold_fake_quantize(fq, true, 1);
if (const auto fq = ov::as_type_ptr<opset1::FakeQuantize>(dequantization.data.get_node_shared_ptr())) {
const auto newFQ = NetworkHelper::fold_fake_quantize(fq, true);
NetworkHelper::copyInfo(fq, newFQ);
replace_node(fq, newFQ);
}
std::shared_ptr<opset1::Multiply> multiplyFromWeights = ov::as_type_ptr<opset1::Multiply>(
convolutionBackpropData->input_value(1).get_node_shared_ptr());
std::shared_ptr<opset1::Subtract> subtractFromWeights = ov::as_type_ptr<opset1::Subtract>(multiplyFromWeights->get_input_node_shared_ptr(0));
const auto multiplyFromWeights = convolutionBackpropData->get_input_node_shared_ptr(1);
auto subtractFromWeights = ov::as_type_ptr<opset1::Subtract>(multiplyFromWeights->get_input_node_shared_ptr(0));
{
const auto newScalePShape = multiplyFromWeights->get_input_partial_shape(1);
@@ -73,7 +73,7 @@ bool check_interval(const std::shared_ptr<opset1::FakeQuantize>& fq,
fq->get_input_node_shared_ptr(2),
fq->get_input_node_shared_ptr(3),
fq->get_input_node_shared_ptr(4)}));
auto result = NetworkHelper::fold_fake_quantize(tmp_fq, false, 1);
auto result = NetworkHelper::fold_fake_quantize(tmp_fq, false);
const auto result_constant = as_type_ptr<opset1::Constant>(result);
if (result_constant == nullptr) {
return false;
@@ -48,10 +48,7 @@ bool FoldFakeQuantizeTransformation::transform(TransformationContext& context, n
return false;
}
std::shared_ptr<ngraph::Node> resultConstant = NetworkHelper::fold_fake_quantize(
fakeQuantize,
false,
((constantShape.rank().get_length() >= 2) && (constantShape[1] != 1ul)) ? 1ul : 0ul);
const auto resultConstant = NetworkHelper::fold_fake_quantize(fakeQuantize, false);
if (ov::is_type<opset1::Constant>(resultConstant)) {
replace_node(fakeQuantize, resultConstant);
return true;
@@ -24,6 +24,7 @@
#include "low_precision/rt_info/quantization_alignment_attribute.hpp"
#include "ngraph/opsets/opset3.hpp"
#include "ngraph/opsets/opset6.hpp"
#include "transformations/utils/utils.hpp"
namespace ngraph {
namespace pass {
@@ -503,11 +504,9 @@ std::shared_ptr<Node> NetworkHelper::fold_fake_quantize(const std::shared_ptr<op
return foldFakeQuantize(fq, false, false);
}
std::shared_ptr<Node> NetworkHelper::fold_fake_quantize(
const std::shared_ptr<opset1::FakeQuantize>& fq,
const bool roundValues,
const int outChannelsShapeIndex) {
return foldFakeQuantize(fq, roundValues, true, outChannelsShapeIndex);
std::shared_ptr<Node> NetworkHelper::fold_fake_quantize(const std::shared_ptr<opset1::FakeQuantize>& fq,
const bool roundValues) {
return foldFakeQuantize(fq, roundValues, true);
}
FakeQuantizeDequantization NetworkHelper::foldDequantization(const std::shared_ptr<Node>& node,
@@ -711,37 +710,8 @@ size_t NetworkHelper::calculateLevels(
std::shared_ptr<Node> NetworkHelper::foldFakeQuantize(
const std::shared_ptr<opset1::FakeQuantize>& fq,
const bool roundValuesArg,
const bool roundValuesWasSet,
const int outChannelsShapeIndex) {
if (ov::is_type<opset1::Constant>(fq->get_input_node_shared_ptr(0)) &&
ov::is_type<opset1::Constant>(fq->get_input_node_shared_ptr(1)) &&
ov::is_type<opset1::Constant>(fq->get_input_node_shared_ptr(2)) &&
ov::is_type<opset1::Constant>(fq->get_input_node_shared_ptr(3)) &&
ov::is_type<opset1::Constant>(fq->get_input_node_shared_ptr(4)) &&
ov::op::util::constantIsEqualTo(ov::as_type_ptr<opset1::Constant>(fq->get_input_node_shared_ptr(1)), 0.f) &&
ov::op::util::constantIsEqualTo(ov::as_type_ptr<opset1::Constant>(fq->get_input_node_shared_ptr(2)), 254.f) &&
ov::op::util::constantIsEqualTo(ov::as_type_ptr<opset1::Constant>(fq->get_input_node_shared_ptr(3)), -127.f) &&
ov::op::util::constantIsEqualTo(ov::as_type_ptr<opset1::Constant>(fq->get_input_node_shared_ptr(4)), 127.f)) {
const auto type1 = fq->input_value(0).get_element_type();
const auto type2 = fq->input_value(3).get_element_type();
if (type1.is_real() && type2.is_real()) {
return fold<opset1::Add>(fq->input_value(0), fq->input_value(3));
}
if (type1.is_real() && !type2.is_real()) {
return fold<opset1::Add>(
fq->input_value(0),
foldConvert(fq->input_value(3), type1));
}
if (!type1.is_real() && type2.is_real()) {
return fold<opset1::Add>(
foldConvert(fq->input_value(0), type2),
fq->input_value(3));
}
return fold<opset1::Add>(
foldConvert(fq->input_value(0), element::f32),
foldConvert(fq->input_value(3), element::f32));
}
const bool roundValuesWasSet) {
// Corner case
// y = FakeQuantize(x, inputLow, inputHigh, outputLow, outputHigh)
// given:
// outputLow is const
@@ -762,99 +732,20 @@ std::shared_ptr<Node> NetworkHelper::foldFakeQuantize(
}
}
auto constant = ov::as_type_ptr<opset1::Constant>(fq->get_input_node_shared_ptr(0));
if (constant) {
const bool roundValues = roundValuesWasSet ? roundValuesArg : fq->get_output_element_type(0).is_integral();
const auto constPShape = fq->get_output_partial_shape(0);
assert(constPShape.is_static());
const Shape constShape = constPShape.to_shape();
if (constShape.size() > 5lu) {
THROW_IE_LPT_EXCEPTION(*fq) << "Unexpected dimensions count " << constShape.size();
}
if (outChannelsShapeIndex != 0 && outChannelsShapeIndex != 1) {
THROW_IE_LPT_EXCEPTION(*fq) << "Unexpected outChannelsShapeIndex " << outChannelsShapeIndex;
if (ov::is_type<opset1::Constant>(fq->get_input_node_shared_ptr(0))) {
std::shared_ptr<Node> subgraph = std::make_shared<ov::op::TypeRelaxed<opset1::FakeQuantize>>(*fq, element::f32);
const auto& original_et = fq->get_output_element_type(0);
const bool roundValues = roundValuesWasSet ? roundValuesArg : original_et.is_integral();
if (roundValues) {
subgraph = std::make_shared<opset6::Round>(subgraph, opset6::Round::RoundMode::HALF_TO_EVEN);
}
size_t OC;
size_t IC;
// OIDHW or IODHW
if (constShape.size() <= 1) {
OC = constShape.empty() ? 1ul : constShape[0];
IC = 1;
} else {
OC = constShape[outChannelsShapeIndex];
IC = constShape[outChannelsShapeIndex == 0 ? 1 : 0];
OPENVINO_SUPPRESS_DEPRECATED_START
const auto result = ov::get_constant_from_source(subgraph);
OPENVINO_SUPPRESS_DEPRECATED_END
if (result != nullptr) {
return foldConvert(result, original_et);
}
const size_t D = constShape.size() > 4lu ? constShape[constShape.size() - 3] : 1;
const size_t H = constShape.size() > 2lu ? constShape.size() == 3lu ? constShape[2] : constShape[constShape.size() - 2] : 1;
const size_t W = constShape.size() > 3lu ? constShape[constShape.size() - 1] : 1;
const auto inputLowValues = ov::as_type_ptr<opset1::Constant>(fq->get_input_node_shared_ptr(1))->cast_vector<float>();
const auto inputHighValues = ov::as_type_ptr<opset1::Constant>(fq->get_input_node_shared_ptr(2))->cast_vector<float>();
const auto outputLowValues = ov::as_type_ptr<opset1::Constant>(fq->get_input_node_shared_ptr(3))->cast_vector<float>();
const auto outputHighValues = ov::as_type_ptr<opset1::Constant>(fq->get_input_node_shared_ptr(4))->cast_vector<float>();
const size_t inputLowSize = inputLowValues.size();
const size_t inputHighSize = inputHighValues.size();
const size_t outputLowSize = outputLowValues.size();
const size_t outputHighSize = outputHighValues.size();
const bool isInputLowBroadcasted = inputLowSize != OC;
if ((inputLowSize != 1) && (inputLowSize != OC)) {
THROW_IE_LPT_EXCEPTION(*fq) << "Unexpected input low values count " << inputLowSize << " for " << OC << " channels";
}
const bool isInputHighBroadcasted = inputHighSize != OC;
if ((inputHighSize != 1) && (inputHighSize != OC)) {
THROW_IE_LPT_EXCEPTION(*fq) << "Unexpected input high values count " << inputHighSize << " for " << OC << " channels";
}
const bool isOutputLowBroadcasted = outputLowSize != OC;
if ((outputLowSize != 1) && (outputLowSize != OC)) {
THROW_IE_LPT_EXCEPTION(*fq) << "Unexpected output low values count " << outputLowSize << " for " << OC << " channels";
}
const bool isOutputHighBroadcasted = outputHighSize != OC;
if ((outputHighSize != 1) && (outputHighSize != OC)) {
THROW_IE_LPT_EXCEPTION(*fq) << "Unexpected output high values count " << outputHighSize << " for " << OC << " channels";
}
auto levels_1 = fq->get_levels() - 1.f;
const size_t DHW = D * H * W;
const size_t IDHW = outChannelsShapeIndex == 0 ? IC * D * H * W : OC * D * H * W;
const auto values = constant->cast_vector<float>();
std::vector<float> quantizedValues(OC * IC * D * H * W);
for (size_t oc = 0; oc < OC; ++oc) {
const float inputLow = inputLowValues[isInputLowBroadcasted ? 0 : oc];
const float inputHigh = inputHighValues[isInputHighBroadcasted ? 0 : oc];
const float outputLow = outputLowValues[isOutputLowBroadcasted ? 0 : oc];
const float outputHigh = outputHighValues[isOutputHighBroadcasted ? 0 : oc];
for (size_t ic = 0; ic < IC; ++ic) {
for (size_t iidx = 0; iidx < DHW; ++iidx) {
size_t idx;
if (outChannelsShapeIndex == 0) {
idx = oc * IDHW + ic * DHW + iidx;
} else {
idx = ic * IDHW + oc * DHW + iidx;
}
if (values[idx] <= inputLow) {
quantizedValues[idx] = roundValues ? std::roundf(outputLow) : outputLow;
} else if (values[idx] > inputHigh) {
quantizedValues[idx] = roundValues ? std::roundf(outputHigh) : outputHigh;
} else {
const float value = std::roundf((values[idx] - inputLow) / (inputHigh - inputLow) * levels_1) /
levels_1 * (outputHigh - outputLow) + outputLow;
quantizedValues[idx] = roundValues ? std::roundf(value) : value;
}
}
}
}
return std::make_shared<opset1::Constant>(fq->get_output_element_type(0), constShape, quantizedValues);
}
return fq;
@@ -1086,8 +977,7 @@ std::tuple<std::shared_ptr<Node>, std::shared_ptr<Node>> NetworkHelper::decompos
newMax->output(0),
fq->get_levels(),
fq->get_auto_broadcast()),
true,
static_cast<int>(outChannelsShapeIndex));
true);
NetworkHelper::copyInfo(fq, newFQ);
std::shared_ptr<ngraph::Node> convert2;
@@ -133,7 +133,7 @@ const std::vector<FoldFakeQuantizeInTransformationsTestValues> testValues = {
{255ul, {}, {0.f}, {254.f}, {-127.f}, {127.f}},
ngraph::element::i8,
},
{{-126, -127, -50, -2, 127, -27, -127, 0, -127, -63, -126, 127, -120, -127, -118, -127}, ngraph::element::f32},
{{-126, -127, -50, -2, 127, -27, -127, 0, -127, -63, -126, 127, -120, -127, -118, -127}, ngraph::element::i8},
},
{
Shape{2, 2, 2, 2},
@@ -70,18 +70,18 @@ const std::vector<LayerTestsDefinitions::GroupConvolutionTransformationParam> pa
},
{ 255ul, ngraph::Shape { 1, 1, 1, 1 }, { 0.f }, { 254.f }, { -127.f }, { 127.f } },
true,
"",
""
"Convolution",
"U8"
},
// group convolution, per-channel weights quantization
// group convolution without reshape, tensor quantization
{
3ul,
-1,
{ 256ul, ngraph::Shape { 1, 1, 1, 1 }, { 0.f }, { 25.5f }, { 0.f }, { 25.5f } },
{ 255ul, ngraph::Shape { 1, 1, 1, 1 }, { 0.f }, { 254.f }, { -127.f }, { 127.f } },
false,
"",
""
"Convolution",
"U8"
}
};
@@ -95,6 +95,110 @@ INSTANTIATE_TEST_SUITE_P(smoke_LPT, GroupConvolutionTransformation,
::testing::ValuesIn(addPrecisionPreserved)),
GroupConvolutionTransformation::getTestCaseName);
namespace test_values_4d {
const std::vector<std::pair<ngraph::PartialShape, ngraph::Shape>> inputShapes = {
{{ 1, 6, 24, 24 }, { 1, 24, 18, 18 }},
};
const std::vector<LayerTestsDefinitions::GroupConvolutionTransformationParam> params = {
// group convolution without reshape, per channel quantization
{
3ul,
-1,
{ 256ul, ngraph::Shape { 1, 1, 1, 1 }, { 0.f }, { 25.5f }, { 0.f }, { 25.5f } },
{ 255ul, ngraph::Shape { 3, 8, 1, 1, 1 }, { -127.f }, { 127.f }, { -127.f }, { 127.f } },
false,
"Convolution",
"U8"
},
// group convolution without reshape, per channel quantization with different values
{
3ul,
-1,
{ 256ul, ngraph::Shape { 1, 1, 1, 1 }, { 0.f }, { 25.5f }, { 0.f }, { 25.5f } },
{ 255ul, ngraph::Shape { 3, 8, 1, 1, 1 },
{-127.f, -12.7f, -1.27f, -127.f, -12.7f, -1.27f, -127.f, -12.7f,
-127.f, -12.7f, -1.27f, -127.f, -12.7f, -1.27f, -127.f, -12.7f,
-127.f, -12.7f, -1.27f, -127.f, -12.7f, -1.27f, -127.f, -12.7f},
{127.f, 12.7f, 1.27f, 127.f, 12.7f, 1.27f, 127.f, 12.7f,
127.f, 12.7f, 1.27f, 127.f, 12.7f, 1.27f, 127.f, 12.7f,
127.f, 12.7f, 1.27f, 127.f, 12.7f, 1.27f, 127.f, 12.7f},
{-127.f, -12.7f, -1.27f, -127.f, -12.7f, -1.27f, -127.f, -12.7f,
-127.f, -12.7f, -1.27f, -127.f, -12.7f, -1.27f, -127.f, -12.7f,
-127.f, -12.7f, -1.27f, -127.f, -12.7f, -1.27f, -127.f, -12.7f},
{127.f, 12.7f, 1.27f, 127.f, 12.7f, 1.27f, 127.f, 12.7f,
127.f, 12.7f, 1.27f, 127.f, 12.7f, 1.27f, 127.f, 12.7f,
127.f, 12.7f, 1.27f, 127.f, 12.7f, 1.27f, 127.f, 12.7f}
},
false,
"Convolution",
"U8"
},
};
INSTANTIATE_TEST_SUITE_P(smoke_LPT, GroupConvolutionTransformation,
::testing::Combine(
::testing::ValuesIn(netPrecisions),
::testing::Values(CommonTestUtils::DEVICE_CPU),
::testing::ValuesIn(trasformationParamValues),
::testing::ValuesIn(inputShapes),
::testing::ValuesIn(params),
::testing::Values(false)),
GroupConvolutionTransformation::getTestCaseName);
} // namespace test_values_4d
namespace test_values_3d {
const std::vector<std::pair<ngraph::PartialShape, ngraph::Shape>> inputShapes = {
{{ 1, 6, 24 }, { 1, 24, 18 }},
};
const std::vector<LayerTestsDefinitions::GroupConvolutionTransformationParam> params = {
// group convolution without reshape, per channel quantization
{
3ul,
-1,
{ 256ul, ngraph::Shape { 1, 1, 1 }, { 0.f }, { 25.5f }, { 0.f }, { 25.5f } },
{ 255ul, ngraph::Shape { 3, 8, 1, 1 }, { -127.f }, { 127.f }, { -127.f }, { 127.f } },
false,
"Convolution",
"U8"
},
// group convolution without reshape, per channel quantization with different values
{
3ul,
-1,
{ 256ul, ngraph::Shape { 1, 1, 1 }, { 0.f }, { 25.5f }, { 0.f }, { 25.5f } },
{ 255ul, ngraph::Shape { 3, 8, 1, 1 },
{-127.f, -12.7f, -1.27f, -127.f, -12.7f, -1.27f, -127.f, -12.7f,
-127.f, -12.7f, -1.27f, -127.f, -12.7f, -1.27f, -127.f, -12.7f,
-127.f, -12.7f, -1.27f, -127.f, -12.7f, -1.27f, -127.f, -12.7f},
{127.f, 12.7f, 1.27f, 127.f, 12.7f, 1.27f, 127.f, 12.7f,
127.f, 12.7f, 1.27f, 127.f, 12.7f, 1.27f, 127.f, 12.7f,
127.f, 12.7f, 1.27f, 127.f, 12.7f, 1.27f, 127.f, 12.7f},
{-127.f, -12.7f, -1.27f, -127.f, -12.7f, -1.27f, -127.f, -12.7f,
-127.f, -12.7f, -1.27f, -127.f, -12.7f, -1.27f, -127.f, -12.7f,
-127.f, -12.7f, -1.27f, -127.f, -12.7f, -1.27f, -127.f, -12.7f},
{127.f, 12.7f, 1.27f, 127.f, 12.7f, 1.27f, 127.f, 12.7f,
127.f, 12.7f, 1.27f, 127.f, 12.7f, 1.27f, 127.f, 12.7f,
127.f, 12.7f, 1.27f, 127.f, 12.7f, 1.27f, 127.f, 12.7f}
},
false,
"Convolution",
"U8"
},
};
INSTANTIATE_TEST_SUITE_P(smoke_LPT, GroupConvolutionTransformation,
::testing::Combine(
::testing::ValuesIn(netPrecisions),
::testing::Values(CommonTestUtils::DEVICE_CPU),
::testing::ValuesIn(trasformationParamValues),
::testing::ValuesIn(inputShapes),
::testing::ValuesIn(params),
::testing::Values(false)),
GroupConvolutionTransformation::getTestCaseName);
} // namespace test_values_3d
namespace depthwise {
const std::vector<std::pair<ngraph::PartialShape, ngraph::Shape>> inputShapes = {
{{ 1, 6, 24, 24 }, { 1, 6, 18, 18 }},
@@ -158,5 +262,4 @@ INSTANTIATE_TEST_SUITE_P(smoke_LPT, GroupConvolutionTransformation,
::testing::ValuesIn(addPrecisionPreserved)),
GroupConvolutionTransformation::getTestCaseName);
} // namespace depthwise
} // namespace
@@ -93,6 +93,110 @@ INSTANTIATE_TEST_SUITE_P(smoke_LPT, GroupConvolutionTransformation,
::testing::ValuesIn(addPrecisionPreserved)),
GroupConvolutionTransformation::getTestCaseName);
namespace test_values_4d {
const std::vector<std::pair<ngraph::PartialShape, ngraph::Shape>> inputShapes = {
{{ 1, 6, 24, 24 }, { 1, 24, 18, 18 }},
};
const std::vector<LayerTestsDefinitions::GroupConvolutionTransformationParam> params = {
// group convolution without reshape, per channel quantization
{
3ul,
-1,
{ 256ul, ngraph::Shape { 1, 1, 1, 1 }, { 0.f }, { 25.5f }, { 0.f }, { 25.5f } },
{ 255ul, ngraph::Shape { 3, 8, 1, 1, 1 }, { -127.f }, { 127.f }, { -127.f }, { 127.f } },
false,
"Convolution",
"U8"
},
// group convolution without reshape, per channel quantization with different values
{
3ul,
-1,
{ 256ul, ngraph::Shape { 1, 1, 1, 1 }, { 0.f }, { 25.5f }, { 0.f }, { 25.5f } },
{ 255ul, ngraph::Shape { 3, 8, 1, 1, 1 },
{-127.f, -12.7f, -1.27f, -127.f, -12.7f, -1.27f, -127.f, -12.7f,
-127.f, -12.7f, -1.27f, -127.f, -12.7f, -1.27f, -127.f, -12.7f,
-127.f, -12.7f, -1.27f, -127.f, -12.7f, -1.27f, -127.f, -12.7f},
{127.f, 12.7f, 1.27f, 127.f, 12.7f, 1.27f, 127.f, 12.7f,
127.f, 12.7f, 1.27f, 127.f, 12.7f, 1.27f, 127.f, 12.7f,
127.f, 12.7f, 1.27f, 127.f, 12.7f, 1.27f, 127.f, 12.7f},
{-127.f, -12.7f, -1.27f, -127.f, -12.7f, -1.27f, -127.f, -12.7f,
-127.f, -12.7f, -1.27f, -127.f, -12.7f, -1.27f, -127.f, -12.7f,
-127.f, -12.7f, -1.27f, -127.f, -12.7f, -1.27f, -127.f, -12.7f},
{127.f, 12.7f, 1.27f, 127.f, 12.7f, 1.27f, 127.f, 12.7f,
127.f, 12.7f, 1.27f, 127.f, 12.7f, 1.27f, 127.f, 12.7f,
127.f, 12.7f, 1.27f, 127.f, 12.7f, 1.27f, 127.f, 12.7f}
},
false,
"Convolution",
"U8"
},
};
INSTANTIATE_TEST_SUITE_P(smoke_LPT, GroupConvolutionTransformation,
::testing::Combine(
::testing::ValuesIn(netPrecisions),
::testing::Values(CommonTestUtils::DEVICE_CPU),
::testing::ValuesIn(trasformationParamValues),
::testing::ValuesIn(inputShapes),
::testing::ValuesIn(params),
::testing::Values(false)),
GroupConvolutionTransformation::getTestCaseName);
} // namespace test_values_4d
namespace test_values_3d {
const std::vector<std::pair<ngraph::PartialShape, ngraph::Shape>> inputShapes = {
{{ 1, 6, 24 }, { 1, 24, 18 }},
};
const std::vector<LayerTestsDefinitions::GroupConvolutionTransformationParam> params = {
// group convolution without reshape, per channel quantization
{
3ul,
-1,
{ 256ul, ngraph::Shape { 1, 1, 1 }, { 0.f }, { 25.5f }, { 0.f }, { 25.5f } },
{ 255ul, ngraph::Shape { 3, 8, 1, 1 }, { -127.f }, { 127.f }, { -127.f }, { 127.f } },
false,
"Convolution",
"U8"
},
// group convolution without reshape, per channel quantization with different values
{
3ul,
-1,
{ 256ul, ngraph::Shape { 1, 1, 1 }, { 0.f }, { 25.5f }, { 0.f }, { 25.5f } },
{ 255ul, ngraph::Shape { 3, 8, 1, 1 },
{-127.f, -12.7f, -1.27f, -127.f, -12.7f, -1.27f, -127.f, -12.7f,
-127.f, -12.7f, -1.27f, -127.f, -12.7f, -1.27f, -127.f, -12.7f,
-127.f, -12.7f, -1.27f, -127.f, -12.7f, -1.27f, -127.f, -12.7f},
{127.f, 12.7f, 1.27f, 127.f, 12.7f, 1.27f, 127.f, 12.7f,
127.f, 12.7f, 1.27f, 127.f, 12.7f, 1.27f, 127.f, 12.7f,
127.f, 12.7f, 1.27f, 127.f, 12.7f, 1.27f, 127.f, 12.7f},
{-127.f, -12.7f, -1.27f, -127.f, -12.7f, -1.27f, -127.f, -12.7f,
-127.f, -12.7f, -1.27f, -127.f, -12.7f, -1.27f, -127.f, -12.7f,
-127.f, -12.7f, -1.27f, -127.f, -12.7f, -1.27f, -127.f, -12.7f},
{127.f, 12.7f, 1.27f, 127.f, 12.7f, 1.27f, 127.f, 12.7f,
127.f, 12.7f, 1.27f, 127.f, 12.7f, 1.27f, 127.f, 12.7f,
127.f, 12.7f, 1.27f, 127.f, 12.7f, 1.27f, 127.f, 12.7f}
},
false,
"Convolution",
"U8"
},
};
INSTANTIATE_TEST_SUITE_P(smoke_LPT, GroupConvolutionTransformation,
::testing::Combine(
::testing::ValuesIn(netPrecisions),
::testing::Values(CommonTestUtils::DEVICE_CPU),
::testing::ValuesIn(trasformationParamValues),
::testing::ValuesIn(inputShapes),
::testing::ValuesIn(params),
::testing::Values(false)),
GroupConvolutionTransformation::getTestCaseName);
} // namespace test_values_3d
namespace depthwise {
const std::vector<std::pair<ngraph::PartialShape, ngraph::Shape>> inputShapes = {
{{ 1, 6, 24, 24 }, { 1, 6, 18, 18 }}
@@ -19,29 +19,6 @@
#include "lpt_ngraph_functions/group_convolution_function.hpp"
namespace LayerTestsDefinitions {
namespace {
std::shared_ptr<ov::Model> replaceFQConstantsOnScalars(const std::shared_ptr<ov::Model>& m) {
auto model = ngraph::clone_function(*m);
for (const auto& op : model->get_ordered_ops()) {
if (!ov::is_type<ov::opset10::FakeQuantize>(op))
continue;
for (size_t i = 1; i < op->get_input_size(); ++i) {
if (auto constant = ov::as_type_ptr<ov::opset10::Constant>(op->get_input_node_shared_ptr(i))) {
const auto& shape = constant->get_shape();
if (ov::shape_size(shape) > 1) {
const auto values = constant->cast_vector<float>();
if (std::all_of(values.begin(), values.end(), [&](float x) { return x == values[0]; })) {
const auto scalar_constant = ov::opset10::Constant::create(constant->get_element_type(), {}, &values[0]);
ov::replace_node(constant, scalar_constant);
}
}
}
}
}
return model;
}
} // namespace
std::string GroupConvolutionTransformation::getTestCaseName(const testing::TestParamInfo<GroupConvolutionTransformationParams>& obj) {
ngraph::element::Type netPrecision;
std::string targetDevice;
@@ -89,8 +66,6 @@ void GroupConvolutionTransformation::SetUp() {
param.fakeQuantizeOnWeights,
param.addReshape,
addPrecisionPreserved);
// WA for issue #107400
functionRefs = replaceFQConstantsOnScalars(function);
}
void GroupConvolutionTransformation::Run() {