aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Flynn <jim.flynn@arm.com>2019-02-11 10:30:30 +0000
committerJim Flynn <jim.flynn@arm.com>2019-02-11 11:46:55 +0000
commit3dad5acc5d8eda6fc472b9a255c1d893d4e1f942 (patch)
treef992225a02b8fd3ce87d5ff8aa08a542aab2c790
parente604cde16fc16dc5fea9fc2c1c38ac8e8e2c4a59 (diff)
downloadarmnn-3dad5acc5d8eda6fc472b9a255c1d893d4e1f942.tar.gz
IVGCVSW-2622 Add static quantization of 2DConvolution
Change-Id: If7985a54eba97f7c61413e0804879e4afbf65c4d Signed-off-by: Jim Flynn <jim.flynn@arm.com>
-rw-r--r--src/armnn/QuantizerVisitor.cpp35
-rw-r--r--src/armnn/QuantizerVisitor.hpp11
-rw-r--r--src/armnn/StaticRangeVisitor.cpp21
-rw-r--r--src/armnn/StaticRangeVisitor.hpp9
-rw-r--r--src/armnn/test/QuantizerTest.cpp87
5 files changed, 163 insertions, 0 deletions
diff --git a/src/armnn/QuantizerVisitor.cpp b/src/armnn/QuantizerVisitor.cpp
index 97a8bc1ad2..c5e203ef86 100644
--- a/src/armnn/QuantizerVisitor.cpp
+++ b/src/armnn/QuantizerVisitor.cpp
@@ -153,4 +153,39 @@ void QuantizerVisitor::VisitBatchNormalizationLayer(const IConnectableLayer* lay
SetQuantizedInputConnections(layer, newLayer);
}
+void QuantizerVisitor::VisitConvolution2dLayer(const IConnectableLayer* layer,
+ const Convolution2dDescriptor& convolution2dDescriptor,
+ const ConstTensor& weights,
+ const char* name)
+{
+ std::vector<uint8_t> weightsBacking;
+ ConstTensor qWeights = CreateQuantizedConst(weights, weightsBacking);
+
+ IConnectableLayer* newLayer = m_QuantizedNetwork->AddConvolution2dLayer(convolution2dDescriptor,
+ qWeights,
+ name);
+ RecordLayer(layer, newLayer);
+ SetQuantizedInputConnections(layer, newLayer);
+}
+
+void QuantizerVisitor::VisitConvolution2dLayer(const IConnectableLayer* layer,
+ const Convolution2dDescriptor& convolution2dDescriptor,
+ const ConstTensor& weights,
+ const ConstTensor& biases,
+ const char* name)
+{
+ std::vector<uint8_t> weightsBacking;
+ ConstTensor qWeights = CreateQuantizedConst(weights, weightsBacking);
+
+ std::vector<uint8_t> biasesBacking;
+ ConstTensor qBiases = CreateQuantizedConst(weights, biasesBacking);
+
+ IConnectableLayer* newLayer = m_QuantizedNetwork->AddConvolution2dLayer(convolution2dDescriptor,
+ qWeights,
+ qBiases,
+ name);
+ RecordLayer(layer, newLayer);
+ SetQuantizedInputConnections(layer, newLayer);
+}
+
} //namespace armnn
diff --git a/src/armnn/QuantizerVisitor.hpp b/src/armnn/QuantizerVisitor.hpp
index 53b3edc3fd..fbf9cfa20e 100644
--- a/src/armnn/QuantizerVisitor.hpp
+++ b/src/armnn/QuantizerVisitor.hpp
@@ -52,6 +52,17 @@ public:
const char *name = nullptr) override;
// Extract the quantized network
+ void VisitConvolution2dLayer(const IConnectableLayer* layer,
+ const Convolution2dDescriptor& convolution2dDescriptor,
+ const ConstTensor& weights,
+ const char* name = nullptr) override;
+ void VisitConvolution2dLayer(const IConnectableLayer* layer,
+ const Convolution2dDescriptor& convolution2dDescriptor,
+ const ConstTensor& weights,
+ const ConstTensor& biases,
+ const char* name = nullptr) override;
+
+ /// Extract the quantized network
INetworkPtr RetrieveFinalNetwork() { return std::move(m_QuantizedNetwork); }
private:
diff --git a/src/armnn/StaticRangeVisitor.cpp b/src/armnn/StaticRangeVisitor.cpp
index eac434eecb..fa95938b37 100644
--- a/src/armnn/StaticRangeVisitor.cpp
+++ b/src/armnn/StaticRangeVisitor.cpp
@@ -59,6 +59,27 @@ void StaticRangeVisitor::VisitBatchNormalizationLayer(const IConnectableLayer* l
SetRange(layer, 0, -15.0f, 15.0f);
}
+void StaticRangeVisitor::VisitConvolution2dLayer(const IConnectableLayer* layer,
+ const Convolution2dDescriptor& convolution2dDescriptor,
+ const ConstTensor& weights,
+ const char* name)
+{
+ boost::ignore_unused(convolution2dDescriptor);
+ boost::ignore_unused(weights);
+ boost::ignore_unused(name);
+ SetRange(layer, 0, -15.0f, 15.0f);
+}
+
+void StaticRangeVisitor::VisitConvolution2dLayer(const IConnectableLayer* layer,
+ const Convolution2dDescriptor& convolution2dDescriptor,
+ const ConstTensor& weights,
+ const ConstTensor& biases,
+ const char* name)
+{
+ boost::ignore_unused(biases);
+ VisitConvolution2dLayer(layer, convolution2dDescriptor, weights, name);
+}
+
void StaticRangeVisitor::VisitActivationLayer(const IConnectableLayer* layer,
const ActivationDescriptor& activationDescriptor,
const char* name)
diff --git a/src/armnn/StaticRangeVisitor.hpp b/src/armnn/StaticRangeVisitor.hpp
index 94a6ea0e50..81a0f4aede 100644
--- a/src/armnn/StaticRangeVisitor.hpp
+++ b/src/armnn/StaticRangeVisitor.hpp
@@ -35,6 +35,15 @@ public:
const ConstTensor& beta,
const ConstTensor& gamma,
const char* name = nullptr) override;
+ void VisitConvolution2dLayer(const IConnectableLayer* layer,
+ const Convolution2dDescriptor& convolution2dDescriptor,
+ const ConstTensor& weights,
+ const char* name = nullptr) override;
+ void VisitConvolution2dLayer(const IConnectableLayer* layer,
+ const Convolution2dDescriptor& convolution2dDescriptor,
+ const ConstTensor& weights,
+ const ConstTensor& biases,
+ const char* name = nullptr) override;
void VisitActivationLayer(const IConnectableLayer* layer,
const ActivationDescriptor& activationDescriptor,
const char* name = nullptr) override;
diff --git a/src/armnn/test/QuantizerTest.cpp b/src/armnn/test/QuantizerTest.cpp
index dd90368524..a960c6b772 100644
--- a/src/armnn/test/QuantizerTest.cpp
+++ b/src/armnn/test/QuantizerTest.cpp
@@ -566,5 +566,92 @@ BOOST_AUTO_TEST_CASE(QuantizeFullyConnectedBiasEnabled)
ValidateFullyConnectedLayer(true);
}
+class TestConv2dQuantization : public TestQuantization
+{
+public:
+ virtual void VisitConvolution2dLayer(const IConnectableLayer *layer,
+ const Convolution2dDescriptor &convolution2dDescriptor,
+ const ConstTensor &weights,
+ const char *name = nullptr)
+ {
+ TensorInfo info = layer->GetOutputSlot(0).GetTensorInfo();
+ BOOST_TEST((info.GetDataType() == DataType::QuantisedAsymm8));
+ BOOST_TEST((info.GetQuantizationOffset() == 128));
+
+ // Based off current static value [-15.0f, 15.0f]
+ BOOST_CHECK_CLOSE(info.GetQuantizationScale(), 30.0f / 255.0f, 0.000001f);
+
+ // test weights const
+ BOOST_TEST((weights.GetInfo().GetDataType() == DataType::QuantisedAsymm8));
+ BOOST_CHECK_CLOSE(weights.GetInfo().GetQuantizationScale(), 3.0f / 255.0f, 0.000001f);
+ BOOST_TEST((weights.GetInfo().GetQuantizationOffset() == 85));
+ }
+
+ virtual void VisitConvolution2dLayer(const IConnectableLayer *layer,
+ const Convolution2dDescriptor &convolution2dDescriptor,
+ const ConstTensor &weights,
+ const ConstTensor &biases,
+ const char *name = nullptr)
+ {
+ VisitConvolution2dLayer(layer, convolution2dDescriptor, weights, name);
+
+ // test biases const
+ BOOST_TEST((biases.GetInfo().GetDataType() == DataType::QuantisedAsymm8));
+ BOOST_CHECK_CLOSE(biases.GetInfo().GetQuantizationScale(), 3.0f / 255.0f, 0.000001f);
+ BOOST_TEST((biases.GetInfo().GetQuantizationOffset() == 85));
+ }
+};
+
+void TestQuantizeConvolution2d(bool useBiases)
+{
+ auto network = INetwork::Create();
+
+ TensorShape shape{3U};
+ TensorInfo info(shape, DataType::Float32);
+
+ std::vector<float> weightsData{-1.0f, 1.5f, 2.0f};
+ ConstTensor weights(info, weightsData);
+
+ Convolution2dDescriptor descriptor;
+ descriptor.m_BiasEnabled = useBiases;
+
+ // Add the layers
+ IConnectableLayer* input0 = network->AddInputLayer(0);
+ IConnectableLayer* conv2d;
+ if (useBiases)
+ {
+ std::vector<float> biasesData{-1.0f, 1.5f, 2.0f};
+ ConstTensor biases(info, biasesData);
+ conv2d = network->AddConvolution2dLayer(descriptor, weights, biases);
+ }
+ else
+ {
+ conv2d = network->AddConvolution2dLayer(descriptor, weights);
+ }
+ IConnectableLayer* output = network->AddOutputLayer(1);
+
+ // Establish connections
+ input0->GetOutputSlot(0).Connect(conv2d->GetInputSlot(0));
+ conv2d->GetOutputSlot(0).Connect(output->GetInputSlot(0));
+
+ //Set TensorInfo
+ input0->GetOutputSlot(0).SetTensorInfo(info);
+ conv2d->GetOutputSlot(0).SetTensorInfo(info);
+
+ auto quantizedNetwork = INetworkQuantizer::Create(network.get())->ExportNetwork();
+ TestConv2dQuantization validator;
+ VisitLayersTopologically(quantizedNetwork.get(), validator);
+}
+
+BOOST_AUTO_TEST_CASE(QuantizeConvolution2d)
+{
+ TestQuantizeConvolution2d(false);
+}
+
+BOOST_AUTO_TEST_CASE(QuantizeConvolution2dWithBiases)
+{
+ TestQuantizeConvolution2d(true);
+}
+
BOOST_AUTO_TEST_SUITE_END()
} // namespace armnn