ArmNN
 21.05
FullyConnected.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 <boost/test/unit_test.hpp>
8 #include "../TfLiteParser.hpp"
9 
10 #include <string>
11 
12 BOOST_AUTO_TEST_SUITE(TensorflowLiteParser)
13 
14 struct FullyConnectedFixture : public ParserFlatbuffersFixture
15 {
16  explicit FullyConnectedFixture(const std::string& inputShape,
17  const std::string& outputShape,
18  const std::string& filterShape,
19  const std::string& filterData,
20  const std::string biasShape = "",
21  const std::string biasData = "")
22  {
23  std::string inputTensors = "[ 0, 2 ]";
24  std::string biasTensor = "";
25  std::string biasBuffer = "";
26  if (biasShape.size() > 0 && biasData.size() > 0)
27  {
28  inputTensors = "[ 0, 2, 3 ]";
29  biasTensor = R"(
30  {
31  "shape": )" + biasShape + R"( ,
32  "type": "INT32",
33  "buffer": 3,
34  "name": "biasTensor",
35  "quantization": {
36  "min": [ 0.0 ],
37  "max": [ 255.0 ],
38  "scale": [ 1.0 ],
39  "zero_point": [ 0 ],
40  }
41  } )";
42  biasBuffer = R"(
43  { "data": )" + biasData + R"(, }, )";
44  }
45  m_JsonString = R"(
46  {
47  "version": 3,
48  "operator_codes": [ { "builtin_code": "FULLY_CONNECTED" } ],
49  "subgraphs": [ {
50  "tensors": [
51  {
52  "shape": )" + inputShape + R"(,
53  "type": "UINT8",
54  "buffer": 0,
55  "name": "inputTensor",
56  "quantization": {
57  "min": [ 0.0 ],
58  "max": [ 255.0 ],
59  "scale": [ 1.0 ],
60  "zero_point": [ 0 ],
61  }
62  },
63  {
64  "shape": )" + outputShape + R"(,
65  "type": "UINT8",
66  "buffer": 1,
67  "name": "outputTensor",
68  "quantization": {
69  "min": [ 0.0 ],
70  "max": [ 511.0 ],
71  "scale": [ 2.0 ],
72  "zero_point": [ 0 ],
73  }
74  },
75  {
76  "shape": )" + filterShape + R"(,
77  "type": "UINT8",
78  "buffer": 2,
79  "name": "filterTensor",
80  "quantization": {
81  "min": [ 0.0 ],
82  "max": [ 255.0 ],
83  "scale": [ 1.0 ],
84  "zero_point": [ 0 ],
85  }
86  }, )" + biasTensor + R"(
87  ],
88  "inputs": [ 0 ],
89  "outputs": [ 1 ],
90  "operators": [
91  {
92  "opcode_index": 0,
93  "inputs": )" + inputTensors + R"(,
94  "outputs": [ 1 ],
95  "builtin_options_type": "FullyConnectedOptions",
96  "builtin_options": {
97  "fused_activation_function": "NONE"
98  },
99  "custom_options_format": "FLEXBUFFERS"
100  }
101  ],
102  } ],
103  "buffers" : [
104  { },
105  { },
106  { "data": )" + filterData + R"(, }, )"
107  + biasBuffer + R"(
108  ]
109  }
110  )";
111  SetupSingleInputSingleOutput("inputTensor", "outputTensor");
112  }
113 };
114 
115 struct FullyConnectedWithNoBiasFixture : FullyConnectedFixture
116 {
117  FullyConnectedWithNoBiasFixture()
118  : FullyConnectedFixture("[ 1, 4, 1, 1 ]", // inputShape
119  "[ 1, 1 ]", // outputShape
120  "[ 1, 4 ]", // filterShape
121  "[ 2, 3, 4, 5 ]") // filterData
122  {}
123 };
124 
125 BOOST_FIXTURE_TEST_CASE(FullyConnectedWithNoBias, FullyConnectedWithNoBiasFixture)
126 {
127  RunTest<2, armnn::DataType::QAsymmU8>(
128  0,
129  { 10, 20, 30, 40 },
130  { 400/2 });
131 }
132 
133 struct FullyConnectedWithBiasFixture : FullyConnectedFixture
134 {
135  FullyConnectedWithBiasFixture()
136  : FullyConnectedFixture("[ 1, 4, 1, 1 ]", // inputShape
137  "[ 1, 1 ]", // outputShape
138  "[ 1, 4 ]", // filterShape
139  "[ 2, 3, 4, 5 ]", // filterData
140  "[ 1 ]", // biasShape
141  "[ 10, 0, 0, 0 ]" ) // biasData
142  {}
143 };
144 
145 BOOST_FIXTURE_TEST_CASE(ParseFullyConnectedWithBias, FullyConnectedWithBiasFixture)
146 {
147  RunTest<2, armnn::DataType::QAsymmU8>(
148  0,
149  { 10, 20, 30, 40 },
150  { (400+10)/2 });
151 }
152 
153 struct FullyConnectedWithBiasMultipleOutputsFixture : FullyConnectedFixture
154 {
155  FullyConnectedWithBiasMultipleOutputsFixture()
156  : FullyConnectedFixture("[ 1, 4, 2, 1 ]", // inputShape
157  "[ 2, 1 ]", // outputShape
158  "[ 1, 4 ]", // filterShape
159  "[ 2, 3, 4, 5 ]", // filterData
160  "[ 1 ]", // biasShape
161  "[ 10, 0, 0, 0 ]" ) // biasData
162  {}
163 };
164 
165 BOOST_FIXTURE_TEST_CASE(FullyConnectedWithBiasMultipleOutputs, FullyConnectedWithBiasMultipleOutputsFixture)
166 {
167  RunTest<2, armnn::DataType::QAsymmU8>(
168  0,
169  { 1, 2, 3, 4, 10, 20, 30, 40 },
170  { (40+10)/2, (400+10)/2 });
171 }
172 
173 struct DynamicFullyConnectedWithBiasMultipleOutputsFixture : FullyConnectedFixture
174 {
175  DynamicFullyConnectedWithBiasMultipleOutputsFixture()
176  : FullyConnectedFixture("[ 1, 4, 2, 1 ]", // inputShape
177  "[ ]", // outputShape
178  "[ 1, 4 ]", // filterShape
179  "[ 2, 3, 4, 5 ]", // filterData
180  "[ 1 ]", // biasShape
181  "[ 10, 0, 0, 0 ]" ) // biasData
182  { }
183 };
184 
186  DynamicFullyConnectedWithBiasMultipleOutputs,
187  DynamicFullyConnectedWithBiasMultipleOutputsFixture)
188 {
189  RunTest<2,
191  armnn::DataType::QAsymmU8>(0,
192  { { "inputTensor", { 1, 2, 3, 4, 10, 20, 30, 40} } },
193  { { "outputTensor", { (40+10)/2, (400+10)/2 } } },
194  true);
195 }
196 
197 
198 struct FullyConnectedNonConstWeightsFixture : public ParserFlatbuffersFixture
199 {
200  explicit FullyConnectedNonConstWeightsFixture(const std::string& inputShape,
201  const std::string& outputShape,
202  const std::string& filterShape,
203  const std::string biasShape = "")
204  {
205  std::string inputTensors = "[ 0, 1 ]";
206  std::string biasTensor = "";
207  std::string biasBuffer = "";
208  std::string outputs = "2";
209  if (biasShape.size() > 0)
210  {
211  inputTensors = "[ 0, 1, 2 ]";
212  biasTensor = R"(
213  {
214  "shape": )" + biasShape + R"(,
215  "type": "INT32",
216  "buffer": 2,
217  "name": "bias",
218  "quantization": {
219  "scale": [ 1.0 ],
220  "zero_point": [ 0 ],
221  "details_type": 0,
222  "quantized_dimension": 0
223  },
224  "is_variable": true
225  }, )";
226 
227  biasBuffer = R"(,{ "data": [] } )";
228  outputs = "3";
229  }
230  m_JsonString = R"(
231  {
232  "version": 3,
233  "operator_codes": [
234  {
235  "builtin_code": "FULLY_CONNECTED",
236  "version": 1
237  }
238  ],
239  "subgraphs": [
240  {
241  "tensors": [
242  {
243  "shape": )" + inputShape + R"(,
244  "type": "INT8",
245  "buffer": 0,
246  "name": "input_0",
247  "quantization": {
248  "scale": [ 1.0 ],
249  "zero_point": [ 0 ],
250  "details_type": 0,
251  "quantized_dimension": 0
252  },
253  },
254  {
255  "shape": )" + filterShape + R"(,
256  "type": "INT8",
257  "buffer": 1,
258  "name": "weights",
259  "quantization": {
260  "scale": [ 1.0 ],
261  "zero_point": [ 0 ],
262  "details_type": 0,
263  "quantized_dimension": 0
264  },
265  },
266  )" + biasTensor + R"(
267  {
268  "shape": )" + outputShape + R"(,
269  "type": "INT8",
270  "buffer": 0,
271  "name": "output",
272  "quantization": {
273  "scale": [
274  2.0
275  ],
276  "zero_point": [
277  0
278  ],
279  "details_type": 0,
280  "quantized_dimension": 0
281  },
282  }
283  ],
284  "inputs": )" + inputTensors + R"(,
285  "outputs": [ )" + outputs + R"( ],
286  "operators": [
287  {
288  "opcode_index": 0,
289  "inputs": )" + inputTensors + R"(,
290  "outputs": [ )" + outputs + R"( ],
291  "builtin_options_type": "FullyConnectedOptions",
292  "builtin_options": {
293  "fused_activation_function": "NONE",
294  "weights_format": "DEFAULT",
295  "keep_num_dims": false,
296  "asymmetric_quantize_inputs": false
297  },
298  "custom_options_format": "FLEXBUFFERS"
299  }
300  ]
301  }
302  ],
303  "description": "ArmnnDelegate: FullyConnected Operator Model",
304  "buffers": [
305  {
306  "data": []
307  },
308  {
309  "data": []
310  }
311  )" + biasBuffer + R"(
312  ]
313  }
314  )";
315  Setup();
316  }
317 };
318 
319 struct FullyConnectedNonConstWeights : FullyConnectedNonConstWeightsFixture
320 {
321  FullyConnectedNonConstWeights()
322  : FullyConnectedNonConstWeightsFixture("[ 1, 4, 1, 1 ]", // inputShape
323  "[ 1, 1 ]", // outputShape
324  "[ 1, 4 ]", // filterShape
325  "[ 1 ]" ) // biasShape
326 
327  {}
328 };
329 
330 BOOST_FIXTURE_TEST_CASE(ParseFullyConnectedNonConstWeights, FullyConnectedNonConstWeights)
331 {
332  RunTest<2, armnn::DataType::QAsymmS8,
334  armnn::DataType::QAsymmS8>(
335  0,
336  {{{"input_0", { 1, 2, 3, 4 }},{"weights", { 2, 3, 4, 5 }}}},
337  {{"bias", { 10 }}},
338  {{"output", { 25 }}});
339 }
340 
341 struct FullyConnectedNonConstWeightsNoBias : FullyConnectedNonConstWeightsFixture
342 {
343  FullyConnectedNonConstWeightsNoBias()
344  : FullyConnectedNonConstWeightsFixture("[ 1, 4, 1, 1 ]", // inputShape
345  "[ 1, 1 ]", // outputShape
346  "[ 1, 4 ]") // filterShape
347 
348  {}
349 };
350 
351 BOOST_FIXTURE_TEST_CASE(ParseFullyConnectedNonConstWeightsNoBias, FullyConnectedNonConstWeightsNoBias)
352 {
353  RunTest<2, armnn::DataType::QAsymmS8,
354  armnn::DataType::QAsymmS8>(
355  0,
356  {{{"input_0", { 1, 2, 3, 4 }},{"weights", { 2, 3, 4, 5 }}}},
357  {{"output", { 20 }}});
358 }
359 
BOOST_AUTO_TEST_SUITE(TensorflowLiteParser)
BOOST_AUTO_TEST_SUITE_END()
BOOST_FIXTURE_TEST_CASE(MatMul, MatMulFixture)
void SetupSingleInputSingleOutput(const std::string &inputName, const std::string &outputName)