fix special FQ node (#14594)
* fix special FQ with zero range in quantized models * fix format & comments * Add test case * remove dot interval test case from smoke_LPT/FakeQuantizeTransformation.CompareFunctions * Remove dot interval gpu test case because Pooling is also folded * handle review comment * fix code style * update docs * remove fold_zero_multiply
This commit is contained in:
1 parent
f0c153858b
commit
fdc2664b24
6 files changed
+94
-15
No files matched your search
@@ -26,6 +26,7 @@ public:
|
||||
bool transform(TransformationContext& context, ngraph::pattern::Matcher &m) override;
|
||||
bool canBeTransformed(const TransformationContext& context, std::shared_ptr<Node> layer) const override;
|
||||
bool isPrecisionPreserved(std::shared_ptr<Node> layer) const noexcept override;
|
||||
bool isConstantOutput(std::shared_ptr<ngraph::Node> op) const;
|
||||
};
|
||||
|
||||
} // namespace low_precision
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include <ngraph/pattern/op/wrap_type.hpp>
|
||||
#include <ngraph/pattern/op/or.hpp>
|
||||
#include "low_precision/network_helper.hpp"
|
||||
#include "itt.hpp"
|
||||
|
||||
@@ -59,8 +60,27 @@ bool FoldFakeQuantizeTransformation::transform(TransformationContext& context, n
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FoldFakeQuantizeTransformation::isConstantOutput(std::shared_ptr<ngraph::Node> node) const {
|
||||
const auto fakeQuantize = ov::as_type_ptr<opset1::FakeQuantize>(node);
|
||||
if (!fakeQuantize) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto outputLow = as_type_ptr<opset1::Constant>(fakeQuantize->get_input_node_shared_ptr(3));
|
||||
const auto outputHigh = as_type_ptr<opset1::Constant>(fakeQuantize->get_input_node_shared_ptr(4));
|
||||
|
||||
if (outputLow == nullptr || outputHigh == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto vecLow = outputLow->cast_vector<float>();
|
||||
const auto vecHigh = outputHigh->cast_vector<float>();
|
||||
|
||||
return vecLow == vecHigh;
|
||||
}
|
||||
|
||||
bool FoldFakeQuantizeTransformation::canBeTransformed(const TransformationContext& context, std::shared_ptr<Node> op) const {
|
||||
return NetworkHelper::isConstantPath(op);
|
||||
return NetworkHelper::isConstantPath(op) || isConstantOutput(op);
|
||||
}
|
||||
|
||||
bool FoldFakeQuantizeTransformation::isPrecisionPreserved(std::shared_ptr<Node> layer) const noexcept {
|
||||
|
||||
@@ -742,6 +742,26 @@ std::shared_ptr<Node> NetworkHelper::foldFakeQuantize(
|
||||
foldConvert(fq->input_value(3), element::f32));
|
||||
}
|
||||
|
||||
// y = FakeQuantize(x, inputLow, inputHigh, outputLow, outputHigh)
|
||||
// given:
|
||||
// outputLow is const
|
||||
// outputHigh is const
|
||||
// outputLow == outputHigh
|
||||
// => y = Broadcast(Convert(outputLow, typeof(y))), ShapeOf(x))
|
||||
if (ov::is_type<opset1::Constant>(fq->get_input_node_shared_ptr(3)) &&
|
||||
ov::is_type<opset1::Constant>(fq->get_input_node_shared_ptr(4))) {
|
||||
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>();
|
||||
|
||||
if (outputLowValues == outputHighValues) {
|
||||
const auto data_shape_node = fold<opset1::ShapeOf>(fq->input_value(0));
|
||||
const auto cvt_output_low = foldConvert(fq->input_value(3), fq->get_output_element_type(0));
|
||||
return fold<opset1::Broadcast>(cvt_output_low, data_shape_node);
|
||||
}
|
||||
}
|
||||
|
||||
auto constant = ov::as_type_ptr<opset1::Constant>(fq->get_input_node_shared_ptr(0));
|
||||
|
||||
if (constant) {
|
||||
|
||||
@@ -183,13 +183,6 @@ const std::vector<FakeQuantizeTransformationTestValues> fakeQuantizeTransformati
|
||||
ngraph::element::i8,
|
||||
{{ngraph::element::f32, {{}, {-128.f}, {0.01f}}}, {ngraph::element::f16, {{}, {-128.f}, {0.01f}}}},
|
||||
true},
|
||||
// dot interval
|
||||
{LayerTransformation::createParamsI8I8(),
|
||||
{256ul, {}, {0.f}, {2.55f}, {2.55f}, {2.55f}},
|
||||
{256ul, {}, {0.f}, {2.55f}, {1.f}, {1.f}},
|
||||
ngraph::element::Type_t::i8,
|
||||
{{ngraph::element::f32, {{}, {}, {2.55f}}}},
|
||||
true},
|
||||
|
||||
// efficientnet-b0: efficientnet-b0/model/blocks_2/depthwise_conv2d/depthwise/fq_input_0, interval: -0.504395 - +0.5
|
||||
// I8 symmetric: max ratio = 0.000907078
|
||||
|
||||
+50
-6
@@ -67,12 +67,23 @@ public:
|
||||
|
||||
const auto params = TestTransformationParams(testValues.params).setUpdatePrecisions(testValues.updatePrecision);
|
||||
|
||||
const auto constant = std::make_shared<ngraph::opset1::Constant>(testValues.actual.constPrecision,
|
||||
testValues.constShape,
|
||||
testValues.actual.constValues);
|
||||
std::shared_ptr<ngraph::Node> dataSource;
|
||||
std::shared_ptr<ngraph::opset1::Parameter> parameter;
|
||||
bool useParameterAsDataSource = (testValues.actual.constValues.size() == 0);
|
||||
|
||||
if (useParameterAsDataSource) {
|
||||
// for data-independent const folding
|
||||
parameter =
|
||||
std::make_shared<ngraph::opset1::Parameter>(testValues.actual.constPrecision, testValues.constShape);
|
||||
dataSource = parameter;
|
||||
} else {
|
||||
dataSource = std::make_shared<ngraph::opset1::Constant>(testValues.actual.constPrecision,
|
||||
testValues.constShape,
|
||||
testValues.actual.constValues);
|
||||
}
|
||||
|
||||
std::shared_ptr<Node> fq =
|
||||
ngraph::builder::subgraph::makeFakeQuantizeTypeRelaxed(constant,
|
||||
ngraph::builder::subgraph::makeFakeQuantizeTypeRelaxed(dataSource,
|
||||
element::f32,
|
||||
testValues.actual.fakeQuantize);
|
||||
ngraph::pass::low_precision::NetworkHelper::setOutDataPrecision(as_type_ptr<opset1::FakeQuantize>(fq),
|
||||
@@ -80,8 +91,10 @@ public:
|
||||
fq = ngraph::pass::low_precision::NetworkHelper::fold_fake_quantize(as_type_ptr<opset1::FakeQuantize>(fq),
|
||||
testValues.roundValues);
|
||||
ngraph::ResultVector results{std::make_shared<ngraph::opset1::Result>(fq)};
|
||||
actualFunction =
|
||||
std::make_shared<ngraph::Function>(results, ngraph::ParameterVector{}, "FoldFakeQuantizeFunction");
|
||||
actualFunction = std::make_shared<ngraph::Function>(
|
||||
results,
|
||||
parameter ? ngraph::ParameterVector{parameter} : ngraph::ParameterVector{},
|
||||
"FoldFakeQuantizeFunction");
|
||||
|
||||
referenceFunction =
|
||||
ngraph::builder::subgraph::FoldFakeQuantizeFunction::getReference(testValues.expected.constPrecision,
|
||||
@@ -189,6 +202,37 @@ const std::vector<FoldFakeQuantizeInTransformationsTestValues> testValues = {
|
||||
ngraph::element::i8},
|
||||
{{-127, -128, -51, -3, 126, -28, -128, -1, -128, -64, -127, 127, -121, -128, -119, -128}, ngraph::element::i8},
|
||||
},
|
||||
{
|
||||
Shape{2, 2, 2, 2},
|
||||
LayerTransformation::createParamsU8I8(),
|
||||
true,
|
||||
false,
|
||||
{{
|
||||
// use empty constValues for data independent const folding
|
||||
},
|
||||
ngraph::element::u8,
|
||||
{256ul, {}, {0.f}, {255.f}, {127.f}, {127.f}},
|
||||
ngraph::element::i8},
|
||||
{{
|
||||
127,
|
||||
127,
|
||||
127,
|
||||
127,
|
||||
127,
|
||||
127,
|
||||
127,
|
||||
127,
|
||||
127,
|
||||
127,
|
||||
127,
|
||||
127,
|
||||
127,
|
||||
127,
|
||||
127,
|
||||
127,
|
||||
},
|
||||
ngraph::element::i8},
|
||||
},
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(smoke_LPT,
|
||||
|
||||
Reference in new issue
Block a user