[LPT] Check on isQuantized fixed (#14151)

This commit is contained in:
Vladislav Golubev authored and GitHub committed 2022-11-28 13:58:42 +04:00
1 parent 4b51cf5ba0
commit f06c44115f
5 files changed
+108 -27

No files matched your search

@@ -208,7 +208,7 @@ std::tuple<std::shared_ptr<Node>, std::shared_ptr<Node>> decomposeFakeQuantize(
}
//TODO: pass min levels as a parameter?
if (levels < 2ul) {
if (levels <= 2ul) {
return std::make_tuple(nullptr, nullptr);
}
@@ -253,8 +253,27 @@ bool WeightableLayerTransformation::isQuantizedStatic(const std::shared_ptr<cons
return false;
}
const size_t outChannelsShapeIndex = ov::is_type<opset1::ConvolutionBackpropData>(layer) ? 1ul : 0ul;
auto checkConstShape = [&](const std::shared_ptr<ngraph::opset1::Constant> node) {
const auto subConstShape = node->get_shape();
if (shape_size(subConstShape) > 1ul && shape_size(subConstShape) != subConstShape[outChannelsShapeIndex])
return false;
else
return true;
};
if (dequantizationOnWeights.subtract && !checkConstShape(dequantizationOnWeights.subtractConstant) ||
dequantizationOnWeights.multiply && !checkConstShape(dequantizationOnWeights.multiplyConstant)) {
return false;
}
auto deqData = dequantizationOnWeights.data.get_node_shared_ptr();
// Quantize/Dequantize case
if (ov::is_type<ngraph::opset1::Convert>(deqData)) {
deqData = deqData->get_input_node_shared_ptr(0);
}
// TODO: LPT: is it possible to share with canBeTransformed?
if (ov::is_type<opset1::Constant>(dequantizationOnWeights.data.get_node())) {
if (ov::is_type<opset1::Constant>(deqData)) {
const ngraph::element::Type weightsDataPrecision = dequantizationOnWeights.data.get_element_type();
if (!DataPrecision::isSupported(weightsDataPrecision)) {
return false;
@@ -266,23 +285,15 @@ bool WeightableLayerTransformation::isQuantizedStatic(const std::shared_ptr<cons
return false;
}
}
const size_t outChannelsShapeIndex = ov::is_type<opset1::ConvolutionBackpropData>(layer) ? 1ul : 0ul;
if (dequantizationOnWeights.subtract) {
const auto subConstShape = dequantizationOnWeights.subtractConstant->get_shape();
if (shape_size(subConstShape) > 1ul && shape_size(subConstShape) != subConstShape[outChannelsShapeIndex]) {
return false;
}
}
if (dequantizationOnWeights.multiply) {
const auto mulConstShape = dequantizationOnWeights.multiplyConstant->get_shape();
if (shape_size(mulConstShape) > 1ul && shape_size(mulConstShape) != mulConstShape[outChannelsShapeIndex]) {
return false;
}
}
return true;
} else if (ov::is_type<opset1::FakeQuantize>(dequantizationOnWeights.data.get_node())) {
} else if (auto fq = ov::as_type_ptr<opset1::FakeQuantize>(deqData)) {
for (size_t i = 1; i < fq->get_input_size(); ++i) {
if (auto constant = ov::as_type_ptr<ngraph::opset1::Constant>(fq->get_input_node_shared_ptr(i))) {
if (!checkConstShape(constant)) {
return false;
}
}
}
return true;
}
@@ -23,6 +23,7 @@ namespace {
using namespace testing;
using namespace ngraph;
using namespace ngraph::pass;
using namespace ngraph::builder::subgraph;
using const_node_ptr = const std::shared_ptr<const ngraph::Node>;
using callback_function_type = std::function<bool(const_node_ptr&)>;
@@ -43,6 +44,19 @@ public:
callback_function_type callback;
Actual() = default;
Actual(
const ngraph::element::Type& precisionBeforeDequantization,
const DequantizationOperations& dequantizationOnActivations,
const FakeQuantizeOnWeights& fakeQuantizeOnWeights,
const DequantizationOperations& dequantizationOnWeights,
const std::shared_ptr<ngraph::opset1::Constant>& weights,
const callback_function_type& callback = empty_callback) :
precisionBeforeDequantization(precisionBeforeDequantization),
dequantizationOnActivations(dequantizationOnActivations),
fakeQuantizeOnWeights(fakeQuantizeOnWeights),
dequantizationOnWeights(dequantizationOnWeights),
weights(weights),
callback(callback) {}
Actual(
const ngraph::element::Type& precisionBeforeDequantization,
const ngraph::builder::subgraph::DequantizationOperations& dequantizationOnActivations,
@@ -55,16 +69,16 @@ public:
weights(weights),
callback(callback) {}
Actual(
const ngraph::element::Type& precisionBeforeDequantization,
const ngraph::builder::subgraph::DequantizationOperations& dequantizationOnActivations,
const builder::subgraph::DequantizationOperations& dequantizationOnWeights,
const ngraph::element::Type& precisionBeforeDequantization,
const ngraph::builder::subgraph::DequantizationOperations& dequantizationOnActivations,
const builder::subgraph::DequantizationOperations& dequantizationOnWeights,
const std::shared_ptr<ngraph::opset1::Constant>& weights,
const callback_function_type& callback = empty_callback) :
precisionBeforeDequantization(precisionBeforeDequantization),
dequantizationOnActivations(dequantizationOnActivations),
dequantizationOnWeights(dequantizationOnWeights),
weights(weights),
callback(callback) {}
precisionBeforeDequantization(precisionBeforeDequantization),
dequantizationOnActivations(dequantizationOnActivations),
dequantizationOnWeights(dequantizationOnWeights),
weights(weights),
callback(callback) {}
};
class Expected {
@@ -113,7 +127,14 @@ public:
element::i64,
Shape{ outputShape.size() },
Shape{ inputChannels, outputShape[1], 1, 1 }));
if (!testValues.actual.fakeQuantizeOnWeights.empty()) {
if (!testValues.actual.fakeQuantizeOnWeights.empty() && !testValues.actual.dequantizationOnWeights.empty()) {
actualWeights = ConvolutionBackpropDataFunction::getWeights(
outputShape,
netPrecision,
testValues.actual.fakeQuantizeOnWeights,
testValues.actual.dequantizationOnWeights,
ov::as_type_ptr<opset1::Constant>(actualWeights));
} else if (!testValues.actual.fakeQuantizeOnWeights.empty()) {
actualWeights = ngraph::builder::subgraph::ConvolutionBackpropDataFunction::getWeights(
outputShape,
netPrecision,
@@ -152,6 +173,7 @@ public:
outputShape,
netPrecision,
testValues.actual.fakeQuantizeOnWeights,
testValues.actual.dequantizationOnWeights,
ov::as_type_ptr<opset1::Constant>(refWeights));
} else {
refWeights = ngraph::builder::subgraph::ConvolutionBackpropDataFunction::getWeights(
@@ -451,6 +473,27 @@ const std::vector<ConvolutionBackpropDataTransformationTestValues> testValues =
true
}
},
// FQ + DQ version
{
LayerTransformation::createParamsU8I8(),
// ActualValues
{
ngraph::element::u8,
{{ngraph::element::f32}, {}, { 0.02f }},
{ 255ul, Shape({ 8, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f }, ngraph::element::i8 },
{{ngraph::element::f32}, {}, { {0.01f}, ngraph::element::f32, {8, 1, 1, 1} }},
op::Constant::create(ngraph::element::i8, ngraph::Shape{}, std::vector<float>{ 2.f })
},
// ExpectedValues
{
ngraph::element::u8,
{{ngraph::element::f32}, {}, { 0.02f }},
{},
{},
op::Constant::create(ngraph::element::i8, ngraph::Shape{}, std::vector<float>{ 2.f }),
false
}
},
// QDq version
{
LayerTransformation::createParamsU8I8(),
@@ -27,6 +27,12 @@ public:
const element::Type& netPrecision,
const builder::subgraph::FakeQuantizeOnWeights& fqOnWeights,
const std::shared_ptr<opset1::Constant>& value = nullptr);
static std::shared_ptr<Node> getWeights(
const Shape& shape,
const element::Type& netPrecision,
const builder::subgraph::FakeQuantizeOnWeights& fqOnWeights,
const builder::subgraph::DequantizationOperations& dequantizationOnWeights,
const std::shared_ptr<opset1::Constant>& value = nullptr);
static std::shared_ptr<Function> get(
const element::Type netPrecision,
const PartialShape& inputShape,
@@ -88,6 +88,27 @@ std::shared_ptr<Node> ConvolutionBackpropDataFunction::getWeights(
return dq;
}
std::shared_ptr<Node> ConvolutionBackpropDataFunction::getWeights(
const Shape& shape,
const element::Type& netPrecision,
const builder::subgraph::FakeQuantizeOnWeights& fqOnWeights,
const builder::subgraph::DequantizationOperations& dequantizationOnWeights,
const std::shared_ptr<opset1::Constant>& value) {
const auto weights =
value != nullptr
? value
: std::make_shared<opset1::Constant>(element::i8, shape, std::vector<float>(shape_size(shape), 1));
const auto convert = std::make_shared<opset1::Convert>(weights, netPrecision);
OutputVector convertedOutput(1);
convert->constant_fold(convertedOutput, convert->input_values());
const auto convertedWeights = convertedOutput[0].get_node_shared_ptr();
const auto fq = makeFakeQuantizeTypeRelaxed(convertedWeights, netPrecision, fqOnWeights);
auto dequantizationStructure = dequantizationOnWeights;
dequantizationStructure.setPrecision(netPrecision);
return makeDequantization(fq, dequantizationStructure);
}
std::shared_ptr<Function> ConvolutionBackpropDataFunction::getOriginal(
const element::Type precision,
const element::Type netPrecision,