ArmNN
 20.11
QuantizerTest.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include "../Graph.hpp"
7 #include "../Network.hpp"
8 #include "../NetworkQuantizerUtils.hpp"
9 #include "../OverrideInputRangeVisitor.hpp"
10 #include "../RangeTracker.hpp"
11 #include "../../armnnQuantizer/CommandLineProcessor.hpp"
12 
13 #include <armnn/INetwork.hpp>
15 #include <armnn/Tensor.hpp>
16 #include <armnn/Types.hpp>
20 #include <QuantizeHelper.hpp>
21 
22 #include <boost/test/unit_test.hpp>
23 
24 #include <unordered_map>
25 
26 namespace armnn
27 {
28 using MinMaxRange = std::pair<float, float>;
29 using MinMaxRanges = std::vector<MinMaxRange>;
30 using MinMaxRangeMap = std::unordered_map<LayerGuid, MinMaxRanges>;
31 
32 const float g_AsymmU8QuantizationBase = 255.0f;
33 // Coinciding with calcution which for AsymmS8 which calculates scale on an unsigned basis
34 const float g_AsymmS8QuantizationBase = 255.0f;
35 const float g_SymmS8QuantizationBase = 127.0f;
36 const float g_SymmS16QuantizationBase = 32767.0f;
37 const float g_TestTolerance = 0.000001f;
38 
39 BOOST_AUTO_TEST_SUITE(Quantizer)
40 
41 class TestQuantization : public LayerVisitorBase<VisitorThrowingPolicy>
42 {
43 public:
44  TestQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
46  , m_InputShape(inputShape)
47  , m_OutputShape(outputShape)
48  , m_QuantizerOptions(QuantizerOptions()) {}
49 
50  TestQuantization(const QuantizerOptions& options, const TensorShape& inputShape, const TensorShape& outputShape)
52  , m_InputShape(inputShape)
53  , m_OutputShape(outputShape)
54  , m_QuantizerOptions(options) {}
55 
56  void VisitInputLayer(const IConnectableLayer* layer,
57  LayerBindingId id,
58  const char* name = nullptr) override
59  {
60  IgnoreUnused(id, name);
61  const TensorInfo& info = layer->GetOutputSlot(0).GetTensorInfo();
62  BOOST_TEST(m_InputShape == info.GetShape());
63  // Based off current default [-15.0f, 15.0f]
64  TestQuantizationParams(info, {30.0f / g_AsymmU8QuantizationBase, 128},
65  {30.0f / g_AsymmS8QuantizationBase, 0},
66  {15.0f / g_SymmS8QuantizationBase , 0},
67  {15.0f / g_SymmS16QuantizationBase, 0});
68  }
69 
70  void VisitOutputLayer(const IConnectableLayer* layer,
71  LayerBindingId id,
72  const char* name = nullptr) override
73  {
74  IgnoreUnused(id, name);
75  const TensorInfo& info = layer->GetInputSlot(0).GetConnection()->GetTensorInfo();
76  BOOST_TEST(m_OutputShape == info.GetShape());
77  }
78 
79 protected:
80  void TestQuantizationParams(const TensorInfo& info,
81  const OffsetScalePair& qAsymmU8Params,
82  const OffsetScalePair& qAsymmS8Params,
83  const OffsetScalePair& qSymmS8Params,
84  const OffsetScalePair& qSymmS16Params)
85  {
86  switch (m_QuantizerOptions.m_ActivationFormat)
87  {
88  case DataType::QAsymmU8:
89  TestQuantizationParamsImpl(
90  info, DataType::QAsymmU8, qAsymmU8Params.first, qAsymmU8Params.second);
91  break;
92  case DataType::QAsymmS8:
93  TestQuantizationParamsImpl(
94  info, DataType::QAsymmS8, qAsymmS8Params.first, qAsymmS8Params.second);
95  break;
96  case DataType::QSymmS8:
97  TestQuantizationParamsImpl(
98  info, DataType::QSymmS8, qSymmS8Params.first, qSymmS8Params.second);
99  break;
100  case DataType::QSymmS16:
101  TestQuantizationParamsImpl(
102  info, DataType::QSymmS16, qSymmS16Params.first, qSymmS16Params.second);
103  break;
104  default:
105  throw InvalidArgumentException("Unsupported quantization target");
106  }
107  }
108 
109  void TestDifferentQuantizationScale(const TensorInfo& info0, const TensorInfo& info1)
110  {
111  BOOST_TEST(info0.GetQuantizationScale() != info1.GetQuantizationScale());
112  }
113 
114  void TestConstantQuantizationParams(const TensorInfo& info,
115  const OffsetScalePair& params,
116  DataType dataType = DataType::QAsymmU8)
117  {
118  IgnoreUnused(dataType);
119  TestQuantizationParamsImpl(info, dataType, params.first, params.second);
120  }
121 
122  void TestBiasQuantizationParams(const TensorInfo& info,
123  const OffsetScalePair& qAsymmU8Params,
124  const OffsetScalePair& qAsymmS8Params,
125  const OffsetScalePair& qSymmS8Params,
126  const OffsetScalePair& qSymmS16Params,
127  DataType dataType = DataType::QAsymmU8)
128  {
129  switch (m_QuantizerOptions.m_ActivationFormat)
130  {
131  case DataType::QAsymmU8:
132  TestQuantizationParamsImpl(info, dataType, qAsymmU8Params.first, qAsymmU8Params.second);
133  break;
134  case DataType::QAsymmS8:
135  TestQuantizationParamsImpl(info, dataType, qAsymmS8Params.first, qAsymmS8Params.second);
136  break;
137  case DataType::QSymmS8:
138  TestQuantizationParamsImpl(info, dataType, qSymmS8Params.first, qSymmS8Params.second);
139  break;
140  case DataType::QSymmS16:
141  TestQuantizationParamsImpl(info, dataType, qSymmS16Params.first, qSymmS16Params.second);
142  break;
143  default:
144  throw InvalidArgumentException("Unsupported quantization target");
145  }
146  }
147 
148  void TestQuantizationOnLayersWithBiases(const IConnectableLayer* layer,
149  const ConstTensor& weights,
150  const Optional<ConstTensor>& biases)
151  {
152  TensorInfo info = layer->GetOutputSlot(0).GetTensorInfo();
153  float inputScaleQAsymmU8 = 30.0f / g_AsymmU8QuantizationBase;
154  float inputScaleQAsymmS8 = 30.0f / g_AsymmS8QuantizationBase;
155  float inputScaleQSymmS8 = 15.0f / g_SymmS8QuantizationBase;
156  float inputScaleQSymmS16 = 15.0f / g_SymmS16QuantizationBase;
157  float weightsScale = 3.0f / g_AsymmU8QuantizationBase;
158 
159  // Based off default static range [-15.0f, 15.0f]
160  TestQuantizationParams(info, {inputScaleQAsymmU8, 128},
161  {inputScaleQAsymmS8, 0},
162  {inputScaleQSymmS8, 0},
163  {inputScaleQSymmS16, 0});
164 
165  TestConstantQuantizationParams(weights.GetInfo(), {weightsScale, 85});
166 
167  if (biases.has_value())
168  {
169  TestBiasQuantizationParams(biases.value().GetInfo(),
170  {inputScaleQAsymmU8 * weightsScale, 0},
171  {inputScaleQAsymmS8 * weightsScale, 0},
172  {inputScaleQSymmS8 * weightsScale, 0},
173  {inputScaleQSymmS16 * weightsScale, 0},
175  }
176  }
177 
178  TensorShape m_InputShape;
179  TensorShape m_OutputShape;
180 
181 private:
182  void TestQuantizationParamsImpl(const TensorInfo& info, DataType dataType, float scale, int32_t offset)
183  {
184  BOOST_TEST((info.GetDataType() == dataType));
185  BOOST_TEST(info.GetQuantizationOffset() == offset);
186  BOOST_CHECK_CLOSE(info.GetQuantizationScale(), scale, g_TestTolerance);
187  }
188 
189  QuantizerOptions m_QuantizerOptions;
190 };
191 
192 void VisitLayersTopologically(const INetwork* inputNetwork, ILayerVisitor& visitor)
193 {
194  auto network = PolymorphicDowncast<const Network*>(inputNetwork);
195  auto graph = network->GetGraph().TopologicalSort();
196 
197  VisitLayers(graph, visitor);
198 }
199 
200 class TestAdditionQuantization : public TestQuantization
201 {
202 public:
203  TestAdditionQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
204  : TestQuantization(inputShape, outputShape) {}
205 
206  TestAdditionQuantization(const QuantizerOptions& options,
207  const TensorShape& inputShape,
208  const TensorShape& outputShape)
209  : TestQuantization(options, inputShape, outputShape) {}
210 
211  void VisitAdditionLayer(const IConnectableLayer* layer,
212  const char* name = nullptr) override
213  {
214  IgnoreUnused(name);
216 
217  // Based off default static range [-20.0f, 20.0f]
218  TestQuantizationParams(info, {40.0f / g_AsymmU8QuantizationBase, 128},
219  {40.0f / g_AsymmS8QuantizationBase, 0},
220  {20.0f / g_SymmS8QuantizationBase, 0},
221  {20.0f / g_SymmS16QuantizationBase, 0});
222  }
223 };
224 
225 
226 BOOST_AUTO_TEST_CASE(QuantizeAddition)
227 {
228  INetworkPtr network = INetwork::Create();
229 
230  // Add the layers
231  IConnectableLayer* input0 = network->AddInputLayer(0);
232  IConnectableLayer* input1 = network->AddInputLayer(1);
233  IConnectableLayer* addition = network->AddAdditionLayer();
234  IConnectableLayer* output = network->AddOutputLayer(2);
235 
236  // Establish connections
237  input0->GetOutputSlot(0).Connect(addition->GetInputSlot(0));
238  input1->GetOutputSlot(0).Connect(addition->GetInputSlot(1));
239  addition->GetOutputSlot(0).Connect(output->GetInputSlot(0));
240 
241  // Set TensorInfo
242  const TensorShape shape{1U};
244  input0->GetOutputSlot(0).SetTensorInfo(info);
245  input1->GetOutputSlot(0).SetTensorInfo(info);
246  addition->GetOutputSlot(0).SetTensorInfo(info);
247 
248  const QuantizerOptions qAsymmU8Options(DataType::QAsymmU8);
249  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get(), qAsymmU8Options)->ExportNetwork();
250  TestAdditionQuantization validatorQAsymmU8(shape, shape);
251  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
252 
253  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
254  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
255  TestAdditionQuantization validatorQAsymmS8(qAsymmS8Options, shape, shape);
256  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
257 
258  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
259  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
260  TestAdditionQuantization validatorQSymmS8(qSymmS8Options, shape, shape);
261  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
262 
263  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
264  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
265  TestAdditionQuantization validatorQSymmS16(qSymmS16options, shape, shape);
266  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
267 }
268 
269 class TestActivationQuantization : public TestQuantization
270 {
271 public:
272  TestActivationQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
273  : TestQuantization(inputShape, outputShape) {}
274 
275  TestActivationQuantization(const QuantizerOptions& options,
276  const TensorShape& inputShape,
277  const TensorShape& outputShape)
278  : TestQuantization(options, inputShape, outputShape) {}
279 
280  void VisitActivationLayer(const IConnectableLayer* layer,
281  const ActivationDescriptor& descriptor,
282  const char* name = nullptr) override
283  {
284  IgnoreUnused(descriptor, name);
285 
287 
288  // Based off default static range [0.0f, 15.0f]
289  TestQuantizationParams(info, {15.0f / g_AsymmU8QuantizationBase, 0},
290  {15.0f / g_AsymmS8QuantizationBase, -128},
291  {15.0f / g_SymmS8QuantizationBase, 0},
292  {15.0f / g_SymmS16QuantizationBase, 0});
293  }
294 };
295 
297 {
298  INetworkPtr network = INetwork::Create();
299 
300  // Add the layers
301  IConnectableLayer* input0 = network->AddInputLayer(0);
302  IConnectableLayer* activation = network->AddActivationLayer(descriptor);
303  IConnectableLayer* output = network->AddOutputLayer(2);
304 
305  // Establish connections
306  input0->GetOutputSlot(0).Connect(activation->GetInputSlot(0));
307  activation->GetOutputSlot(0).Connect(output->GetInputSlot(0));
308 
309  // Set TensorInfo
311  input0->GetOutputSlot(0).SetTensorInfo(info);
312  activation->GetOutputSlot(0).SetTensorInfo(info);
313 
314  return network;
315 }
316 
318 {
319  INetworkPtr network = INetwork::Create();
320 
321  // Add input/output layers
322  IConnectableLayer* inputLayer = network->AddInputLayer(0);
323  IConnectableLayer* output = network->AddOutputLayer(1);
324 
325  // Establish connections
326  inputLayer->GetOutputSlot(0).Connect(output->GetInputSlot(0));
327 
328  // Set TensorInfo
329  TensorShape shape{8U};
331  inputLayer->GetOutputSlot(0).SetTensorInfo(info);
332 
333  return network;
334 }
335 
337 {
338  for (auto&& inputLayer : network->GetGraph().GetInputLayers())
339  {
340  ARMNN_ASSERT_MSG(inputLayer->GetNumOutputSlots() == 1, "Input layer should have exactly 1 output slot");
341  return inputLayer->GetOutputSlot(0).GetTensorInfo();
342  }
343  throw InvalidArgumentException("Network has no input layers");
344 }
345 
346 BOOST_AUTO_TEST_CASE(InputOutputLayerDynamicQuant)
347 {
349 
350  armnn::TensorInfo tensorInfo = GetInputTensorInfo(PolymorphicDowncast<const Network*>(network.get()));
351 
352  // Outliers -56 and 98
353  std::vector<float> inputData({0, 0, 0, -56, 98, 0, 0, 0});
354  armnn::ConstTensor inputTensor(tensorInfo, inputData.data());
355 
356  InputTensors inputTensors;
357  inputTensors.push_back(std::make_pair(0, inputTensor));
358 
360 
361  quantizer->Refine(inputTensors);
362 
363  // Outliers -77 and 65
364  std::vector<float> inputData2({0, -77, 0, -56, 65, 0, 0, 0});
365  armnn::ConstTensor inputTensor2(tensorInfo, inputData2.data());
366  InputTensors inputTensors2;
367  inputTensors2.push_back(std::make_pair(0, inputTensor2));
368 
369  quantizer->Refine(inputTensors2);
370 
371  INetworkPtr quantizedNetwork = quantizer->ExportNetwork();
372  // Output Layer should be quantized for a min max of -77 and 98
373  // according to QU8 Quantization Scheme
374  std::unique_ptr<IQuantizationScheme> quantizationScheme = std::make_unique<QAsymmU8QuantizationScheme>();
375  OffsetScalePair qParams = quantizationScheme->ComputeScheme(-77.0, 98.0);
376 
377  class TestOutputLayerVisitor : public LayerVisitorBase<VisitorNoThrowPolicy>
378  {
379  public:
380  TestOutputLayerVisitor(const OffsetScalePair& offsetScalePair, const DataType& dataType) :
381  m_OffsetScalePair(offsetScalePair), m_DataType(dataType) {}
382 
383  void VisitOutputLayer(const IConnectableLayer* layer,
384  LayerBindingId id,
385  const char* name = nullptr) override
386  {
387  IgnoreUnused(id, name);
388  const TensorInfo& info = layer->GetInputSlot(0).GetConnection()->GetTensorInfo();
389  BOOST_CHECK_MESSAGE(info.GetDataType() == m_DataType,
390  std::string(armnn::GetDataTypeName(info.GetDataType()))
391  .append(" == ").append(armnn::GetDataTypeName(m_DataType)));
392  // int_32t
393  BOOST_CHECK(info.GetQuantizationOffset() == m_OffsetScalePair.second);
394  // float
395  BOOST_TEST(info.GetQuantizationScale() == m_OffsetScalePair.first, boost::test_tools::tolerance(0.001));
396  }
397 
398  private:
399  const OffsetScalePair m_OffsetScalePair;
400  const DataType m_DataType;
401  };
402 
403  TestOutputLayerVisitor visitor(qParams, quantizationScheme->GetDataType());
404  quantizedNetwork->Accept(visitor);
405 }
406 
407 BOOST_AUTO_TEST_CASE(QuantizeAbsActivation)
408 {
409  ActivationDescriptor descriptor;
410  descriptor.m_Function = ActivationFunction::Abs;
411  descriptor.m_A = 3.5f;
412  descriptor.m_B = -10.0f;
413 
414  const TensorShape shape{1U};
415  INetworkPtr network = CreateNetworkWithActivationLayer(descriptor, shape);
416 
417  const QuantizerOptions qAsymmU8Options(DataType::QAsymmU8);
418  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get(), qAsymmU8Options)->ExportNetwork();
419  TestActivationQuantization validatorQAsymmU8(shape, shape);
420  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
421 
422  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
423  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
424  TestActivationQuantization validatorQAsymmS8(qAsymmS8Options, shape, shape);
425  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
426 
427  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
428  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
429  TestActivationQuantization validatorQSymmS8(qSymmS8Options, shape, shape);
430  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
431 
432  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
433  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
434  TestActivationQuantization validatorQSymmS16(qSymmS16options, shape, shape);
435  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
436 }
437 
438 BOOST_AUTO_TEST_CASE(QuantizeLinearActivation)
439 {
440  ActivationDescriptor descriptor;
442  descriptor.m_A = 3.5f;
443  descriptor.m_B = -10.0f;
444 
445  const TensorShape shape{1U};
446  INetworkPtr network = CreateNetworkWithActivationLayer(descriptor, shape);
447 
448  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
449  TestActivationQuantization validatorQAsymmU8(shape, shape);
450  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
451 
452  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
453  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
454  TestActivationQuantization validatorQAsymmS8(qAsymmS8Options, shape, shape);
455  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
456 
457  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
458  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
459  TestActivationQuantization validatorQSymmS8(qSymmS8Options, shape, shape);
460  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
461 
462  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
463  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
464  TestActivationQuantization validatorQSymmS16(qSymmS16options, shape, shape);
465  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
466 }
467 
468 BOOST_AUTO_TEST_CASE(QuantizeReLuActivation)
469 {
470  ActivationDescriptor descriptor;
472  descriptor.m_A = 3.5f;
473  descriptor.m_B = -10.0f;
474 
475  const TensorShape shape{1U};
476  INetworkPtr network = CreateNetworkWithActivationLayer(descriptor, shape);
477 
478  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
479  TestActivationQuantization validatorQAsymmU8(shape, shape);
480  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
481 
482  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
483  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
484  TestActivationQuantization validatorQAsymmS8(qAsymmS8Options, shape, shape);
485  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
486 
487  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
488  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
489  TestActivationQuantization validatorQSymmS8(qSymmS8Options, shape, shape);
490  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
491 
492  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
493  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
494  TestActivationQuantization validatorQSymmS16(qSymmS16options, shape, shape);
495  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
496 }
497 
498 BOOST_AUTO_TEST_CASE(QuantizeSoftReLuActivation)
499 {
500  ActivationDescriptor descriptor;
502  descriptor.m_A = 3.5f;
503  descriptor.m_B = -10.0f;
504 
505  const TensorShape shape{1U};
506  INetworkPtr network = CreateNetworkWithActivationLayer(descriptor, shape);
507 
508  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
509  TestActivationQuantization validatorQAsymmU8(shape, shape);
510  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
511 
512  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
513  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
514  TestActivationQuantization validatorQAsymmS8(qAsymmS8Options, shape, shape);
515  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
516 
517  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
518  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
519  TestActivationQuantization validatorQSymmS8(qSymmS8Options, shape, shape);
520  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
521 
522  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
523  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
524  TestActivationQuantization validatorQSymmS16(qSymmS16options, shape, shape);
525  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
526 }
527 
528 BOOST_AUTO_TEST_CASE(QuantizeBoundedReluActivation)
529 {
530  class TestBoundedReluActivationQuantization : public TestQuantization
531  {
532  public:
533  TestBoundedReluActivationQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
534  : TestQuantization(inputShape, outputShape) {}
535 
536  TestBoundedReluActivationQuantization(const QuantizerOptions& options,
537  const TensorShape& inputShape,
538  const TensorShape& outputShape)
539  : TestQuantization(options, inputShape, outputShape) {}
540 
541  void VisitActivationLayer(const IConnectableLayer* layer,
542  const ActivationDescriptor& descriptor,
543  const char* name = nullptr) override
544  {
545  IgnoreUnused(descriptor, name);
547 
548  // Based off default static range [0.0f, 3.5f]
549  TestQuantizationParams(info, {3.5f / g_AsymmU8QuantizationBase, 0},
550  {3.5f / g_AsymmS8QuantizationBase, -128},
551  {3.5f / g_SymmS8QuantizationBase, 0},
552  {3.5f / g_SymmS16QuantizationBase, 0});
553  }
554  };
555 
556  ActivationDescriptor descriptor;
558  descriptor.m_A = 3.5f;
559  descriptor.m_B = -10.0f;
560 
561  const TensorShape shape{1U};
562  INetworkPtr network = CreateNetworkWithActivationLayer(descriptor, shape);
563 
564  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
565  TestBoundedReluActivationQuantization validatorQAsymmU8(shape, shape);
566  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
567 
568  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
569  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
570  TestBoundedReluActivationQuantization validatorQAsymmS8(qAsymmS8Options, shape, shape);
571  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
572 
573  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
574  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
575  TestBoundedReluActivationQuantization validatorQSymmS8(qSymmS8Options, shape, shape);
576  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
577 
578  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
579  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
580  TestBoundedReluActivationQuantization validatorQSymmS16(qSymmS16options, shape, shape);
581  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
582 }
583 
584 BOOST_AUTO_TEST_CASE(QuantizeTanHActivation)
585 {
586  class TestTanHActivationQuantization : public TestQuantization
587  {
588  public:
589  TestTanHActivationQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
590  : TestQuantization(inputShape, outputShape) {}
591 
592  TestTanHActivationQuantization(const QuantizerOptions& options,
593  const TensorShape& inputShape,
594  const TensorShape& outputShape)
595  : TestQuantization(options, inputShape, outputShape) {}
596 
597  void VisitActivationLayer(const IConnectableLayer* layer,
598  const ActivationDescriptor& descriptor,
599  const char* name = nullptr) override
600  {
601  IgnoreUnused(descriptor, name);
603 
604  // Based off default static range [-1.0f, 1.0f]
605  TestQuantizationParams(
606  info, {2.0f / g_AsymmU8QuantizationBase, 128},
607  {2.0f / g_AsymmS8QuantizationBase, 0},
608  {1.0f / g_SymmS8QuantizationBase , 0},
609  {1.0f / g_SymmS16QuantizationBase, 0});
610  }
611  };
612 
613  ActivationDescriptor descriptor;
615  descriptor.m_A = 3.5f;
616  descriptor.m_B = -10.0f;
617 
618  const TensorShape shape{1U};
619  INetworkPtr network = CreateNetworkWithActivationLayer(descriptor, shape);
620 
621  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
622  TestTanHActivationQuantization validatorQAsymmU8(shape, shape);
623  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
624 
625  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
626  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
627  TestTanHActivationQuantization validatorQAsymmS8(qAsymmS8Options, shape, shape);
628  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
629 
630  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
631  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
632  TestTanHActivationQuantization validatorQSymmS8(qSymmS8Options, shape, shape);
633  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
634 
635  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
636  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
637  TestTanHActivationQuantization validatorQSymmS16(qSymmS16options, shape, shape);
638  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
639 }
640 
641 class TestLeakyReLuActivationQuantization : public TestQuantization
642 {
643 public:
644  TestLeakyReLuActivationQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
645  : TestQuantization(inputShape, outputShape) {}
646 
647  TestLeakyReLuActivationQuantization(const QuantizerOptions& options,
648  const TensorShape& inputShape,
649  const TensorShape& outputShape)
650  : TestQuantization(options, inputShape, outputShape) {}
651 
652  void VisitActivationLayer(const IConnectableLayer* layer,
653  const ActivationDescriptor& descriptor,
654  const char* name = nullptr) override
655  {
656  IgnoreUnused(descriptor, name);
658 
659  // Based off default static range [-5.0f, 15.0f]
660  TestQuantizationParams(info, {20.0f / g_AsymmU8QuantizationBase, 64},
661  {20.0f / g_AsymmS8QuantizationBase,-64},
662  {15.0f / g_SymmS8QuantizationBase , 0},
663  {15.0f / g_SymmS16QuantizationBase, 0});
664  }
665 
666 protected:
667  // Used by the descendant classes which test layers
668  // that are forwarding their parent layer settings
669  void CheckForwardedQuantizationSettings(const IConnectableLayer* layer)
670  {
672  TestQuantizationParams(info, {20.0f / g_AsymmU8QuantizationBase, 64},
673  {20.0f / g_AsymmS8QuantizationBase,-64},
674  {15.0f / g_SymmS8QuantizationBase, 0},
675  {15.0f / g_SymmS16QuantizationBase, 0});
676  }
677 };
678 
679 BOOST_AUTO_TEST_CASE(QuantizeLeakyReLuActivation)
680 {
681  ActivationDescriptor descriptor;
683  descriptor.m_A = 3.5f;
684  descriptor.m_B = -10.0f;
685 
686  const TensorShape shape{1U};
687  INetworkPtr network = CreateNetworkWithActivationLayer(descriptor, shape);
688 
689  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
690  TestLeakyReLuActivationQuantization validatorQAsymmU8(shape, shape);
691  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
692 
693  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
694  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
695  TestLeakyReLuActivationQuantization validatorQAsymmS8(qAsymmS8Options, shape, shape);
696  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
697 
698  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
699  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
700  TestLeakyReLuActivationQuantization validatorQSymmS8(qSymmS8Options, shape, shape);
701  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
702 
703  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
704  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
705  TestLeakyReLuActivationQuantization validatorQSymmS16(qSymmS16options, shape, shape);
706  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
707 }
708 
709 
710 BOOST_AUTO_TEST_CASE(QuantizeELuActivation)
711 {
712  class TestEluActivationQuantization : public TestQuantization
713  {
714  public:
715  TestEluActivationQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
716  : TestQuantization(inputShape, outputShape) {}
717 
718  TestEluActivationQuantization(const QuantizerOptions& options,
719  const TensorShape& inputShape,
720  const TensorShape& outputShape)
721  : TestQuantization(options, inputShape, outputShape) {}
722 
723  void VisitActivationLayer(const IConnectableLayer* layer,
724  const ActivationDescriptor& descriptor,
725  const char* name = nullptr) override
726  {
727  IgnoreUnused(descriptor, name);
729 
730  // Based off default static range [-15.0f, 15.0f]
731  TestQuantizationParams(
732  info, {30.0f / g_AsymmU8QuantizationBase, 128},
733  {30.0f / g_AsymmS8QuantizationBase, 0},
734  {15.0f / g_SymmS8QuantizationBase, 0},
735  {15.0f / g_SymmS16QuantizationBase, 0});
736  }
737  };
738 
739  ActivationDescriptor descriptor;
740  descriptor.m_Function = ActivationFunction::Elu;
741 
742  const TensorShape shape{1U};
743  INetworkPtr network = CreateNetworkWithActivationLayer(descriptor, shape);
744 
745  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
746  TestEluActivationQuantization validatorQAsymmU8(shape, shape);
747  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
748 
749  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
750  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
751  TestEluActivationQuantization validatorQAsymmS8(qAsymmS8Options, shape, shape);
752  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
753 
754  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
755  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
756  TestEluActivationQuantization validatorQSymmS8(qSymmS8Options, shape, shape);
757  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
758 
759  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
760  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
761  TestEluActivationQuantization validatorQSymmS16(qSymmS16options, shape, shape);
762  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
763 }
764 BOOST_AUTO_TEST_CASE(QuantizeHardSwishActivation)
765 {
766  class TestHardSwishActivationQuantization : public TestQuantization
767  {
768  public:
769  TestHardSwishActivationQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
770  : TestQuantization(inputShape, outputShape) {}
771 
772  TestHardSwishActivationQuantization(const QuantizerOptions& options,
773  const TensorShape& inputShape,
774  const TensorShape& outputShape)
775  : TestQuantization(options, inputShape, outputShape) {}
776 
777  void VisitActivationLayer(const IConnectableLayer* layer,
778  const ActivationDescriptor& descriptor,
779  const char* name = nullptr) override
780  {
781  IgnoreUnused(descriptor, name);
783 
784  // Based off default static range [-15.0f, 15.0f]
785  TestQuantizationParams(
786  info, {30.0f / g_AsymmU8QuantizationBase, 128},
787  {30.0f / g_AsymmS8QuantizationBase, 0},
788  {15.0f / g_SymmS8QuantizationBase, 0},
789  {15.0f / g_SymmS16QuantizationBase, 0});
790  }
791  };
792 
793  ActivationDescriptor descriptor;
795 
796  const TensorShape shape{1U};
797  INetworkPtr network = CreateNetworkWithActivationLayer(descriptor, shape);
798 
799  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
800  TestHardSwishActivationQuantization validatorQAsymmU8(shape, shape);
801  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
802 
803  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
804  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
805  TestHardSwishActivationQuantization validatorQAsymmS8(qAsymmS8Options, shape, shape);
806  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
807 
808  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
809  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
810  TestHardSwishActivationQuantization validatorQSymmS8(qSymmS8Options, shape, shape);
811  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
812 
813  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
814  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
815  TestHardSwishActivationQuantization validatorQSymmS16(qSymmS16options, shape, shape);
816  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
817 }
818 
819 
820 BOOST_AUTO_TEST_CASE(QuantizeBatchNorm)
821 {
822  class TestBatchNormalizationQuantization : public TestQuantization
823  {
824  public:
825  TestBatchNormalizationQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
826  : TestQuantization(inputShape, outputShape) {}
827 
828  TestBatchNormalizationQuantization(const QuantizerOptions& options,
829  const TensorShape& inputShape,
830  const TensorShape& outputShape)
831  : TestQuantization(options, inputShape, outputShape) {}
832 
833  void VisitBatchNormalizationLayer(const IConnectableLayer* layer,
834  const BatchNormalizationDescriptor& desc,
835  const ConstTensor& mean,
836  const ConstTensor& variance,
837  const ConstTensor& beta,
838  const ConstTensor& gamma,
839  const char* name = nullptr) override
840  {
841  IgnoreUnused(desc, name);
843 
844  // Based off default static range [-15.0f, 15.0f]
845  TestQuantizationParams(
846  info, {30.0f / g_AsymmU8QuantizationBase, 128},
847  {30.0f / g_AsymmS8QuantizationBase, 0},
848  {15.0f / g_SymmS8QuantizationBase, 0},
849  {15.0f / g_SymmS16QuantizationBase, 0});
850 
851  // Test constants
852  TestConstantQuantizationParams(mean.GetInfo(), {3.0f / g_AsymmU8QuantizationBase, 85});
853  TestConstantQuantizationParams(variance.GetInfo(), {3.0f / g_AsymmU8QuantizationBase, 85});
854  TestConstantQuantizationParams(beta.GetInfo(), {3.0f / g_AsymmU8QuantizationBase, 85});
855  TestConstantQuantizationParams(gamma.GetInfo(), {3.0f / g_AsymmU8QuantizationBase, 85});
856  }
857  };
858 
859  INetworkPtr network = INetwork::Create();
860 
861  const TensorShape shape{3U};
863 
864  std::vector<float> meanData{-1.0f, 1.5f, 2.0f};
865  std::vector<float> varData{-1.0f, 1.5f, 2.0f};
866  std::vector<float> betaData{-1.0f, 1.5f, 2.0f};
867  std::vector<float> gammaData{-1.0f, 1.5f, 2.0f};
868 
869  ConstTensor mean(info, meanData);
870  ConstTensor var(info, varData);
871  ConstTensor beta(info, betaData);
872  ConstTensor gamma(info, gammaData);
873 
875 
876  // Add the layers
877  IConnectableLayer* input0 = network->AddInputLayer(0);
878  IConnectableLayer* batchNorm = network->AddBatchNormalizationLayer(desc, mean, var, beta, gamma);
879  IConnectableLayer* output = network->AddOutputLayer(1);
880 
881  // Establish connections
882  input0->GetOutputSlot(0).Connect(batchNorm->GetInputSlot(0));
883  batchNorm->GetOutputSlot(0).Connect(output->GetInputSlot(0));
884 
885  // Set TensorInfo
886  input0->GetOutputSlot(0).SetTensorInfo(info);
887  batchNorm->GetOutputSlot(0).SetTensorInfo(info);
888 
889  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
890  TestBatchNormalizationQuantization validatorQAsymmU8(shape, shape);
891  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
892 
893  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
894  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
895  TestBatchNormalizationQuantization validatorQAsymmS8(qAsymmS8Options, shape, shape);
896  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
897 
898  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
899  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
900  TestBatchNormalizationQuantization validatorQSymmS8(qSymmS8Options, shape, shape);
901  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
902 
903  const QuantizerOptions QQsymm16Options(DataType::QSymmS16);
904  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), QQsymm16Options)->ExportNetwork();
905  TestBatchNormalizationQuantization validatorQSymmS16(QQsymm16Options, shape, shape);
906  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
907 }
908 
909 BOOST_AUTO_TEST_CASE(QuantizeDepthToSpace)
910 {
911  class TestDepthToSpaceQuantization : public TestQuantization
912  {
913  public:
914  TestDepthToSpaceQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
915  : TestQuantization(inputShape, outputShape) {}
916 
917  TestDepthToSpaceQuantization(const QuantizerOptions& options,
918  const TensorShape& inputShape,
919  const TensorShape& outputShape)
920  : TestQuantization(options, inputShape, outputShape) {}
921 
922  virtual void VisitDepthToSpaceLayer(const IConnectableLayer* layer,
923  const DepthToSpaceDescriptor& desc,
924  const char* name = nullptr)
925  {
926  IgnoreUnused(desc, name);
927  const TensorInfo& info = layer->GetOutputSlot(0).GetTensorInfo();
928 
929  const OffsetScalePair qAsymmU8Params{ 30.0f / g_AsymmU8QuantizationBase, 128 };
930  const OffsetScalePair qAsymmS8Params{ 30.0f / g_AsymmS8QuantizationBase, 0 };
931  const OffsetScalePair qSymmS8Params { 15.0f / g_SymmS8QuantizationBase, 0 };
932  const OffsetScalePair qSymmS16Params{ 15.0f / g_SymmS16QuantizationBase, 0 };
933 
934  TestQuantizationParams(info, qAsymmU8Params, qAsymmS8Params, qSymmS8Params, qSymmS16Params);
935  }
936  };
937 
938  const TensorShape inputShape { 1, 2, 2, 4 };
939  const TensorShape outputShape{ 1, 4, 4, 1 };
940 
941  const TensorInfo inputInfo (inputShape, DataType::Float32);
942  const TensorInfo outputInfo(outputShape, DataType::Float32);
943 
944  INetworkPtr network = INetwork::Create();
945  const DepthToSpaceDescriptor descriptor(2, armnn::DataLayout::NHWC);
946 
947  IConnectableLayer* inputLayer = network->AddInputLayer(0);
948  IConnectableLayer* depthToSpaceLayer = network->AddDepthToSpaceLayer(descriptor);
949  IConnectableLayer* outputLayer = network->AddOutputLayer(0);
950 
951  inputLayer->GetOutputSlot(0).Connect(depthToSpaceLayer->GetInputSlot(0));
952  depthToSpaceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
953 
954  inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
955  depthToSpaceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
956 
957  // test QAsymmU8 quantization
958  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
959  TestDepthToSpaceQuantization validatorQAsymmU8(inputShape, outputShape);
960  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
961 
962  // test QAsymmS8 quantization
963  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
964  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
965  TestDepthToSpaceQuantization validatorQAsymmS8(qAsymmS8Options, inputShape, outputShape);
966  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
967 
968  // test QSymmS8 quantization
969  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
970  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
971  TestDepthToSpaceQuantization validatorQSymmS8(qSymmS8Options, inputShape, outputShape);
972  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
973 
974  // test QSymmS16 quantization
975  const QuantizerOptions Qsymm16Options(DataType::QSymmS16);
976  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), Qsymm16Options)->ExportNetwork();
977  TestDepthToSpaceQuantization validatorQSymmS16(Qsymm16Options, inputShape, outputShape);
978  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
979 }
980 
981 BOOST_AUTO_TEST_CASE(OverrideInputRangeEmptyNetwork)
982 {
983  RangeTracker ranges;
984  RangeTracker::MinMaxRange minMaxRange(-12.3f, 45.6f); // Range to use for the override
985 
986  Network network; // Empty network
987  auto inputLayers = network.GetGraph().GetInputLayers(); // Empty list of input layers
988 
989  OverrideInputRangeVisitor overrideInputRangeVisitor(ranges, 0, minMaxRange);
990  VisitLayers(inputLayers, overrideInputRangeVisitor);
991 
992  BOOST_CHECK(ranges.IsEmpty()); // Check that the map of ranges remained untouched
993 }
994 
995 BOOST_AUTO_TEST_CASE(OverrideInputRangeNoInputLayers)
996 {
997  RangeTracker ranges;
998  MinMaxRange minMaxRange(-12.3f, 45.6f); // Range to use for the override
999 
1000  Network network;
1001  network.AddAdditionLayer(); // Network with no input layers
1002  auto inputLayers = network.GetGraph().GetInputLayers(); // Empty list of input layers
1003 
1004  OverrideInputRangeVisitor overrideInputRangeVisitor(ranges, 0, minMaxRange);
1005  VisitLayers(inputLayers, overrideInputRangeVisitor);
1006 
1007  BOOST_CHECK(ranges.IsEmpty()); // Check that the map of ranges remained untouched
1008 }
1009 
1010 BOOST_AUTO_TEST_CASE(OverrideInputRangeInputLayers)
1011 {
1012  RangeTracker ranges;
1013  MinMaxRange minMaxRange(-12.3f, 45.6f); // Range to use for the override
1014 
1015  Network network;
1016 
1017  // Adding the layers
1018  IConnectableLayer* input0 = network.AddInputLayer(0);
1019  IConnectableLayer* input1 = network.AddInputLayer(1);
1020  IConnectableLayer* addition = network.AddAdditionLayer();
1021  IConnectableLayer* output = network.AddOutputLayer(2);
1022 
1023  // Connecting the layer
1024  input0->GetOutputSlot(0).Connect(addition->GetInputSlot(0));
1025  input1->GetOutputSlot(0).Connect(addition->GetInputSlot(1));
1026  addition->GetOutputSlot(0).Connect(output->GetInputSlot(0));
1027 
1028  // Setting the TensorInfos
1029  TensorShape shape{1U};
1031  input0->GetOutputSlot(0).SetTensorInfo(info);
1032  input1->GetOutputSlot(0).SetTensorInfo(info);
1033  addition->GetOutputSlot(0).SetTensorInfo(info);
1034 
1035  auto inputLayers = network.GetGraph().GetInputLayers(); // List of input layers
1036 
1037  // Trying to override the input range for the input layer with binding id 3 (does not exist in the network)
1038  OverrideInputRangeVisitor overrideInputRangeVisitorLayer3(ranges, 3, minMaxRange);
1039  VisitLayers(inputLayers, overrideInputRangeVisitorLayer3);
1040 
1041  // Check that the map of ranges remained untouched
1042  BOOST_CHECK(ranges.IsEmpty());
1043 
1044  // Override the input range for the input layer with binding id 1
1045  OverrideInputRangeVisitor overrideInputRangeVisitorLayer1(ranges, 1, minMaxRange);
1046  VisitLayers(inputLayers, overrideInputRangeVisitorLayer1);
1047 
1048  // Check that the map of ranges has been populated
1049  BOOST_CHECK(!ranges.IsEmpty());
1050 
1051  // Check that an entry for the input layer with binding id 0 does not exist
1052  BOOST_CHECK(!ranges.HasRanges(input0->GetGuid()));
1053 
1054  // Check that an entry for the input layer with binding id 1 exists
1055  BOOST_CHECK(ranges.HasRanges(input1->GetGuid()));
1056 
1057  // Check the the overridden values are what we intended to set
1058  BOOST_CHECK(ranges.GetRange(input1->GetGuid(), 0) == minMaxRange);
1059 }
1060 
1062  const TensorShape& inputShape,
1063  const TensorShape& outputShape)
1064 {
1066  desc.m_BiasEnabled = biasEnabled;
1067  INetworkPtr network = INetwork::Create();
1068 
1069  const TensorInfo info(inputShape, DataType::Float32);
1070  const TensorInfo outputInfo(outputShape, DataType::Float32);
1071 
1072  std::vector<float> weightsData{-1.0f, 1.5f, 2.0f};
1073  ConstTensor weights(info, weightsData);
1074 
1075  // Add the layers
1076  IConnectableLayer* input0 = network->AddInputLayer(0);
1077  IConnectableLayer* fullyConnected;
1078  Optional<ConstTensor> optionalBias;
1079  std::vector<float> biasData{10.0f, 20.0f, 30.0f};
1080  if (desc.m_BiasEnabled)
1081  {
1082  ConstTensor bias(info, biasData);
1083  optionalBias = Optional<ConstTensor>(bias);
1084  }
1085  fullyConnected = network->AddFullyConnectedLayer(desc, weights, optionalBias);
1086  IConnectableLayer* output = network->AddOutputLayer(1);
1087 
1088  // Establish connections
1089  input0->GetOutputSlot(0).Connect(fullyConnected->GetInputSlot(0));
1090  fullyConnected->GetOutputSlot(0).Connect(output->GetInputSlot(0));
1091 
1092  // Set TensorInfo
1093  input0->GetOutputSlot(0).SetTensorInfo(info);
1094  fullyConnected->GetOutputSlot(0).SetTensorInfo(outputInfo);
1095 
1096  return network;
1097 }
1098 
1099 void ValidateFullyConnectedLayer(const bool biasEnabled)
1100 {
1101  class TestFullyConnectedQuantization : public TestQuantization
1102  {
1103  public:
1104  TestFullyConnectedQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
1105  : TestQuantization(inputShape, outputShape) {}
1106 
1107  TestFullyConnectedQuantization(const QuantizerOptions& options,
1108  const TensorShape& inputShape,
1109  const TensorShape& outputShape)
1110  : TestQuantization(options, inputShape, outputShape) {}
1111 
1112  void VisitFullyConnectedLayer(const IConnectableLayer* layer,
1113  const FullyConnectedDescriptor& desc,
1114  const ConstTensor& weights,
1115  const Optional<ConstTensor>& biases,
1116  const char* name = nullptr) override
1117  {
1118  IgnoreUnused(desc, name);
1119  TestQuantizationOnLayersWithBiases(layer, weights, biases);
1120  }
1121  };
1122 
1123  const TensorShape shape{3U};
1124  INetworkPtr network = CreateNetworkWithFullyConnectedLayer(biasEnabled, shape, shape);
1125 
1126  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
1127  TestFullyConnectedQuantization validatorQAsymmU8(shape, shape);
1128  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
1129 
1130  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
1131  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
1132  TestFullyConnectedQuantization validatorQAsymmS8(qAsymmS8Options, shape, shape);
1133  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
1134 
1135  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
1136  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
1137  TestFullyConnectedQuantization validatorQSymmS8(qSymmS8Options, shape, shape);
1138  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
1139 
1140  const QuantizerOptions Qsymm16Options(DataType::QSymmS16);
1141  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), Qsymm16Options)->ExportNetwork();
1142  TestFullyConnectedQuantization validatorQSymmS16(Qsymm16Options, shape, shape);
1143  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
1144 }
1145 
1147 {
1148  class TestFillQuantization : public TestQuantization
1149  {
1150  public:
1151  TestFillQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
1152  : TestQuantization(inputShape, outputShape) {}
1153 
1154  TestFillQuantization(const QuantizerOptions& options,
1155  const TensorShape& inputShape,
1156  const TensorShape& outputShape)
1157  : TestQuantization(options, inputShape, outputShape) {}
1158 
1159  virtual void VisitFillLayer(const IConnectableLayer* layer,
1160  const FillDescriptor& desc,
1161  const char* name = nullptr)
1162  {
1163  IgnoreUnused(desc, name);
1165 
1166  const OffsetScalePair qAsymmU8Params{ 30.0f / g_AsymmU8QuantizationBase, 128 };
1167  const OffsetScalePair qAsymmS8Params { 30.0f / g_AsymmS8QuantizationBase, 0};
1168  const OffsetScalePair qSymmS8Params { 15.0f / g_SymmS8QuantizationBase, 0};
1169  const OffsetScalePair qSymmS16Params{ 15.0f / g_SymmS16QuantizationBase, 0 };
1170 
1171  TestQuantizationParams(info, qAsymmU8Params, qAsymmS8Params, qSymmS8Params, qSymmS16Params);
1172  }
1173  };
1174 
1175  const TensorShape tensorShape{ 1U };
1176  const TensorInfo tensorInfo(tensorShape, DataType::Float32);
1177 
1178  INetworkPtr network = INetwork::Create();
1179 
1180  FillDescriptor descriptor;
1181  descriptor.m_Value = 1;
1182 
1183  IConnectableLayer* inputLayer = network->AddInputLayer(0);
1184  IConnectableLayer* fillLayer = network->AddFillLayer(descriptor);
1185  IConnectableLayer* outputLayer = network->AddOutputLayer(0);
1186 
1187  inputLayer->GetOutputSlot(0).Connect(fillLayer->GetInputSlot(0));
1188  fillLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1189 
1190  inputLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1191  fillLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1192 
1193  // test QAsymmU8 quantization
1194  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
1195  TestFillQuantization validatorQAsymmU8(tensorShape, tensorShape);
1196  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
1197 
1198  // test QAsymmS8 quantization
1199  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
1200  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
1201  TestFillQuantization validatorQAsymmS8(qAsymmS8Options, tensorShape, tensorShape);
1202  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
1203 
1204  // test QSymmS8 quantization
1205  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
1206  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
1207  TestFillQuantization validatorQSymmS8(qSymmS8Options, tensorShape, tensorShape);
1208  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
1209 
1210  // test QuantisedSymmS16 quantization
1211  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
1212  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
1213  TestFillQuantization validatorQSymmS16(qSymmS16options, tensorShape, tensorShape);
1214  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
1215 }
1216 
1217 BOOST_AUTO_TEST_CASE(QuantizeFullyConnected)
1218 {
1220 }
1221 
1222 BOOST_AUTO_TEST_CASE(QuantizeFullyConnectedBiasEnabled)
1223 {
1225 }
1226 
1227 void TestQuantizeConvolution2d(bool useBiases)
1228 {
1229  class TestConv2dQuantization : public TestQuantization
1230  {
1231  public:
1232  TestConv2dQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
1233  : TestQuantization(inputShape, outputShape) {}
1234 
1235  TestConv2dQuantization(const QuantizerOptions& options,
1236  const TensorShape& inputShape,
1237  const TensorShape& outputShape)
1238  : TestQuantization(options, inputShape, outputShape) {}
1239 
1240  void VisitConvolution2dLayer(const IConnectableLayer *layer,
1241  const Convolution2dDescriptor& convolution2dDescriptor,
1242  const ConstTensor& weights,
1243  const Optional<ConstTensor>& biases,
1244  const char *name = nullptr) override
1245  {
1246  IgnoreUnused(convolution2dDescriptor, name);
1247  TestQuantizationOnLayersWithBiases(layer, weights, biases);
1248  }
1249  };
1250 
1251  INetworkPtr network = INetwork::Create();
1252 
1253  TensorShape shape{3U};
1255 
1256  std::vector<float> weightsData{-1.0f, 1.5f, 2.0f};
1257  ConstTensor weights(info, weightsData);
1258 
1259  Convolution2dDescriptor descriptor;
1260  descriptor.m_BiasEnabled = useBiases;
1261 
1262  // Add the layers
1263  IConnectableLayer* input0 = network->AddInputLayer(0);
1264  IConnectableLayer* conv2d;
1265  Optional<ConstTensor> optionalBiases;
1266  std::vector<float> biasesData{-1.0f, 1.5f, 2.0f};
1267  if (useBiases)
1268  {
1269  ConstTensor biases(info, biasesData);
1270  optionalBiases = Optional<ConstTensor>(biases);
1271  }
1272  conv2d = network->AddConvolution2dLayer(descriptor, weights, optionalBiases);
1273  IConnectableLayer* output = network->AddOutputLayer(1);
1274 
1275  // Establish connections
1276  input0->GetOutputSlot(0).Connect(conv2d->GetInputSlot(0));
1277  conv2d->GetOutputSlot(0).Connect(output->GetInputSlot(0));
1278 
1279  // Set TensorInfo
1280  input0->GetOutputSlot(0).SetTensorInfo(info);
1281  conv2d->GetOutputSlot(0).SetTensorInfo(info);
1282 
1283  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
1284  TestConv2dQuantization validatorQAsymmU8(shape, shape);
1285  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
1286 
1287  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
1288  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
1289  TestConv2dQuantization validatorQAsymmS8(qAsymmS8Options, shape, shape);
1290  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
1291 
1292  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
1293  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
1294  TestConv2dQuantization validatorQSymmS8(qSymmS8Options, shape, shape);
1295  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
1296 
1297  const QuantizerOptions Qsymm16Options(DataType::QSymmS16);
1298  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), Qsymm16Options)->ExportNetwork();
1299  TestConv2dQuantization validatorQSymmS16(Qsymm16Options, shape, shape);
1300  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
1301 }
1302 
1303 BOOST_AUTO_TEST_CASE(QuantizeConvolution2d)
1304 {
1306 }
1307 
1308 BOOST_AUTO_TEST_CASE(QuantizeConvolution2dWithBiases)
1309 {
1311 }
1312 
1314 {
1315  class TestDepthwiseConv2dQuantization : public TestQuantization
1316  {
1317  public:
1318  TestDepthwiseConv2dQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
1319  : TestQuantization(inputShape, outputShape) {}
1320 
1321  TestDepthwiseConv2dQuantization(const QuantizerOptions& options,
1322  const TensorShape& inputShape,
1323  const TensorShape& outputShape)
1324  : TestQuantization(options, inputShape, outputShape) {}
1325 
1326  void VisitDepthwiseConvolution2dLayer(const IConnectableLayer *layer,
1327  const DepthwiseConvolution2dDescriptor& convolution2dDescriptor,
1328  const ConstTensor& weights,
1329  const Optional<ConstTensor>& biases,
1330  const char *name = nullptr) override
1331  {
1332  IgnoreUnused(convolution2dDescriptor, name);
1333  TestQuantizationOnLayersWithBiases(layer, weights, biases);
1334  }
1335  };
1336 
1337  INetworkPtr network = INetwork::Create();
1338 
1339  TensorShape shape{3U};
1341 
1342  std::vector<float> weightsData{-1.0f, 1.5f, 2.0f};
1343  ConstTensor weights(info, weightsData);
1344 
1346  descriptor.m_BiasEnabled = useBiases;
1347 
1348  // Add the layers
1349  IConnectableLayer* input0 = network->AddInputLayer(0);
1350  IConnectableLayer* depthwiseConv2d;
1351  Optional<ConstTensor> optionalBiases;
1352  std::vector<float> biasesData{-1.0f, 1.5f, 2.0f};
1353  if (useBiases)
1354  {
1355  ConstTensor biases(info, biasesData);
1356  optionalBiases = Optional<ConstTensor>(biases);
1357  }
1358  depthwiseConv2d = network->AddDepthwiseConvolution2dLayer(descriptor, weights, optionalBiases);
1359  IConnectableLayer* output = network->AddOutputLayer(1);
1360 
1361  // Establish connections
1362  input0->GetOutputSlot(0).Connect(depthwiseConv2d->GetInputSlot(0));
1363  depthwiseConv2d->GetOutputSlot(0).Connect(output->GetInputSlot(0));
1364 
1365  //Set TensorInfo
1366  input0->GetOutputSlot(0).SetTensorInfo(info);
1367  depthwiseConv2d->GetOutputSlot(0).SetTensorInfo(info);
1368 
1369  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
1370  TestDepthwiseConv2dQuantization validatorQAsymmU8(shape, shape);
1371  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
1372 
1373  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
1374  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
1375  TestDepthwiseConv2dQuantization validatorQAsymmS8(qAsymmS8Options, shape, shape);
1376  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
1377 
1378  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
1379  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
1380  TestDepthwiseConv2dQuantization validatorQSymmS8(qSymmS8Options, shape, shape);
1381  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
1382 
1383  const QuantizerOptions Qsymm16Options(DataType::QSymmS16);
1384  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), Qsymm16Options)->ExportNetwork();
1385  TestDepthwiseConv2dQuantization validatorQSymmS16(Qsymm16Options, shape, shape);
1386  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
1387 }
1388 
1389 BOOST_AUTO_TEST_CASE(QuantizeDepthwiseConvolution2d)
1390 {
1392 }
1393 
1394 BOOST_AUTO_TEST_CASE(QuantizeDepthwiseConvolution2dWithBiases)
1395 {
1397 }
1398 
1399 BOOST_AUTO_TEST_CASE(QuantizeInstanceNormalization)
1400 {
1401  class TestInstanceNormalizationQuantization : public TestQuantization
1402  {
1403  public:
1404  TestInstanceNormalizationQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
1405  : TestQuantization(inputShape, outputShape) {}
1406 
1407  TestInstanceNormalizationQuantization(const QuantizerOptions& options,
1408  const TensorShape& inputShape,
1409  const TensorShape& outputShape)
1410  : TestQuantization(options, inputShape, outputShape) {}
1411 
1412  virtual void VisitInstanceNormalizationLayer(const IConnectableLayer* layer,
1413  const InstanceNormalizationDescriptor& descriptor,
1414  const char* name = nullptr)
1415  {
1416  IgnoreUnused(descriptor, name);
1417  const TensorInfo& info = layer->GetOutputSlot(0).GetTensorInfo();
1418 
1419  const OffsetScalePair qAsymmU8Params{ 30.0f / g_AsymmU8QuantizationBase, 128 };
1420  const OffsetScalePair qAsymmS8Params { 30.0f / g_AsymmS8QuantizationBase, 0};
1421  const OffsetScalePair qSymmS8Params { 15.0f / g_SymmS8QuantizationBase, 0};
1422  const OffsetScalePair qSymmS16Params{ 15.0f / g_SymmS16QuantizationBase, 0 };
1423 
1424  TestQuantizationParams(info, qAsymmU8Params, qAsymmS8Params, qSymmS8Params, qSymmS16Params);
1425  }
1426  };
1427 
1428  const TensorShape tensorShape{ 1, 4, 4, 1 };
1429  const TensorInfo tensorInfo(tensorShape, DataType::Float32);
1430 
1431  INetworkPtr network = INetwork::Create();
1432 
1433  IConnectableLayer* inputLayer = network->AddInputLayer(0);
1434  IConnectableLayer* instanceNormLayer = network->AddInstanceNormalizationLayer(InstanceNormalizationDescriptor());
1435  IConnectableLayer* outputLayer = network->AddOutputLayer(0);
1436 
1437  inputLayer->GetOutputSlot(0).Connect(instanceNormLayer->GetInputSlot(0));
1438  instanceNormLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1439 
1440  inputLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1441  instanceNormLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1442 
1443  // test QAsymmU8 quantization
1444  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
1445  TestInstanceNormalizationQuantization validatorQAsymmU8(tensorShape, tensorShape);
1446  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
1447 
1448  //test QAsymmS8 quantization
1449  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
1450  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
1451  TestInstanceNormalizationQuantization validatorQAsymmS8(qAsymmS8Options, tensorShape, tensorShape);
1452  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
1453 
1454  // test QSymmS8 quantization
1455  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
1456  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
1457  TestInstanceNormalizationQuantization validatorQSymmS8(qSymmS8Options, tensorShape, tensorShape);
1458  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
1459 
1460  // test QSymmS16 quantization
1461  const QuantizerOptions qSymmS16Options(DataType::QSymmS16);
1462  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16Options)->ExportNetwork();
1463  TestInstanceNormalizationQuantization validatorQSymmS16(qSymmS16Options, tensorShape, tensorShape);
1464  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
1465 }
1466 
1467 BOOST_AUTO_TEST_CASE(QuantizeLogSoftmax)
1468 {
1469  class TestLogSoftmaxQuantization : public TestQuantization
1470  {
1471  public:
1472  TestLogSoftmaxQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
1473  : TestQuantization(inputShape, outputShape) {}
1474 
1475  TestLogSoftmaxQuantization(const QuantizerOptions& options,
1476  const TensorShape& inputShape,
1477  const TensorShape& outputShape)
1478  : TestQuantization(options, inputShape, outputShape) {}
1479 
1480  void VisitLogSoftmaxLayer(const IConnectableLayer* layer,
1481  const SoftmaxDescriptor& descriptor,
1482  const char* name = nullptr) override
1483  {
1484  IgnoreUnused(descriptor, name);
1486 
1487  const OffsetScalePair qAsymmU8Params{ 30.0f / g_AsymmU8QuantizationBase, 128 };
1488  const OffsetScalePair qAsymmS8Params { 30.0f / g_AsymmS8QuantizationBase, 0};
1489  const OffsetScalePair qSymmS8Params { 15.0f / g_SymmS8QuantizationBase, 0};
1490  const OffsetScalePair qSymmS16Params{ 15.0f / g_SymmS16QuantizationBase, 0 };
1491 
1492  TestQuantizationParams(info, qAsymmU8Params, qAsymmS8Params, qSymmS8Params, qSymmS16Params);
1493  }
1494  };
1495 
1496  const TensorShape tensorShape{ 1U };
1497  const TensorInfo tensorInfo(tensorShape, DataType::Float32);
1498 
1499  INetworkPtr network = INetwork::Create();
1500 
1501  LogSoftmaxDescriptor descriptor;
1502  descriptor.m_Beta = 1.0f;
1503 
1504  IConnectableLayer* inputLayer = network->AddInputLayer(0);
1505  IConnectableLayer* logSoftmaxLayer = network->AddLogSoftmaxLayer(descriptor);
1506  IConnectableLayer* outputLayer = network->AddOutputLayer(0);
1507 
1508  inputLayer->GetOutputSlot(0).Connect(logSoftmaxLayer->GetInputSlot(0));
1509  logSoftmaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1510 
1511  inputLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1512  logSoftmaxLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1513 
1514  // test QAsymmU8 quantization
1515  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
1516  TestLogSoftmaxQuantization validatorQAsymmU8(tensorShape, tensorShape);
1517  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
1518 
1519  // test QAsymmS8 quantization
1520  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
1521  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
1522  TestLogSoftmaxQuantization validatorQAsymmS8(qAsymmS8Options, tensorShape, tensorShape);
1523  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
1524 
1525  // test QSymmS8 quantization
1526  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
1527  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
1528  TestLogSoftmaxQuantization validatorQSymmS8(qSymmS8Options, tensorShape, tensorShape);
1529  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
1530 
1531  // test QuantisedSymmS16 quantization
1532  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
1533  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
1534  TestLogSoftmaxQuantization validatorQSymmS16(qSymmS16options, tensorShape, tensorShape);
1535  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
1536 }
1537 
1539 {
1540  INetworkPtr network = INetwork::Create();
1541 
1542  // Add the layers
1543  IConnectableLayer* input0 = network->AddInputLayer(0);
1544  IConnectableLayer* softmax = network->AddSoftmaxLayer(descriptor);
1545  IConnectableLayer* output = network->AddOutputLayer(2);
1546 
1547  // Establish connections
1548  input0->GetOutputSlot(0).Connect(softmax->GetInputSlot(0));
1549  softmax->GetOutputSlot(0).Connect(output->GetInputSlot(0));
1550 
1551  // Set TensorInfo
1553  input0->GetOutputSlot(0).SetTensorInfo(info);
1554  softmax->GetOutputSlot(0).SetTensorInfo(info);
1555 
1556  return network;
1557 }
1558 
1559 BOOST_AUTO_TEST_CASE(QuantizeSoftmax)
1560 {
1561  class TestSoftmaxQuantization : public TestQuantization
1562  {
1563  public:
1564  TestSoftmaxQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
1565  : TestQuantization(inputShape, outputShape) {}
1566 
1567  TestSoftmaxQuantization(const QuantizerOptions& options,
1568  const TensorShape& inputShape,
1569  const TensorShape& outputShape)
1570  : TestQuantization(options, inputShape, outputShape) {}
1571 
1572  void VisitSoftmaxLayer(const IConnectableLayer* layer,
1573  const SoftmaxDescriptor& descriptor,
1574  const char* name = nullptr) override
1575  {
1576  IgnoreUnused(descriptor, name);
1578 
1579  // Based off default static range [0.0f, 1.0f]
1580  TestQuantizationParams(info, {1.0f / g_AsymmU8QuantizationBase, 0},
1581  {1.0f / g_AsymmS8QuantizationBase, -128},
1582  {1.0f / g_SymmS8QuantizationBase, 0},
1583  {1.0f / g_SymmS16QuantizationBase, 0});
1584  }
1585  };
1586 
1587  SoftmaxDescriptor descriptor;
1588  descriptor.m_Beta = 1.0f;
1589 
1590  const TensorShape shape{1U};
1591  INetworkPtr network = CreateNetworkWithSoftmaxLayer(descriptor, shape);
1592 
1593  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
1594  TestSoftmaxQuantization validatorQAsymmU8(shape, shape);
1595  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
1596 
1597  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
1598  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
1599  TestSoftmaxQuantization validatorQAsymmS8(qAsymmS8Options, shape, shape);
1600  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
1601 
1602  // test QSymmS8 quantization
1603  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
1604  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
1605  TestSoftmaxQuantization validatorQSymmS8(qSymmS8Options, shape, shape);
1606  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
1607 
1608  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
1609  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
1610  TestSoftmaxQuantization validatorQSymmS16(qSymmS16options, shape, shape);
1611  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
1612 }
1613 
1614 BOOST_AUTO_TEST_CASE(QuantizeStandIn)
1615 {
1616  const TensorShape tensorShape{ 1U };
1617  const TensorInfo tensorInfo(tensorShape, DataType::Float32);
1618 
1619  INetworkPtr network = INetwork::Create();
1620 
1621  StandInDescriptor descriptor;
1622  descriptor.m_NumInputs = 1;
1623  descriptor.m_NumOutputs = 1;
1624 
1625  IConnectableLayer* inputLayer = network->AddInputLayer(0);
1626  IConnectableLayer* standInLayer = network->AddStandInLayer(descriptor);
1627  IConnectableLayer* outputLayer = network->AddOutputLayer(0);
1628 
1629  inputLayer->GetOutputSlot(0).Connect(standInLayer->GetInputSlot(0));
1630  standInLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1631 
1632  inputLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1633  standInLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1634 
1635  // test QAsymmU8 quantization
1636  BOOST_CHECK_THROW(INetworkQuantizer::Create(network.get())->ExportNetwork(),
1638 
1639  // test QAsymmS8 quantization
1640  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
1641  BOOST_CHECK_THROW(INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork(),
1643 
1644  // test QuantisedSymmS16 quantization
1645  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
1646  BOOST_CHECK_THROW(INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork(),
1648 
1649  // test QuantisedSymmS16 quantization
1650  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
1651  BOOST_CHECK_THROW(INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork(),
1653 }
1654 
1656 {
1657  ActivationDescriptor activationDescriptor;
1658  activationDescriptor.m_Function = ActivationFunction::LeakyReLu;
1659  activationDescriptor.m_A = 3.5f;
1660  activationDescriptor.m_B = -10.0f;
1661 
1662  // Add the layers
1663  IConnectableLayer* input0 = network->AddInputLayer(0);
1664  IConnectableLayer* activation = network->AddActivationLayer(activationDescriptor);
1665 
1666  // Establish connections
1667  input0->GetOutputSlot(0).Connect(activation->GetInputSlot(0));
1668 
1669  // Set TensorInfo
1670  input0->GetOutputSlot(0).SetTensorInfo(info);
1671  activation->GetOutputSlot(0).SetTensorInfo(info);
1672 
1673  return activation;
1674 }
1675 
1677  IConnectableLayer* activation,
1678  IConnectableLayer* layerUnderTest,
1679  const TensorInfo& info)
1680 {
1681  // Add the output Layer
1682  IConnectableLayer* output = network->AddOutputLayer(3);
1683 
1684  // Establish connections
1685  activation->GetOutputSlot(0).Connect(layerUnderTest->GetInputSlot(0));
1686  layerUnderTest->GetOutputSlot(0).Connect(output->GetInputSlot(0));
1687 
1688  //Set TensorInfo
1689  layerUnderTest->GetOutputSlot(0).SetTensorInfo(info);
1690 }
1691 
1692 BOOST_AUTO_TEST_CASE(QuantizePermute)
1693 {
1694  class TestPermuteQuantization : public TestLeakyReLuActivationQuantization
1695  {
1696  public:
1697  TestPermuteQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
1698  : TestLeakyReLuActivationQuantization(inputShape, outputShape) {}
1699 
1700  TestPermuteQuantization(const QuantizerOptions& options,
1701  const TensorShape& inputShape,
1702  const TensorShape& outputShape)
1703  : TestLeakyReLuActivationQuantization(options, inputShape, outputShape) {}
1704 
1705  void VisitPermuteLayer(const IConnectableLayer* layer,
1706  const PermuteDescriptor& desc,
1707  const char* name = nullptr) override
1708  {
1709  IgnoreUnused(desc, name);
1710  CheckForwardedQuantizationSettings(layer);
1711  }
1712  };
1713 
1714  INetworkPtr network = INetwork::Create();
1715 
1716  const TensorShape shape{1U};
1718 
1719  IConnectableLayer* activation = CreateStartOfLeakyReluNetwork(network.get(), info);
1720 
1721  // Add the layer under test
1722  PermuteDescriptor desc;
1723  IConnectableLayer* permute = network->AddPermuteLayer(desc);
1724 
1725  CompleteLeakyReluNetwork(network.get(), activation, permute, info);
1726 
1727  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
1728  TestPermuteQuantization validatorQAsymmU8(shape, shape);
1729  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
1730 
1731  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
1732  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
1733  TestPermuteQuantization validatorQAsymmS8(qAsymmS8Options, shape, shape);
1734  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
1735 
1736  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
1737  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
1738  TestPermuteQuantization validatorQSymmS8(qSymmS8Options, shape, shape);
1739  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
1740 
1741  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
1742  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
1743  TestPermuteQuantization validatorQSymmS16(qSymmS16options, shape, shape);
1744  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
1745 }
1746 
1747 BOOST_AUTO_TEST_CASE(QuantizeSpaceToBatch)
1748 {
1749  class TestSpaceToBatchQuantization : public TestLeakyReLuActivationQuantization
1750  {
1751  public:
1752  TestSpaceToBatchQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
1753  : TestLeakyReLuActivationQuantization(inputShape, outputShape) {}
1754 
1755  TestSpaceToBatchQuantization(const QuantizerOptions& options,
1756  const TensorShape& inputShape,
1757  const TensorShape& outputShape)
1758  : TestLeakyReLuActivationQuantization(options, inputShape, outputShape) {}
1759 
1760  void VisitSpaceToBatchNdLayer(const IConnectableLayer* layer,
1761  const SpaceToBatchNdDescriptor& spaceToBatchNdDescriptor,
1762  const char* name = nullptr) override
1763  {
1764  IgnoreUnused(spaceToBatchNdDescriptor, name);
1765  CheckForwardedQuantizationSettings(layer);
1766  }
1767  };
1768 
1769  INetworkPtr network = INetwork::Create();
1770 
1771  const TensorShape shape{1U};
1773 
1774  IConnectableLayer* activation = CreateStartOfLeakyReluNetwork(network.get(), info);
1775 
1776  // Add the layer under test
1777  SpaceToBatchNdDescriptor descriptor;
1778  IConnectableLayer* spaceToBatch = network->AddSpaceToBatchNdLayer(descriptor);
1779 
1780  CompleteLeakyReluNetwork(network.get(), activation, spaceToBatch, info);
1781 
1782  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
1783  TestSpaceToBatchQuantization validatorQAsymmU8(shape, shape);
1784  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
1785 
1786  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
1787  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
1788  TestSpaceToBatchQuantization validatorQAsymmS8(qAsymmS8Options, shape, shape);
1789  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
1790 
1791  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
1792  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
1793  TestSpaceToBatchQuantization validatorQSymmS8(qSymmS8Options, shape, shape);
1794  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
1795 
1796  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
1797  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
1798  TestSpaceToBatchQuantization validatorQSymmS16(qSymmS16options, shape, shape);
1799  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
1800 }
1801 
1802 BOOST_AUTO_TEST_CASE(QuantizeSpaceToDepth)
1803 {
1804  class TestSpaceToDepthQuantization : public TestLeakyReLuActivationQuantization
1805  {
1806  public:
1807  TestSpaceToDepthQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
1808  : TestLeakyReLuActivationQuantization(inputShape, outputShape)
1809  {}
1810 
1811  TestSpaceToDepthQuantization(const QuantizerOptions& options,
1812  const TensorShape& inputShape,
1813  const TensorShape& outputShape)
1814  : TestLeakyReLuActivationQuantization(options, inputShape, outputShape)
1815  {}
1816 
1817  void VisitSpaceToDepthLayer(const IConnectableLayer* layer,
1818  const SpaceToDepthDescriptor&,
1819  const char* = nullptr) override
1820  {
1822  TestQuantizationParams(info,
1823  { 30.0f / g_AsymmU8QuantizationBase, 128 },
1824  { 30.0f / g_AsymmS8QuantizationBase, 0 },
1825  { 15.0f / g_SymmS8QuantizationBase, 0 },
1826  { 15.0f / g_SymmS16QuantizationBase, 0 });
1827  }
1828  };
1829 
1830  INetworkPtr network = INetwork::Create();
1831 
1832  const TensorShape shape{ 1u };
1834 
1835  IConnectableLayer* activation = CreateStartOfLeakyReluNetwork(network.get(), info);
1836  IConnectableLayer* spaceToDepth = network->AddSpaceToDepthLayer(SpaceToDepthDescriptor());
1837 
1838  CompleteLeakyReluNetwork(network.get(), activation, spaceToDepth, info);
1839 
1840  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
1841  TestSpaceToDepthQuantization validatorQAsymmU8(shape, shape);
1842  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
1843 
1844  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
1845  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
1846  TestSpaceToDepthQuantization validatorQAsymmS8(qAsymmS8Options, shape, shape);
1847  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
1848 
1849  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
1850  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
1851  TestSpaceToDepthQuantization validatorQSymmS8(qSymmS8Options, shape, shape);
1852  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
1853 
1854  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
1855  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
1856  TestSpaceToDepthQuantization validatorQSymmS16(qSymmS16options, shape, shape);
1857  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
1858 }
1859 
1860 BOOST_AUTO_TEST_CASE(QuantizePooling2d)
1861 {
1862  class TestPooling2dQuantization : public TestLeakyReLuActivationQuantization
1863  {
1864  public:
1865  TestPooling2dQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
1866  : TestLeakyReLuActivationQuantization(inputShape, outputShape) {}
1867 
1868  TestPooling2dQuantization(const QuantizerOptions& options,
1869  const TensorShape& inputShape,
1870  const TensorShape& outputShape)
1871  : TestLeakyReLuActivationQuantization(options, inputShape, outputShape) {}
1872 
1873  void VisitPooling2dLayer(const IConnectableLayer* layer,
1874  const Pooling2dDescriptor& desc,
1875  const char* name = nullptr) override
1876  {
1877  IgnoreUnused(desc, name);
1878  CheckForwardedQuantizationSettings(layer);
1879  }
1880  };
1881 
1882  auto network = INetwork::Create();
1883 
1884  TensorShape shape{1U};
1886 
1887  Pooling2dDescriptor desc;
1888  ActivationDescriptor activationDescriptor;
1889  activationDescriptor.m_Function = ActivationFunction::LeakyReLu;
1890  activationDescriptor.m_A = 3.5f;
1891  activationDescriptor.m_B = -10.0f;
1892 
1893  // Add the layers
1894  IConnectableLayer* input0 = network->AddInputLayer(0);
1895  IConnectableLayer* activation = network->AddActivationLayer(activationDescriptor);
1896  IConnectableLayer* pooling2d = network->AddPooling2dLayer(desc);
1897  IConnectableLayer* output = network->AddOutputLayer(3);
1898 
1899  // Establish connections
1900  input0->GetOutputSlot(0).Connect(activation->GetInputSlot(0));
1901  activation->GetOutputSlot(0).Connect(pooling2d->GetInputSlot(0));
1902  pooling2d->GetOutputSlot(0).Connect(output->GetInputSlot(0));
1903 
1904  // Set TensorInfo
1905  input0->GetOutputSlot(0).SetTensorInfo(info);
1906  activation->GetOutputSlot(0).SetTensorInfo(info);
1907  pooling2d->GetOutputSlot(0).SetTensorInfo(info);
1908 
1909  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
1910  TestPooling2dQuantization validatorQAsymmU8(shape, shape);
1911  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
1912 
1913  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
1914  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
1915  TestPooling2dQuantization validatorQAsymmS8(qAsymmS8Options, shape, shape);
1916  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
1917 
1918  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
1919  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
1920  TestPooling2dQuantization validatorQSymmS8(qSymmS8Options, shape, shape);
1921  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
1922 
1923  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
1924  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
1925  TestPooling2dQuantization validatorQSymmS16(qSymmS16options, shape, shape);
1926  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
1927 }
1928 
1930 {
1931  class TestConstantQuantization : public TestAdditionQuantization
1932  {
1933  public:
1934  TestConstantQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
1935  : TestAdditionQuantization(inputShape, outputShape) {}
1936 
1937  TestConstantQuantization(const QuantizerOptions& options,
1938  const TensorShape& inputShape,
1939  const TensorShape& outputShape)
1940  : TestAdditionQuantization(options, inputShape, outputShape) {}
1941 
1942  void VisitConstantLayer(const IConnectableLayer* layer,
1943  const ConstTensor& input,
1944  const char* name = nullptr) override
1945  {
1946  IgnoreUnused(input, name);
1948 
1949  // Based off the range of values in the const tensor used for the test: [-2.0f, 6.0f]
1950  TestQuantizationParams(info, {8.0f / g_AsymmU8QuantizationBase, 64},
1951  {8.0f / g_AsymmS8QuantizationBase, -64},
1952  {6.0f / g_SymmS8QuantizationBase, 0},
1953  {6.0f / g_SymmS16QuantizationBase, 0});
1954  }
1955  };
1956 
1957  INetworkPtr network = INetwork::Create();
1958 
1959  // Constant layer data
1960  std::vector<float> data = {-2.0f, -1.0f, 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
1961  const TensorShape shape{1U, 1U, 3U, 3U};
1962  TensorInfo tensorInfo(shape, DataType::Float32);
1963  ConstTensor constantTensor(tensorInfo, data);
1964 
1965  // Add the layers
1966  IConnectableLayer* input = network->AddInputLayer(0);
1967  IConnectableLayer* constant = network->AddConstantLayer(constantTensor);
1968  IConnectableLayer* addition = network->AddAdditionLayer();
1969  IConnectableLayer* output = network->AddOutputLayer(1);
1970 
1971  // Establish connections
1972  input->GetOutputSlot(0).Connect(addition->GetInputSlot(0));
1973  constant->GetOutputSlot(0).Connect(addition->GetInputSlot(1));
1974  addition->GetOutputSlot(0).Connect(output->GetInputSlot(0));
1975 
1976  // Set TensorInfo in the remaining layers
1977  input->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1978  addition->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1979  constant->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1980 
1981  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
1982  TestConstantQuantization validatorQAsymmU8(shape, shape);
1983  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
1984 
1985  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
1986  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
1987  TestConstantQuantization validatorQAsymmS8(qAsymmS8Options, shape, shape);
1988  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
1989 
1990  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
1991  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
1992  TestConstantQuantization validatorQSymmS8(qSymmS8Options, shape, shape);
1993  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
1994 
1995  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
1996  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
1997  TestConstantQuantization validatorQSymmS16(qSymmS16options, shape, shape);
1998  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
1999 }
2000 
2001 BOOST_AUTO_TEST_CASE(QuantizeArgMinMax)
2002 {
2003  class TestArgMinMaxQuantization : public TestQuantization
2004  {
2005  public:
2006  TestArgMinMaxQuantization(const TensorShape& inputShape, const TensorShape& outputShape) :
2007  TestQuantization(inputShape, outputShape) {}
2008 
2009  TestArgMinMaxQuantization(const QuantizerOptions& options,
2010  const TensorShape& inputShape,
2011  const TensorShape& outputShape) :
2012  TestQuantization(options, inputShape, outputShape)
2013  {}
2014 
2015  void VisitInputLayer(const IConnectableLayer* layer,
2016  LayerBindingId id,
2017  const char* name = nullptr) override
2018  {
2019  IgnoreUnused(layer, id, name);
2020  }
2021 
2022  void VisitOutputLayer(const IConnectableLayer* layer,
2023  LayerBindingId id,
2024  const char* name = nullptr) override
2025  {
2026  IgnoreUnused(layer, id, name);
2027  }
2028  void VisitArgMinMaxLayer(const IConnectableLayer* layer,
2029  const ArgMinMaxDescriptor& argMinMaxDescriptor,
2030  const char* name = nullptr) override
2031  {
2032  IgnoreUnused(argMinMaxDescriptor, name);
2033  TensorInfo outputInfo = layer->GetOutputSlot(0).GetTensorInfo();
2034 
2035  TestQuantizationParams(outputInfo,
2036  { 30.0f / g_AsymmU8QuantizationBase, 128 },
2037  { 30.0f / g_AsymmS8QuantizationBase, 0},
2038  { 15.0f / g_SymmS8QuantizationBase, 0},
2039  { 15.0f / g_SymmS16QuantizationBase, 0 });
2040  }
2041  };
2042 
2043  INetworkPtr network = INetwork::Create();
2044 
2045  const TensorShape inputShape{ 1, 1, 1, 5 };
2046  const TensorShape outputShape{ 1, 1, 1 };
2047 
2048  TensorInfo inputInfo(inputShape, DataType::Float32);
2049  TensorInfo outputInfo(outputShape, DataType::Float32);
2050 
2051  // Add the input layers
2052  IConnectableLayer* input = network->AddInputLayer(0);
2053 
2054  // Add the layer under test
2055  ArgMinMaxDescriptor argMinMaxDescriptor;
2056  argMinMaxDescriptor.m_Function = ArgMinMaxFunction::Max;
2057  IConnectableLayer* argMinMaxLayer = network->AddArgMinMaxLayer(argMinMaxDescriptor);
2058 
2059  // Add the output layers
2060  IConnectableLayer* output = network->AddOutputLayer(1);
2061 
2062  // Establish connections
2063  input->GetOutputSlot(0).Connect(argMinMaxLayer->GetInputSlot(0));
2064  argMinMaxLayer->GetOutputSlot(0).Connect(output->GetInputSlot(0));
2065 
2066  // Set tensor info
2067  input->GetOutputSlot(0).SetTensorInfo(inputInfo);
2068  argMinMaxLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2069 
2070  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
2071  TestArgMinMaxQuantization validatorQAsymmU8(inputShape, outputShape);
2072  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
2073 
2074  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
2075  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
2076  TestArgMinMaxQuantization validatorQAsymmS8(qAsymmS8Options, inputShape, outputShape);
2077  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
2078 
2079  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
2080  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
2081  TestArgMinMaxQuantization validatorQSymmS8(qSymmS8Options, inputShape, outputShape);
2082  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
2083 
2084  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
2085  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
2086  TestArgMinMaxQuantization validatorQSymmS16(qSymmS16options, inputShape, outputShape);
2087  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
2088 }
2089 
2090 BOOST_AUTO_TEST_CASE(QuantizeComparison)
2091 {
2092  class TestComparisonQuantization : public TestQuantization
2093  {
2094  public:
2095  TestComparisonQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
2096  : TestQuantization(inputShape, outputShape) {}
2097 
2098  TestComparisonQuantization(const QuantizerOptions& options,
2099  const TensorShape& inputShape,
2100  const TensorShape& outputShape)
2101  : TestQuantization(options, inputShape, outputShape) {}
2102 
2103  void VisitComparisonLayer(const IConnectableLayer* layer,
2104  const ComparisonDescriptor& descriptor,
2105  const char* name = nullptr) override
2106  {
2107  IgnoreUnused(descriptor, name);
2109 
2110  const OffsetScalePair qAsymmU8Params{ 30.0f / g_AsymmU8QuantizationBase, 128 };
2111  const OffsetScalePair qAsymmS8Params { 30.0f / g_AsymmS8QuantizationBase, 0};
2112  const OffsetScalePair qSymmS8Params { 15.0f / g_SymmS8QuantizationBase, 0};
2113  const OffsetScalePair qSymmS16Params{ 15.0f / g_SymmS16QuantizationBase, 0 };
2114 
2115  TestQuantizationParams(info, qAsymmU8Params, qAsymmS8Params, qSymmS8Params, qSymmS16Params);
2116  }
2117  };
2118 
2119  const TensorShape tensorShape{ 1u };
2120  const TensorInfo tensorInfo(tensorShape, DataType::Float32);
2121 
2122  INetworkPtr network = INetwork::Create();
2124 
2125  IConnectableLayer* inputLayer0 = network->AddInputLayer(0);
2126  IConnectableLayer* inputLayer1 = network->AddInputLayer(1);
2127  IConnectableLayer* comparisonLayer = network->AddComparisonLayer(descriptor);
2128  IConnectableLayer* outputLayer = network->AddOutputLayer(0);
2129 
2130  inputLayer0->GetOutputSlot(0).Connect(comparisonLayer->GetInputSlot(0));
2131  inputLayer1->GetOutputSlot(0).Connect(comparisonLayer->GetInputSlot(1));
2132  comparisonLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2133 
2134  inputLayer0->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2135  inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2136  comparisonLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2137 
2138  // test QAsymmU8 quantization
2139  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
2140  TestComparisonQuantization validatorQAsymmU8(tensorShape, tensorShape);
2141  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
2142 
2143  // test QAsymmS8 quantization
2144  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
2145  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
2146  TestComparisonQuantization validatorQAsymmS8(qAsymmS8Options, tensorShape, tensorShape);
2147  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
2148 
2149  // test QSymmS8 quantization
2150  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
2151  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
2152  TestComparisonQuantization validatorQSymmS8(qSymmS8Options, tensorShape, tensorShape);
2153  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
2154 
2155  // test QuantisedSymmS16 quantization
2156  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
2157  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
2158  TestComparisonQuantization validatorQSymmS16(qSymmS16options, tensorShape, tensorShape);
2159  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
2160 }
2161 
2162 BOOST_AUTO_TEST_CASE(QuantizeConcat)
2163 {
2164  class TestConcatQuantization : public TestQuantization
2165  {
2166  public:
2167  TestConcatQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
2168  : TestQuantization(inputShape, outputShape) {}
2169 
2170  TestConcatQuantization(const QuantizerOptions& options,
2171  const TensorShape& inputShape,
2172  const TensorShape& outputShape)
2173  : TestQuantization(options, inputShape, outputShape) {}
2174 
2175  void VisitInputLayer(const IConnectableLayer* layer,
2176  LayerBindingId id,
2177  const char* name = nullptr) override
2178  {
2179  IgnoreUnused(layer, id, name);
2180  }
2181  void VisitOutputLayer(const IConnectableLayer* layer,
2182  LayerBindingId id,
2183  const char* name = nullptr) override
2184  {
2185  IgnoreUnused(layer, id, name);
2186  }
2187  void VisitConcatLayer(const IConnectableLayer* layer,
2188  const OriginsDescriptor& originsDescriptor,
2189  const char* name = nullptr) override
2190  {
2191  IgnoreUnused(originsDescriptor, name);
2192  TensorInfo outputInfo = layer->GetOutputSlot(0).GetTensorInfo();
2193  TestQuantizationParams(
2194  outputInfo, {60.8f / g_AsymmU8QuantizationBase, 65},
2195  {60.8f / g_SymmS8QuantizationBase, -63},
2196  {45.3f / g_SymmS8QuantizationBase, 0},
2197  {45.3f / g_SymmS16QuantizationBase, 0});
2198 
2199  TensorInfo inputInfo0 = layer->GetInputSlot(0).GetConnection()->GetTensorInfo();
2200  TensorInfo inputInfo1 = layer->GetInputSlot(1).GetConnection()->GetTensorInfo();
2201  TensorInfo inputInfo2 = layer->GetInputSlot(2).GetConnection()->GetTensorInfo();
2202 
2203  TestDifferentQuantizationScale(inputInfo0, inputInfo1);
2204  TestDifferentQuantizationScale(inputInfo0, inputInfo2);
2205  TestDifferentQuantizationScale(inputInfo1, inputInfo2);
2206  TestDifferentQuantizationScale(inputInfo0, outputInfo);
2207  }
2208  };
2209 
2210  INetworkPtr network = INetwork::Create();
2211 
2212  IConnectableLayer* input0 = network->AddInputLayer(0);
2213  IConnectableLayer* input1 = network->AddInputLayer(1);
2214  IConnectableLayer* input2 = network->AddInputLayer(2);
2215 
2216  OriginsDescriptor descriptor(3, 1);
2217  IConnectableLayer* concatLayer = network->AddConcatLayer(descriptor);
2218 
2219  IConnectableLayer* output0 = network->AddOutputLayer(3);
2220 
2221  // Establish connections
2222  input0->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(0));
2223  input1->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(1));
2224  input2->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(2));
2225  concatLayer->GetOutputSlot(0).Connect(output0->GetInputSlot(0));
2226 
2227  // Set TensorInfo
2228  const TensorShape shape{1U};
2230 
2231  input0->GetOutputSlot(0).SetTensorInfo(info);
2232  input1->GetOutputSlot(0).SetTensorInfo(info);
2233  input2->GetOutputSlot(0).SetTensorInfo(info);
2234  concatLayer->GetOutputSlot(0).SetTensorInfo(info);
2235 
2236  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
2237  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
2238  INetworkQuantizerPtr quantizerPtrQAsymmU8 = INetworkQuantizer::Create(network.get());
2239  INetworkQuantizerPtr quantizerPtrQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options);
2240  INetworkQuantizerPtr quantizerPtrQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options);
2241  // Override the input ranges
2242  float min = -15.5f;
2243  float max = 45.3f;
2244 
2245  quantizerPtrQAsymmU8->OverrideInputRange(0, (min + 2.1f), (max - 3.2f));
2246  quantizerPtrQAsymmU8->OverrideInputRange(1, (min + 6.7f), max);
2247  quantizerPtrQAsymmU8->OverrideInputRange(2, min, (max - 7.8f));
2248 
2249  quantizerPtrQSymmS8->OverrideInputRange(0, (min + 2.1f), (max - 3.2f));
2250  quantizerPtrQSymmS8->OverrideInputRange(1, (min + 6.7f), max);
2251  quantizerPtrQSymmS8->OverrideInputRange(2, min, (max - 7.8f));
2252 
2253  quantizerPtrQSymmS16->OverrideInputRange(0, (min + 2.1f), (max - 3.2f));
2254  quantizerPtrQSymmS16->OverrideInputRange(1, (min + 6.7f), max);
2255  quantizerPtrQSymmS16->OverrideInputRange(2, min, (max - 7.8f));
2256 
2257  INetworkPtr quantizedNetworkQAsymmU8 = quantizerPtrQAsymmU8->ExportNetwork();
2258  TestConcatQuantization validatorQAsymmU8(shape, shape);
2259  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
2260 
2261  INetworkPtr quantizedNetworkQSymmS8 = quantizerPtrQSymmS8->ExportNetwork();
2262  TestConcatQuantization validatorQSymmS8(qSymmS8Options, shape, shape);
2263  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
2264 
2265  INetworkPtr quantizedNetworkQSymmS16 = quantizerPtrQSymmS16->ExportNetwork();
2266  TestConcatQuantization validatorQSymmS16(qSymmS16options, shape, shape);
2267  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
2268 }
2269 
2270 BOOST_AUTO_TEST_CASE(QuantizeReshape)
2271 {
2272  class TestReshapeQuantization : public TestLeakyReLuActivationQuantization
2273  {
2274  public:
2275  TestReshapeQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
2276  : TestLeakyReLuActivationQuantization(inputShape, outputShape) {}
2277 
2278  TestReshapeQuantization(const QuantizerOptions& options,
2279  const TensorShape& inputShape,
2280  const TensorShape& outputShape)
2281  : TestLeakyReLuActivationQuantization(options, inputShape, outputShape) {}
2282 
2283  virtual void VisitReshapeLayer(const IConnectableLayer* layer,
2284  const ReshapeDescriptor& reshapeDescriptor,
2285  const char* name = nullptr) override
2286  {
2287  IgnoreUnused(reshapeDescriptor, name);
2288  CheckForwardedQuantizationSettings(layer);
2289  }
2290  };
2291 
2292  INetworkPtr network = INetwork::Create();
2293 
2294  const TensorShape shape{1U};
2296 
2297  IConnectableLayer* activation = CreateStartOfLeakyReluNetwork(network.get(), info);
2298 
2299  // Add the layer under test
2300  ReshapeDescriptor descriptor({1, 2, 3, 4});
2301  IConnectableLayer* reshape = network->AddReshapeLayer(descriptor);
2302 
2303  CompleteLeakyReluNetwork(network.get(), activation, reshape, info);
2304 
2305  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
2306  TestReshapeQuantization validatorQAsymmU8(shape, shape);
2307  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
2308 
2309  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
2310  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
2311  TestReshapeQuantization validatorQAsymmS8(qAsymmS8Options, shape, shape);
2312  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
2313 
2314  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
2315  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
2316  TestReshapeQuantization validatorQSymmS8(qSymmS8Options, shape, shape);
2317  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
2318 
2319  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
2320  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
2321  TestReshapeQuantization validatorQSymmS16(qSymmS16options, shape, shape);
2322  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
2323 }
2324 
2325 BOOST_AUTO_TEST_CASE(QuantizeSplitter)
2326 {
2327  class TestSplitterQuantization : public TestLeakyReLuActivationQuantization
2328  {
2329  public:
2330  TestSplitterQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
2331  : TestLeakyReLuActivationQuantization(inputShape, outputShape) {}
2332 
2333  TestSplitterQuantization(const QuantizerOptions& options,
2334  const TensorShape& inputShape,
2335  const TensorShape& outputShape)
2336  : TestLeakyReLuActivationQuantization(options, inputShape, outputShape) {}
2337 
2338  virtual void VisitSplitterLayer(const IConnectableLayer* layer,
2339  const SplitterDescriptor& desc,
2340  const char* name = nullptr)
2341  {
2342  IgnoreUnused(desc, name);
2343  CheckForwardedQuantizationSettings(layer);
2344  }
2345  };
2346 
2347  INetworkPtr network = INetwork::Create();
2348 
2349  const TensorShape shape{3U};
2351 
2352  IConnectableLayer* activation = CreateStartOfLeakyReluNetwork(network.get(), info);
2353 
2354  // Add the layer under test
2355  ViewsDescriptor splitterDesc(2,4);
2356  IConnectableLayer* splitter = network->AddSplitterLayer(splitterDesc);
2357  CompleteLeakyReluNetwork(network.get(), activation, splitter, info);
2358 
2359  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
2360  TestSplitterQuantization validatorQAsymmU8(shape, shape);
2361  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
2362 
2363  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
2364  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
2365  TestSplitterQuantization validatorQAsymmS8(qAsymmS8Options, shape, shape);
2366  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
2367 
2368  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
2369  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
2370  TestSplitterQuantization validatorQSymmS8(qSymmS8Options, shape, shape);
2371  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
2372 
2373  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
2374  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
2375  TestSplitterQuantization validatorQSymmS16(qSymmS16options, shape, shape);
2376  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
2377 }
2378 
2379 BOOST_AUTO_TEST_CASE(QuantizeResize)
2380 {
2381  class TestResizeQuantization : public TestLeakyReLuActivationQuantization
2382  {
2383  public:
2384  TestResizeQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
2385  : TestLeakyReLuActivationQuantization(inputShape, outputShape)
2386  {}
2387 
2388  TestResizeQuantization(const QuantizerOptions& options,
2389  const TensorShape& inputShape,
2390  const TensorShape& outputShape)
2391  : TestLeakyReLuActivationQuantization(options, inputShape, outputShape)
2392  {}
2393 
2394  void VisitResizeLayer(const IConnectableLayer* layer,
2395  const ResizeDescriptor& resizeDescriptor,
2396  const char* name = nullptr) override
2397  {
2398  IgnoreUnused(resizeDescriptor, name);
2399  CheckForwardedQuantizationSettings(layer);
2400  }
2401  };
2402 
2403  INetworkPtr network = INetwork::Create();
2404 
2405  const TensorShape shape{1U};
2407 
2408  IConnectableLayer* activation = CreateStartOfLeakyReluNetwork(network.get(), info);
2409 
2410  // Add the layer under test
2411  ResizeDescriptor descriptor;
2412  descriptor.m_TargetHeight = 3;
2413  descriptor.m_TargetWidth = 3;
2414  IConnectableLayer* resizeLayer = network->AddResizeLayer(descriptor);
2415 
2416  CompleteLeakyReluNetwork(network.get(), activation, resizeLayer, info);
2417 
2418  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
2419  TestResizeQuantization validatorQAsymmU8(shape, shape);
2420  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
2421 
2422  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
2423  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
2424  TestResizeQuantization validatorQAsymmS8(qAsymmS8Options, shape, shape);
2425  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
2426 
2427  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
2428  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
2429  TestResizeQuantization validatorQSymmS8(qSymmS8Options, shape, shape);
2430  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
2431 
2432  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
2433  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
2434  TestResizeQuantization validatorQSymmS16(qSymmS16options, shape, shape);
2435  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
2436 }
2437 
2438 BOOST_AUTO_TEST_CASE(QuantizeStridedSlice)
2439 {
2440  class TestStridedSliceQuantization : public TestLeakyReLuActivationQuantization
2441  {
2442  public:
2443  TestStridedSliceQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
2444  : TestLeakyReLuActivationQuantization(inputShape, outputShape) {}
2445 
2446  TestStridedSliceQuantization(const QuantizerOptions& options,
2447  const TensorShape& inputShape,
2448  const TensorShape& outputShape)
2449  : TestLeakyReLuActivationQuantization(options, inputShape, outputShape) {}
2450 
2451  virtual void VisitStridedSliceLayer(const IConnectableLayer* layer,
2452  const StridedSliceDescriptor& desc,
2453  const char* name = nullptr)
2454  {
2455  IgnoreUnused(desc, name);
2456  CheckForwardedQuantizationSettings(layer);
2457  }
2458  };
2459 
2460  INetworkPtr network = INetwork::Create();
2461 
2462  const TensorShape shape{3U};
2464 
2465  IConnectableLayer* activation = CreateStartOfLeakyReluNetwork(network.get(), info);
2466 
2467  // Add the layer under test
2468  StridedSliceDescriptor stridedSliceDesc;
2469  IConnectableLayer* stridedSlice = network->AddStridedSliceLayer(stridedSliceDesc);
2470 
2471  CompleteLeakyReluNetwork(network.get(), activation, stridedSlice, info);
2472 
2473  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
2474  TestStridedSliceQuantization validatorQAsymmU8(shape, shape);
2475  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
2476 
2477  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
2478  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
2479  TestStridedSliceQuantization validatorQAsymmS8(qAsymmS8Options, shape, shape);
2480  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
2481 
2482  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
2483  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
2484  TestStridedSliceQuantization validatorQSymmS8(qSymmS8Options, shape, shape);
2485  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
2486 
2487  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
2488  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
2489  TestStridedSliceQuantization validatorQSymmS16(qSymmS16options, shape, shape);
2490  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
2491 }
2492 
2493 BOOST_AUTO_TEST_CASE(QuantizeBatchToSpace)
2494 {
2495  class TestBatchToSpaceQuantization : public TestLeakyReLuActivationQuantization
2496  {
2497  public:
2498  TestBatchToSpaceQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
2499  : TestLeakyReLuActivationQuantization(inputShape, outputShape) {}
2500 
2501  TestBatchToSpaceQuantization(const QuantizerOptions& options,
2502  const TensorShape& inputShape,
2503  const TensorShape& outputShape)
2504  : TestLeakyReLuActivationQuantization(options, inputShape, outputShape) {}
2505 
2506  void VisitBatchToSpaceNdLayer(const IConnectableLayer* layer,
2507  const BatchToSpaceNdDescriptor& batchToSpaceNdDescriptor,
2508  const char* name = nullptr) override
2509  {
2510  IgnoreUnused(batchToSpaceNdDescriptor, name);
2511  CheckForwardedQuantizationSettings(layer);
2512  }
2513  };
2514 
2515  INetworkPtr network = INetwork::Create();
2516 
2517  const TensorShape shape{1U};
2519 
2520  IConnectableLayer* activation = CreateStartOfLeakyReluNetwork(network.get(), info);
2521 
2522  // Add the layer under test
2523  BatchToSpaceNdDescriptor descriptor;
2524  IConnectableLayer* batchToSpace = network->AddBatchToSpaceNdLayer(descriptor);
2525 
2526  CompleteLeakyReluNetwork(network.get(), activation, batchToSpace, info);
2527 
2528  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
2529  TestBatchToSpaceQuantization validatorQAsymmU8(shape, shape);
2530  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
2531 
2532  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
2533  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
2534  TestBatchToSpaceQuantization validatorQAsymmS8(qAsymmS8Options, shape, shape);
2535  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
2536 
2537  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
2538  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
2539  TestBatchToSpaceQuantization validatorQSymmS8(qSymmS8Options, shape, shape);
2540  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
2541 
2542  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
2543  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
2544  TestBatchToSpaceQuantization validatorQSymmS16(qSymmS16options, shape, shape);
2545  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
2546 }
2547 
2548 BOOST_AUTO_TEST_CASE(QuantizePrelu)
2549 {
2550  class TestPreluQuantization : public TestQuantization
2551  {
2552  public:
2553  TestPreluQuantization(const TensorShape& inputShape,
2554  const TensorShape& alphaShape,
2555  const TensorShape& outputShape)
2556  : TestQuantization(inputShape, outputShape)
2557  , m_AlphaShape(alphaShape)
2558  {}
2559 
2560  TestPreluQuantization(const QuantizerOptions& options,
2561  const TensorShape& inputShape,
2562  const TensorShape& alphaShape,
2563  const TensorShape& outputShape)
2564  : TestQuantization(options, inputShape, outputShape)
2565  , m_AlphaShape(alphaShape)
2566  {}
2567 
2568  void VisitInputLayer(const IConnectableLayer* layer,
2569  LayerBindingId id,
2570  const char* name = nullptr) override
2571  {
2572  IgnoreUnused(id, name);
2573  const TensorInfo& info = layer->GetOutputSlot(0).GetTensorInfo();
2574 
2575  switch (id)
2576  {
2577  case 0: // Input
2578  BOOST_TEST(m_InputShape == info.GetShape());
2579  break;
2580  case 1: // Alpha
2581  BOOST_TEST(m_AlphaShape == info.GetShape());
2582  break;
2583  default:
2584  throw InvalidArgumentException("Invalid layer binding id for PReLU layer");
2585  }
2586 
2587  // Based off current default [-15.0f, 15.0f]
2588  TestQuantizationParams(info,
2589  { 30.0f / g_AsymmU8QuantizationBase, 128 }, // QASymmU8
2590  { 30.0f / g_AsymmS8QuantizationBase, 0}, // QASymmS8
2591  { 15.0f / g_SymmS8QuantizationBase, 0}, // QSymmS8
2592  { 15.0f / g_SymmS16QuantizationBase, 0 }); // QSymmS16
2593  }
2594 
2595  void VisitOutputLayer(const IConnectableLayer* layer,
2596  LayerBindingId id,
2597  const char* name = nullptr) override
2598  {
2599  IgnoreUnused(id, name);
2600  const TensorInfo& info = layer->GetInputSlot(0).GetConnection()->GetTensorInfo();
2601  BOOST_TEST(m_OutputShape == info.GetShape());
2602  }
2603 
2604  void VisitPreluLayer(const IConnectableLayer* layer,
2605  const char* name = nullptr) override
2606  {
2607  IgnoreUnused(name);
2608  const TensorInfo& info = layer->GetOutputSlot(0).GetTensorInfo();
2609  TestQuantizationParams(info,
2610  { 30.0f / g_AsymmU8QuantizationBase, 128 }, // QASymmU8
2611  { 30.0f / g_AsymmS8QuantizationBase, 0}, // QAsymmS8
2612  { 15.0f / g_SymmS8QuantizationBase, 0}, // QSymmS8
2613  { 15.0f / g_SymmS16QuantizationBase, 0 }); // QSymmS16
2614  }
2615 
2616  private:
2617  TensorShape m_AlphaShape;
2618  };
2619 
2620  INetworkPtr network = INetwork::Create();
2621 
2622  const TensorShape inputShape{ 4, 1, 2 };
2623  const TensorShape alphaShape{ 5, 4, 3, 1 };
2624  const TensorShape outputShape{ 5, 4, 3, 2 };
2625  TensorInfo inputInfo(inputShape, DataType::Float32);
2626  TensorInfo alphaInfo(alphaShape, DataType::Float32);
2627  TensorInfo outputInfo(outputShape, DataType::Float32);
2628 
2629  // Add the input layers
2630  IConnectableLayer* input = network->AddInputLayer(0);
2631  IConnectableLayer* alpha = network->AddInputLayer(1);
2632 
2633  // Add the layer under test
2634  IConnectableLayer* prelu = network->AddPreluLayer("prelu");
2635 
2636  // Add the output layers
2637  IConnectableLayer* output = network->AddOutputLayer(0);
2638 
2639  // Establish connections
2640  input->GetOutputSlot(0).Connect(prelu->GetInputSlot(0));
2641  alpha->GetOutputSlot(0).Connect(prelu->GetInputSlot(1));
2642  prelu->GetOutputSlot(0).Connect(output->GetInputSlot(0));
2643 
2644  // Set tensor info
2645  input->GetOutputSlot(0).SetTensorInfo(inputInfo);
2646  alpha->GetOutputSlot(0).SetTensorInfo(alphaInfo);
2647  prelu->GetOutputSlot(0).SetTensorInfo(outputInfo);
2648 
2649  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
2650  TestPreluQuantization validatorQAsymmU8(inputShape, alphaShape, outputShape);
2651  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
2652 
2653  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
2654  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
2655  TestPreluQuantization validatorQAsymmS8(qAsymmS8Options, inputShape, alphaShape, outputShape);
2656  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
2657 
2658  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
2659  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
2660  TestPreluQuantization validatorQSymmS8(qSymmS8Options, inputShape, alphaShape, outputShape);
2661  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
2662 
2663  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
2664  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
2665  TestPreluQuantization validatorQSymmS16(qSymmS16options, inputShape, alphaShape, outputShape);
2666  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
2667 }
2668 
2670 {
2671  class TestTransposeConvolution2dQuantization : public TestQuantization
2672  {
2673  public:
2674  TestTransposeConvolution2dQuantization(const TensorShape& inputShape, const TensorShape& outputShape) :
2675  TestQuantization(inputShape, outputShape)
2676  {}
2677 
2678  TestTransposeConvolution2dQuantization(const QuantizerOptions& options,
2679  const TensorShape& inputShape,
2680  const TensorShape& outputShape) :
2681  TestQuantization(options, inputShape, outputShape)
2682  {}
2683 
2684  void VisitTransposeConvolution2dLayer(const IConnectableLayer *layer,
2685  const TransposeConvolution2dDescriptor& descriptor,
2686  const ConstTensor& weights,
2687  const Optional<ConstTensor>& biases,
2688  const char *name = nullptr) override
2689  {
2690  IgnoreUnused(descriptor, name);
2691  TestQuantizationOnLayersWithBiases(layer, weights, biases);
2692  }
2693  };
2694 
2695  INetworkPtr network = INetwork::Create();
2696 
2697  TensorShape shape{ 3 };
2699 
2700  std::initializer_list<float> floatData{ -1.0f, 1.5f, 2.0f };
2701  std::vector<float> weightsData(floatData);
2702  ConstTensor weights(info, weightsData);
2703 
2705  descriptor.m_BiasEnabled = useBiases;
2706 
2707  // construct network
2708  IConnectableLayer* input = network->AddInputLayer(0);
2709  Optional<ConstTensor> optionalBiases;
2710  std::vector<float> biasesData(floatData);
2711  if (useBiases)
2712  {
2713  ConstTensor biases(info, biasesData);
2714  optionalBiases = Optional<ConstTensor>(biases);
2715  }
2716  IConnectableLayer* transposeConv2d = network->AddTransposeConvolution2dLayer(descriptor, weights, optionalBiases);
2717  IConnectableLayer* output = network->AddOutputLayer(1);
2718 
2719  input->GetOutputSlot(0).Connect(transposeConv2d->GetInputSlot(0));
2720  transposeConv2d->GetOutputSlot(0).Connect(output->GetInputSlot(0));
2721 
2722  input->GetOutputSlot(0).SetTensorInfo(info);
2723  transposeConv2d->GetOutputSlot(0).SetTensorInfo(info);
2724 
2725  // test QAsymmU8 quantization
2726  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
2727  TestTransposeConvolution2dQuantization validatorQAsymmU8(shape, shape);
2728  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
2729 
2730  //test QAsymmS8 quantization
2731  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
2732  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
2733  TestTransposeConvolution2dQuantization validatorQAsymmS8(qAsymmS8Options, shape, shape);
2734  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
2735 
2736  // test QSymmS8 quantization
2737  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
2738  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
2739  TestTransposeConvolution2dQuantization validatorQSymmS8(qSymmS8Options, shape, shape);
2740  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
2741 
2742  // test QSymmS16 quantization
2743  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
2744  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
2745  TestTransposeConvolution2dQuantization validatorQSymmS16(qSymmS16options, shape, shape);
2746  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
2747 }
2748 
2749 BOOST_AUTO_TEST_CASE(QuantizeTransposeConvolution2d)
2750 {
2752 }
2753 
2754 BOOST_AUTO_TEST_CASE(QuantizeTransposeConvolution2dWithBiases)
2755 {
2757 }
2758 
2759 BOOST_AUTO_TEST_CASE(QuantizeStack)
2760 {
2761  class TestStackQuantization : public TestQuantization
2762  {
2763  public:
2764  TestStackQuantization(const TensorShape& inputShape,
2765  const TensorShape& outputShape)
2766  : TestQuantization(inputShape, outputShape) {}
2767 
2768  TestStackQuantization(const QuantizerOptions& options,
2769  const TensorShape& inputShape,
2770  const TensorShape& outputShape)
2771  : TestQuantization(options, inputShape, outputShape) {}
2772 
2773  void VisitInputLayer(const IConnectableLayer* layer,
2774  LayerBindingId id,
2775  const char* name = nullptr) override
2776  {
2777  IgnoreUnused(layer, id, name);
2778  }
2779  void VisitOutputLayer(const IConnectableLayer* layer,
2780  LayerBindingId id,
2781  const char* name = nullptr) override
2782  {
2783  IgnoreUnused(layer, id, name);
2784  }
2785 
2786  void VisitStackLayer(const IConnectableLayer* layer,
2787  const StackDescriptor& descriptor,
2788  const char* name = nullptr) override
2789  {
2790  IgnoreUnused(descriptor, name);
2791  TensorInfo outputInfo = layer->GetOutputSlot(0).GetTensorInfo();
2792 
2793  TestQuantizationParams(outputInfo,
2794  { 30.0f / g_AsymmU8QuantizationBase, 128 },
2795  { 30.0f / g_AsymmS8QuantizationBase, 0},
2796  { 15.0f / g_SymmS8QuantizationBase, 0},
2797  { 15.0f / g_SymmS16QuantizationBase, 0 });
2798  }
2799  };
2800 
2801  INetworkPtr network = INetwork::Create();
2802 
2803  IConnectableLayer* input0 = network->AddInputLayer(0);
2804  IConnectableLayer* input1 = network->AddInputLayer(1);
2805 
2806  const TensorShape inputShape{ 3, 4, 5 };
2807  const TensorShape outputShape{ 3, 4, 2, 5 };
2808 
2809  StackDescriptor descriptor(2, 2, inputShape);
2810  IConnectableLayer* stackLayer = network->AddStackLayer(descriptor);
2811 
2812  IConnectableLayer* output = network->AddOutputLayer(0);
2813 
2814  input0->GetOutputSlot(0).Connect(stackLayer->GetInputSlot(0));
2815  input1->GetOutputSlot(0).Connect(stackLayer->GetInputSlot(1));
2816  stackLayer->GetOutputSlot(0).Connect(output->GetInputSlot(0));
2817 
2818  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
2819  TestStackQuantization validatorQAsymmU8(inputShape, outputShape);
2820  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
2821 
2822  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
2823  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
2824  TestStackQuantization validatorQAsymmS8(qAsymmS8Options, inputShape, inputShape);
2825  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
2826 
2827  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
2828  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
2829  TestStackQuantization validatorQSymmS8(qSymmS8Options, inputShape, inputShape);
2830  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
2831 
2832  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
2833  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
2834  TestStackQuantization validatorQSymmS16(qSymmS16options, inputShape, outputShape);
2835  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
2836 }
2837 
2838 BOOST_AUTO_TEST_CASE(QuantizeSlice)
2839 {
2840  class TestSliceQuantization : public TestQuantization
2841  {
2842  public:
2843  TestSliceQuantization(const TensorShape& inputShape, const TensorShape& outputShape)
2844  : TestQuantization(inputShape, outputShape)
2845  {}
2846 
2847  TestSliceQuantization(const QuantizerOptions& options,
2848  const TensorShape& inputShape,
2849  const TensorShape& outputShape)
2850  : TestQuantization(options, inputShape, outputShape)
2851  {}
2852 
2853  virtual void VisitSliceLayer(const IConnectableLayer* layer,
2854  const SliceDescriptor& desc,
2855  const char* name = nullptr)
2856  {
2857  IgnoreUnused(desc, name);
2858  const TensorInfo& info = layer->GetOutputSlot(0).GetTensorInfo();
2859 
2860  const OffsetScalePair qAsymmU8Params{ 30.0f / g_AsymmU8QuantizationBase, 128 };
2861  const OffsetScalePair qAsymmS8Params{ 30.0f / g_AsymmS8QuantizationBase, 0 };
2862  const OffsetScalePair qSymmS8Params { 15.0f / g_SymmS8QuantizationBase, 0 };
2863  const OffsetScalePair qSymmS16Params{ 15.0f / g_SymmS16QuantizationBase, 0 };
2864 
2865  TestQuantizationParams(info, qAsymmU8Params, qAsymmS8Params, qSymmS8Params, qSymmS16Params);
2866  }
2867  };
2868 
2869  TensorShape shape{ 3 };
2871 
2872  INetworkPtr network = INetwork::Create();
2873 
2874  IConnectableLayer* inputLayer = network->AddInputLayer(0);
2875  IConnectableLayer* sliceLayer = network->AddSliceLayer(SliceDescriptor());
2876  IConnectableLayer* outputLayer = network->AddOutputLayer(0);
2877 
2878  inputLayer->GetOutputSlot(0).Connect(sliceLayer->GetInputSlot(0));
2879  sliceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2880 
2881  inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2882  sliceLayer->GetOutputSlot(0).SetTensorInfo(info);
2883 
2884  // test QAsymmU8 quantization
2885  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get())->ExportNetwork();
2886  TestSliceQuantization validatorQAsymmU8(shape, shape);
2887  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
2888 
2889  // test QASymmS8 quantization
2890  const QuantizerOptions qAsymmS8Options(DataType::QAsymmS8);
2891  INetworkPtr quantizedNetworkQAsymmS8 = INetworkQuantizer::Create(network.get(), qAsymmS8Options)->ExportNetwork();
2892  TestSliceQuantization validatorQAsymmS8(qAsymmS8Options, shape, shape);
2893  VisitLayersTopologically(quantizedNetworkQAsymmS8.get(), validatorQAsymmS8);
2894 
2895  // test QSymmS8 quantization
2896  const QuantizerOptions qSymmS8Options(DataType::QSymmS8);
2897  INetworkPtr quantizedNetworkQSymmS8 = INetworkQuantizer::Create(network.get(), qSymmS8Options)->ExportNetwork();
2898  TestSliceQuantization validatorQSymmS8(qSymmS8Options, shape, shape);
2899  VisitLayersTopologically(quantizedNetworkQSymmS8.get(), validatorQSymmS8);
2900 
2901  // test QSymmS16 quantization
2902  const QuantizerOptions qSymmS16options(DataType::QSymmS16);
2903  INetworkPtr quantizedNetworkQSymmS16 = INetworkQuantizer::Create(network.get(), qSymmS16options)->ExportNetwork();
2904  TestSliceQuantization validatorQSymmS16(qSymmS16options, shape, shape);
2905  VisitLayersTopologically(quantizedNetworkQSymmS16.get(), validatorQSymmS16);
2906 }
2907 
2908 std::vector<uint8_t> SetupQuantize(float value)
2909 {
2910  armnn::TensorInfo inputInfo({ 1, 2, 2 }, armnn::DataType::Float32);
2911  inputInfo.SetQuantizationScale(1.0f);
2912  inputInfo.SetQuantizationOffset(1);
2913  std::vector<float> input({ value, 0.0f, 0.0f, 1.0f });
2914  const std::vector<float> &inputRef = input;
2915 
2916  auto output = armnnUtils::QuantizedVector<uint8_t>(inputRef,
2917  inputInfo.GetQuantizationScale(),
2918  inputInfo.GetQuantizationOffset());
2919 
2920  return output;
2921 }
2922 
2924 {
2925  BOOST_CHECK_EQUAL(SetupQuantize(std::numeric_limits<float>::infinity())[0], 255);
2926 }
2927 
2928 BOOST_AUTO_TEST_CASE(QuantizeNegativeInf)
2929 {
2930  BOOST_CHECK_EQUAL(SetupQuantize(-1 * std::numeric_limits<float>::infinity())[0], 0);
2931 }
2932 
2933 class TestPreserveType : public TestAdditionQuantization
2934 {
2935 public:
2936  TestPreserveType(const QuantizerOptions& options,
2937  const DataType& dataType,
2938  const TensorShape& inputShape,
2939  const TensorShape& outputShape)
2940  : TestAdditionQuantization(options, inputShape, outputShape)
2941  , m_DataType(dataType)
2942  , m_VisitedQuantizeLayer(false)
2943  , m_VisitedDequantizeLayer(false) {}
2944 
2945  void VisitInputLayer(const IConnectableLayer* layer,
2946  LayerBindingId id,
2947  const char* name = nullptr) override
2948  {
2949  IgnoreUnused(id, name);
2950  const TensorInfo& info = layer->GetOutputSlot(0).GetTensorInfo();
2951  BOOST_TEST(GetDataTypeName(info.GetDataType()) == GetDataTypeName(m_DataType));
2952  BOOST_TEST(m_InputShape == info.GetShape());
2953  }
2954 
2955  void VisitOutputLayer(const IConnectableLayer* layer,
2956  LayerBindingId id,
2957  const char* name = nullptr) override
2958  {
2959  IgnoreUnused(id, name);
2960  const TensorInfo& info = layer->GetInputSlot(0).GetConnection()->GetTensorInfo();
2961  BOOST_TEST(GetDataTypeName(info.GetDataType()) == GetDataTypeName(m_DataType));
2962  BOOST_TEST(m_OutputShape == info.GetShape());
2963  }
2964 
2965  void VisitQuantizeLayer(const IConnectableLayer* layer,
2966  const char* name = nullptr) override
2967  {
2968  IgnoreUnused(layer, name);
2969  m_VisitedQuantizeLayer = true;
2970  }
2971 
2972  void VisitDequantizeLayer(const IConnectableLayer* layer,
2973  const char* name = nullptr) override
2974  {
2975  IgnoreUnused(layer, name);
2976  m_VisitedDequantizeLayer = true;
2977  }
2978 
2979  void CheckQuantizeDequantizeLayerVisited(bool expected)
2980  {
2981  if (expected)
2982  {
2983  BOOST_CHECK(m_VisitedQuantizeLayer);
2984  BOOST_CHECK(m_VisitedDequantizeLayer);
2985  }
2986  else
2987  {
2988  BOOST_CHECK(!m_VisitedQuantizeLayer);
2989  BOOST_CHECK(!m_VisitedDequantizeLayer);
2990  }
2991  }
2992 private:
2993  const DataType m_DataType;
2994  bool m_VisitedQuantizeLayer;
2995  bool m_VisitedDequantizeLayer;
2996 };
2997 
2998 void PreserveTypeTestImpl(const DataType& dataType)
2999 {
3000  INetworkPtr network = INetwork::Create();
3001 
3002  // Add the layers
3003  IConnectableLayer* input0 = network->AddInputLayer(0);
3004  IConnectableLayer* input1 = network->AddInputLayer(1);
3005  IConnectableLayer* addition = network->AddAdditionLayer();
3006  IConnectableLayer* output = network->AddOutputLayer(2);
3007 
3008  input0->GetOutputSlot(0).Connect(addition->GetInputSlot(0));
3009  input1->GetOutputSlot(0).Connect(addition->GetInputSlot(1));
3010  addition->GetOutputSlot(0).Connect(output->GetInputSlot(0));
3011 
3012  const TensorShape shape{1U, 2U, 3U};
3013  const TensorInfo info(shape, dataType);
3014  input0->GetOutputSlot(0).SetTensorInfo(info);
3015  input1->GetOutputSlot(0).SetTensorInfo(info);
3016  addition->GetOutputSlot(0).SetTensorInfo(info);
3017 
3018  QuantizerOptions options = dataType == DataType::Float32 ?
3019  QuantizerOptions(DataType::QAsymmU8, true) : QuantizerOptions(dataType, true);
3020 
3021  INetworkPtr quantizedNetworkQAsymmU8 = INetworkQuantizer::Create(network.get(), options)->ExportNetwork();
3022  TestPreserveType validatorQAsymmU8(options, dataType, shape, shape);
3023  VisitLayersTopologically(quantizedNetworkQAsymmU8.get(), validatorQAsymmU8);
3024  validatorQAsymmU8.CheckQuantizeDequantizeLayerVisited(
3025  dataType == DataType::Float32 || dataType == DataType::Float16);
3026 }
3027 
3028 BOOST_AUTO_TEST_CASE(PreserveTypeFloat32)
3029 {
3031 }
3032 
3033 BOOST_AUTO_TEST_CASE(PreserveTypeQAsymmU8)
3034 {
3036 }
3037 
3038 BOOST_AUTO_TEST_CASE(PreserveTypeQsymm8)
3039 {
3041 }
3042 
3043 BOOST_AUTO_TEST_CASE(PreserveTypeQsymm16)
3044 {
3046 }
3047 
3048 BOOST_AUTO_TEST_CASE(TestConnectionPreservationAfterDynamicQuant)
3049 {
3050  class TestConnectionPreservation : public LayerVisitorBase<VisitorNoThrowPolicy>
3051  {
3052  public:
3053  TestConnectionPreservation(const Graph& graph)
3055  , m_Graph(graph)
3056  {}
3057 
3058  void VisitAdditionLayer(const IConnectableLayer* layer, const char*) override
3059  {
3060  CheckLayerName(layer->GetInputSlot(0).GetConnection()->GetOwningLayerGuid(), "reLU1");
3061  CheckLayerName(layer->GetInputSlot(1).GetConnection()->GetOwningLayerGuid(), "reLU2");
3062  }
3063 
3064  void CheckLayerName(LayerGuid guid, std::string expectedName)
3065  {
3066  bool guidFound = false;
3067  for (Layer* layer : m_Graph)
3068  {
3069  if (layer->GetGuid() == guid)
3070  {
3071  BOOST_CHECK_EQUAL(layer->GetName(), expectedName.c_str());
3072  guidFound = true;
3073  break;
3074  }
3075  }
3076  if (!guidFound)
3077  {
3078  BOOST_FAIL("No layer matching the GUID was found");
3079  }
3080  }
3081 
3082  private:
3083  Graph m_Graph;
3084  };
3085 
3086  INetworkPtr network = INetwork::Create();
3087 
3088  IConnectableLayer* inputLayer = network->AddInputLayer(0,"inputLayer1");
3089  armnn::ActivationDescriptor ReLUDesc;
3091 
3092  IConnectableLayer* reLULayer1 = network->AddActivationLayer(ReLUDesc, "reLU1");
3093  IConnectableLayer* reLULayer2 = network->AddActivationLayer(ReLUDesc, "reLU2");
3094  IConnectableLayer* addLayer1 = network->AddAdditionLayer("addLayer1");
3095  IConnectableLayer* outputLayer = network->AddOutputLayer(0,"outPutLayer1");
3096 
3097  inputLayer->GetOutputSlot(0).Connect(reLULayer1->GetInputSlot(0));
3098  reLULayer1->GetOutputSlot(0).Connect(reLULayer2->GetInputSlot(0));
3099  reLULayer1->GetOutputSlot(0).Connect(addLayer1->GetInputSlot(0));
3100  reLULayer2->GetOutputSlot(0).Connect(addLayer1->GetInputSlot(1));
3101  addLayer1->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
3102 
3103  inputLayer->GetOutputSlot(0).SetTensorInfo(TensorInfo(TensorShape({1, 2, 2, 1}), DataType::Float32));
3104  reLULayer1->GetOutputSlot(0).SetTensorInfo(TensorInfo(TensorShape({1, 2, 2, 1}), DataType::Float32));
3105  reLULayer2->GetOutputSlot(0).SetTensorInfo(TensorInfo(TensorShape({1, 2, 2, 1}), DataType::Float32));
3106  addLayer1->GetOutputSlot(0).SetTensorInfo(TensorInfo(TensorShape({1, 2, 2, 1}), DataType::Float32));
3107 
3108  TestConnectionPreservation visitor1(PolymorphicDowncast<const Network*>(network.get())->GetGraph());
3109  VisitLayersTopologically(network.get(), visitor1);
3110 
3112 
3113  armnn::TensorInfo tensorInfo = GetInputTensorInfo(PolymorphicDowncast<const Network*>(network.get()));
3114 
3115  std::vector<float> inputData({0, 2, 0, 4});
3116  armnn::ConstTensor inputTensor(tensorInfo, inputData.data());
3117 
3118  InputTensors inputTensors;
3119  inputTensors.push_back(std::make_pair(0, inputTensor));
3120  quantizer->Refine(inputTensors);
3121 
3122  INetworkPtr quantNetwork = quantizer->ExportNetwork();
3123 
3124  TestConnectionPreservation visitor2(PolymorphicDowncast<const Network*>(quantNetwork.get())->GetGraph());
3125  VisitLayersTopologically(quantNetwork.get(), visitor2);
3126 }
3127 
3129 } // namespace armnn
BOOST_AUTO_TEST_SUITE(TensorflowLiteParser)
const float g_AsymmU8QuantizationBase
bool m_BiasEnabled
Enable/disable bias.
std::pair< float, int > OffsetScalePair
A ViewsDescriptor for the SplitterLayer.
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
Definition: INetwork.hpp:61
bool m_BiasEnabled
Enable/disable bias.
IConnectableLayer * AddOutputLayer(LayerBindingId id, const char *name=nullptr) override
Adds an output layer to the network.
Definition: Network.cpp:1467
A TransposeConvolution2dDescriptor for the TransposeConvolution2dLayer.
const TensorShape & GetShape() const
Definition: Tensor.hpp:187
A ReshapeDescriptor for the ReshapeLayer.
INetworkPtr CreateNetworkWithActivationLayer(const ActivationDescriptor &descriptor, const TensorShape &shape)
Visitor object for overriding the input range of the quantized input layers in a network.
A ComparisonDescriptor for the ComparisonLayer.
Definition: Descriptors.hpp:73
A Convolution2dDescriptor for the Convolution2dLayer.
INetworkPtr CreateNetworkWithInputOutputLayers()
bool m_BiasEnabled
Enable/disable bias.
const Graph & GetGraph() const
Definition: Network.hpp:34
float m_Beta
Exponentiation value.
virtual IConnectableLayer * AddActivationLayer(const ActivationDescriptor &activationDescriptor, const char *name=nullptr)=0
Adds an activation layer to the network.
const float g_SymmS8QuantizationBase
ArgMinMaxFunction m_Function
Specify if the function is to find Min or Max.
Definition: Descriptors.hpp:65
IConnectableLayer * AddInputLayer(LayerBindingId id, const char *name=nullptr) override
Adds an input layer to the network.
Definition: Network.cpp:1192
std::unique_ptr< class INetworkQuantizer, void(*)(INetworkQuantizer *quantizer)> INetworkQuantizerPtr
Main network class which provides the interface for building up a neural network. ...
Definition: INetwork.hpp:105
std::vector< std::pair< LayerBindingId, class ConstTensor > > InputTensors
Definition: Tensor.hpp:340
std::vector< uint8_t > SetupQuantize(float value)
Copyright (c) 2020 ARM Limited.
void IgnoreUnused(Ts &&...)
INetworkPtr CreateNetworkWithFullyConnectedLayer(const bool biasEnabled, const TensorShape &inputShape, const TensorShape &outputShape)
A SpaceToDepthDescriptor for the SpaceToDepthLayer.
A BatchToSpaceNdDescriptor for the BatchToSpaceNdLayer.
void VisitLayers(const LayerContainer &layerContainer, ILayerVisitor &visitor)
std::pair< float, float > MinMaxRange
int LayerBindingId
Type of identifiers for bindable layers (inputs, outputs).
Definition: Types.hpp:202
virtual void SetTensorInfo(const TensorInfo &tensorInfo)=0
uint32_t m_NumOutputs
Number of output tensors.
constexpr const char * GetDataTypeName(DataType dataType)
Definition: TypesUtils.hpp:180
A ResizeDescriptor for the ResizeLayer.
MinMaxRange GetRange(LayerGuid guid, unsigned int idx) const
Retrieve the Range for a particular output slot on a particular layer.
A StackDescriptor for the StackLayer.
virtual IConnectableLayer * AddOutputLayer(LayerBindingId id, const char *name=nullptr)=0
Adds an output layer to the network.
void VisitLayersTopologically(const INetwork *inputNetwork, ILayerVisitor &visitor)
DataType
Definition: Types.hpp:32
IConnectableLayer * CreateStartOfLeakyReluNetwork(INetwork *network, const TensorInfo &info)
#define ARMNN_ASSERT_MSG(COND, MSG)
Definition: Assert.hpp:15
int32_t GetQuantizationOffset() const
Definition: Tensor.cpp:469
An ArgMinMaxDescriptor for ArgMinMaxLayer.
Definition: Descriptors.hpp:51
float GetQuantizationScale() const
Definition: Tensor.cpp:452
DataType GetDataType() const
Definition: Tensor.hpp:194
An OriginsDescriptor for the ConcatLayer.
bool has_value() const noexcept
Definition: Optional.hpp:53
std::unordered_map< LayerGuid, MinMaxRanges > MinMaxRangeMap
A FullyConnectedDescriptor for the FullyConnectedLayer.
virtual LayerGuid GetGuid() const =0
Returns the unique id of the layer.
bool m_BiasEnabled
Enable/disable bias.
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
Definition: Tensor.hpp:314
bool HasRanges(LayerGuid guid) const
Query that there is an entry for a layer.
void TestQuantizeDepthwiseConvolution2d(bool useBiases)
std::vector< MinMaxRange > MinMaxRanges
void SetQuantizationScale(float scale)
Definition: Tensor.cpp:464
A StandInDescriptor for the StandIn layer.
BOOST_AUTO_TEST_CASE(CheckConvolution2dLayer)
An ActivationDescriptor for the ActivationLayer.
Definition: Descriptors.hpp:20
const TensorInfo & GetInfo() const
Definition: Tensor.hpp:282
min(a, max(b, input)) ReLu1 & ReLu6.
uint32_t m_TargetHeight
Target height value.
A SliceDescriptor for the SliceLayer.
Visitor base class with empty implementations.
const float g_TestTolerance
void ValidateFullyConnectedLayer(const bool biasEnabled)
const float g_SymmS16QuantizationBase
Private implementation of INetwork.
Definition: Network.hpp:28
bool IsEmpty() const
Query function to check that the RangeTracker is empty.
A SpaceToBatchNdDescriptor for the SpaceToBatchNdLayer.
float m_A
Alpha upper bound value used by the activation functions. (BoundedReLu, Linear, TanH, Elu).
Definition: Descriptors.hpp:45
BOOST_AUTO_TEST_SUITE_END()
std::pair< float, float > MinMaxRange
void QuantizeConstant(const srcType *src, uint8_t *dst, size_t numElements, float &scale, int &offset)
IConnectableLayer * AddAdditionLayer(const char *name=nullptr) override
Adds an addition layer to the network.
Definition: Network.cpp:1457
uint32_t m_NumInputs
Number of input tensors.
void TestQuantizeConvolution2d(bool useBiases)
void CompleteLeakyReluNetwork(INetwork *network, IConnectableLayer *activation, IConnectableLayer *layerUnderTest, const TensorInfo &info)
virtual const IInputSlot & GetInputSlot(unsigned int index) const =0
Get a const input slot handle by slot index.
virtual const IOutputSlot * GetConnection() const =0
A StridedSliceDescriptor for the StridedSliceLayer.
virtual const TensorInfo & GetTensorInfo() const =0
virtual const IOutputSlot & GetOutputSlot(unsigned int index) const =0
Get the const output slot handle by slot index.
virtual const char * GetName() const =0
Returns the name of the layer.
InputLayersAccessor GetInputLayers() const
Returns a wrapper object with begin(), end() methods to iterate over the input layers in a range-base...
Definition: Graph.hpp:185
std::unique_ptr< INetwork, void(*)(INetwork *network)> INetworkPtr
Definition: INetwork.hpp:101
INetworkPtr CreateNetworkWithSoftmaxLayer(const SoftmaxDescriptor &descriptor, const TensorShape &shape)
virtual int Connect(IInputSlot &destination)=0
virtual LayerGuid GetOwningLayerGuid() const =0
void PreserveTypeTestImpl(const DataType &dataType)
A Pooling2dDescriptor for the Pooling2dLayer.
An InstanceNormalizationDescriptor for InstanceNormalizationLayer.
static INetworkPtr Create(NetworkOptions networkOptions={})
Definition: Network.cpp:46
virtual IConnectableLayer * AddInputLayer(LayerBindingId id, const char *name=nullptr)=0
Adds an input layer to the network.
float m_B
Beta lower bound value used by the activation functions. (BoundedReLu, Linear, TanH).
Definition: Descriptors.hpp:47
A SoftmaxDescriptor for the SoftmaxLayer.
TensorInfo GetInputTensorInfo(const Network *network)
ActivationFunction m_Function
The activation function to use (Sigmoid, TanH, Linear, ReLu, BoundedReLu, SoftReLu, LeakyReLu, Abs, Sqrt, Square, Elu).
Definition: Descriptors.hpp:43
void TestQuantizeTransposeConvolution2d(bool useBiases)
const float g_AsymmS8QuantizationBase
A DepthwiseConvolution2dDescriptor for the DepthwiseConvolution2dLayer.
static INetworkQuantizerPtr Create(INetwork *inputNetwork, const QuantizerOptions &options=QuantizerOptions())
Create Quantizer object wrapped in unique_ptr.
A FillDescriptor for the FillLayer.
A BatchNormalizationDescriptor for the BatchNormalizationLayer.
A PermuteDescriptor for the PermuteLayer.