[GNA] Fixed accuracy degradation caused by the input quantization restriction (#7258)
* [GNA] Fixed accuracy degradation caused by the input quantization restriction * [GNA] Put scale factor calculation into a separate function
This commit is contained in:
1 parent
fc92eea000
commit
98eaa9359f
3 files changed
+23
-16
No files matched your search
@@ -36,6 +36,17 @@ struct ScaleFactorUpdateResult {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Calculates a scale factor from FakeQuantize statistics according to the formula:
|
||||
* scale factor = max representable value / max absolute input value
|
||||
* @param levels Number of integer quants
|
||||
* @param minValue Minimum value to be quantized
|
||||
* @param maxValue Maximum value to be quantized
|
||||
*/
|
||||
inline float CalculateScaleFactorFromStats(size_t levels, float minValue, float maxValue) {
|
||||
return maxValue == minValue ? 1.0f : (levels - 1) / (maxValue - minValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compares two float values and returns if they are equal
|
||||
* @param p1 First float value
|
||||
@@ -372,7 +383,7 @@ class ScaleFactorPerLayer<InferenceEngine::CNNLayer *> {
|
||||
auto maxOutValue = quantizedParams->_dst_quant.GetMaxValues().front();
|
||||
auto absMax = std::max(std::abs(minOutValue), std::abs(maxOutValue));
|
||||
|
||||
result = (quantizedParams->_dst_quant.GetLevels() - 1) / (maxOutValue - minOutValue);
|
||||
result = CalculateScaleFactorFromStats(quantizedParams->_dst_quant.GetLevels(), minOutValue, maxOutValue);
|
||||
if (std::isinf(result) || fp32eq(absMax, 0.0f)) {
|
||||
result = max_activation_scale_factor;
|
||||
}
|
||||
@@ -452,7 +463,7 @@ class ScaleFactorPerLayer<InferenceEngine::CNNLayer *> {
|
||||
if (CNNNetHasPrevLayer(cnnLayer) && quant->_dst_quant.IsStatsSet() && !quant->_dst_quant.IsScaleSet()) {
|
||||
auto minOutValue = quant->_dst_quant.GetMinValues().front();
|
||||
auto maxOutValue = quant->_dst_quant.GetMaxValues().front();
|
||||
auto scale = (quant->_dst_quant.GetLevels() - 1) / (maxOutValue - minOutValue);
|
||||
auto scale = CalculateScaleFactorFromStats(quant->_dst_quant.GetLevels(), minOutValue, maxOutValue);
|
||||
quant->_dst_quant.SetScale(scale);
|
||||
quant->_src_quant = quant->_dst_quant;
|
||||
}
|
||||
@@ -1068,8 +1079,8 @@ class ScaleFactorPerLayer<InferenceEngine::WeightableLayer*> {
|
||||
quant->_src_quant = quantDataForInputLayer->_dst_quant;
|
||||
if (quant->_weights_quant.IsStatsSet() && !quant->_weights_quant.IsScaleSet()) {
|
||||
auto getScale = [&quant](size_t i) {
|
||||
auto valuesDiff = quant->_weights_quant.GetMaxValues(false)[i] - quant->_weights_quant.GetMinValues(false)[i];
|
||||
return valuesDiff == 0 ? 1.0f : (quant->_weights_quant.GetLevels() - 1) / valuesDiff;
|
||||
return CalculateScaleFactorFromStats(quant->_weights_quant.GetLevels(),
|
||||
quant->_weights_quant.GetMinValues(false)[i], quant->_weights_quant.GetMaxValues(false)[i]);
|
||||
};
|
||||
|
||||
float min_channel_scale = getScale(0);
|
||||
@@ -1222,9 +1233,8 @@ public:
|
||||
quantData->_weights_quant.SetScale(quantParams1->_dst_quant.GetScale());
|
||||
if (quantData->_src_quant.IsStatsSet()) {
|
||||
auto getScale = [&quantParams0](size_t i) {
|
||||
return (quantParams0->_dst_quant.GetLevels() - 1) /
|
||||
(quantParams0->_dst_quant.GetMaxValues(false)[i] -
|
||||
quantParams0->_dst_quant.GetMinValues(false)[i]);
|
||||
return CalculateScaleFactorFromStats(quantParams0->_dst_quant.GetLevels(),
|
||||
quantParams0->_dst_quant.GetMinValues(false)[i], quantParams0->_dst_quant.GetMaxValues(false)[i]);
|
||||
};
|
||||
float min_channel_scale = getScale(0);
|
||||
quantParams0->_dst_quant.SetScale(min_channel_scale);
|
||||
|
||||
@@ -489,13 +489,9 @@ void GNAPlugin::UpdateInputScaleFromNetwork(InferenceEngine::CNNNetwork & networ
|
||||
return (std::abs(p1 - p2) <= 0.00001f * std::min(std::abs(p1), std::abs(p2)));
|
||||
};
|
||||
// GNA input is always quantized to int16, so number of levels can't be greater than max uint16
|
||||
size_t levels = std::min(fqLayer.getLevels(), static_cast<size_t>(std::numeric_limits<uint16_t>::max()));
|
||||
float scaleInput = (levels - 1) / (inputRange.second[0] - inputRange.first[0]);
|
||||
auto minAbsVal = std::min(std::abs(inputRange.second[0]), std::abs(inputRange.first[0]));
|
||||
auto maxAbsVal = std::max(std::abs(inputRange.second[0]), std::abs(inputRange.first[0]));
|
||||
if (fp32eq(minAbsVal, 0.0f) && !fp32eq(maxAbsVal, 0.0f)) {
|
||||
scaleInput = (fqLayer.getLevels() - 1) / (2 * maxAbsVal);
|
||||
}
|
||||
// todo: should be solved in POT (issue 63330)
|
||||
size_t levels = std::min(fqLayer.getLevels(), static_cast<size_t>(std::numeric_limits<uint16_t>::max() + 1));
|
||||
auto scaleInput = frontend::CalculateScaleFactorFromStats(levels, inputRange.first[0], inputRange.second[0]);
|
||||
|
||||
IE_ASSERT(config.inputScaleFactors.size() > inputIdx);
|
||||
IE_ASSERT(inputsDesc->inputScaleFactors.size() > inputIdx);
|
||||
|
||||
@@ -73,8 +73,9 @@ protected:
|
||||
std::tie(netPrecision, targetDevice, configuration, inputShape, inputMinMax, levels) = this->GetParam();
|
||||
auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision);
|
||||
|
||||
auto inputLowNode = ngraph::builder::makeConstant<float>(ngPrc, {1}, { inputMinMax.first });
|
||||
auto inputHighNode = ngraph::builder::makeConstant<float>(ngPrc, {1}, { inputMinMax.second });
|
||||
std::tie(inputDataMin, inputDataMax) = inputMinMax;
|
||||
auto inputLowNode = ngraph::builder::makeConstant<float>(ngPrc, {1}, { inputDataMin });
|
||||
auto inputHighNode = ngraph::builder::makeConstant<float>(ngPrc, {1}, { inputDataMax });
|
||||
|
||||
auto inputVector = ngraph::builder::makeParams(ngPrc, {inputShape});
|
||||
|
||||
|
||||
Reference in new issue
Block a user