blob: 2a7b4951b7f76235f69dc6590d85704dd2c40087 [file] [log] [blame]
surmeh01bceff2f2018-03-29 16:29:27 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// See LICENSE file in the project root for full license information.
4//
5
6#include <boost/test/unit_test.hpp>
7#include "armnnTfParser/ITfParser.hpp"
8#include "ParserPrototxtFixture.hpp"
9#include "Runtime.hpp"
10#include "Network.hpp"
11#include "Graph.hpp"
12
13BOOST_AUTO_TEST_SUITE(TensorflowParser)
14
15// In Tensorflow fully connected layers are expressed as a MatMul followed by an Add.
16// The TfParser must detect this case and convert them to a FullyConnected layer.
17struct FullyConnectedFixture : public ParserPrototxtFixture<armnnTfParser::ITfParser>
18{
19 FullyConnectedFixture()
20 {
21 // input = tf.placeholder(tf.float32, [1, 1], "input")
22 // weights = tf.constant([2], tf.float32, [1, 1])
23 // matmul = tf.matmul(input, weights)
24 // bias = tf.constant([1], tf.float32)
25 // output = tf.add(matmul, bias, name="output")
26 m_Prototext = R"(
27node {
28 name: "input"
29 op: "Placeholder"
30 attr {
31 key: "dtype"
32 value {
33 type: DT_FLOAT
34 }
35 }
36 attr {
37 key: "shape"
38 value {
39 shape {
40 dim {
41 size: 1
42 }
43 dim {
44 size: 1
45 }
46 }
47 }
48 }
49}
50node {
51 name: "Const"
52 op: "Const"
53 attr {
54 key: "dtype"
55 value {
56 type: DT_FLOAT
57 }
58 }
59 attr {
60 key: "value"
61 value {
62 tensor {
63 dtype: DT_FLOAT
64 tensor_shape {
65 dim {
66 size: 1
67 }
68 dim {
69 size: 1
70 }
71 }
72 float_val: 2.0
73 }
74 }
75 }
76}
77node {
78 name: "MatMul"
79 op: "MatMul"
80 input: "input"
81 input: "Const"
82 attr {
83 key: "T"
84 value {
85 type: DT_FLOAT
86 }
87 }
88 attr {
89 key: "transpose_a"
90 value {
91 b: false
92 }
93 }
94 attr {
95 key: "transpose_b"
96 value {
97 b: false
98 }
99 }
100}
101node {
102 name: "Const_1"
103 op: "Const"
104 attr {
105 key: "dtype"
106 value {
107 type: DT_FLOAT
108 }
109 }
110 attr {
111 key: "value"
112 value {
113 tensor {
114 dtype: DT_FLOAT
115 tensor_shape {
116 dim {
117 size: 1
118 }
119 }
120 float_val: 1.0
121 }
122 }
123 }
124}
125node {
126 name: "output"
127 op: "Add"
128 input: "MatMul"
129 input: "Const_1"
130 attr {
131 key: "T"
132 value {
133 type: DT_FLOAT
134 }
135 }
136}
137 )";
138 SetupSingleInputSingleOutput({ 1, 1 }, "input", "output");
139 }
140};
141
142BOOST_FIXTURE_TEST_CASE(FullyConnected, FullyConnectedFixture)
143{
144 RunTest<1>({ 3 }, { 7 });
145}
146
147// Similar to FullyConnectedFixture, but this time the MatMul's output is used by two Adds. This should result
148// in two FullyConnected layers being created.
149// I
150// |
151// M -- C
152// / \'
153// C-- A A -- C
154// \ /
155// A
156struct MatMulUsedInTwoFcFixture : public ParserPrototxtFixture<armnnTfParser::ITfParser>
157{
158 MatMulUsedInTwoFcFixture()
159 {
160 m_Prototext = R"(
161node {
162 name: "input"
163 op: "Placeholder"
164 attr {
165 key: "dtype"
166 value {
167 type: DT_FLOAT
168 }
169 }
170 attr {
171 key: "shape"
172 value {
173 shape {
174 dim {
175 size: 1
176 }
177 dim {
178 size: 1
179 }
180 }
181 }
182 }
183}
184node {
185 name: "Const"
186 op: "Const"
187 attr {
188 key: "dtype"
189 value {
190 type: DT_FLOAT
191 }
192 }
193 attr {
194 key: "value"
195 value {
196 tensor {
197 dtype: DT_FLOAT
198 tensor_shape {
199 dim {
200 size: 1
201 }
202 dim {
203 size: 1
204 }
205 }
206 float_val: 2.0
207 }
208 }
209 }
210}
211node {
212 name: "MatMul"
213 op: "MatMul"
214 input: "input"
215 input: "Const"
216 attr {
217 key: "T"
218 value {
219 type: DT_FLOAT
220 }
221 }
222 attr {
223 key: "transpose_a"
224 value {
225 b: false
226 }
227 }
228 attr {
229 key: "transpose_b"
230 value {
231 b: false
232 }
233 }
234}
235node {
236 name: "Const_1"
237 op: "Const"
238 attr {
239 key: "dtype"
240 value {
241 type: DT_FLOAT
242 }
243 }
244 attr {
245 key: "value"
246 value {
247 tensor {
248 dtype: DT_FLOAT
249 tensor_shape {
250 dim {
251 size: 1
252 }
253 }
254 float_val: 5.0
255 }
256 }
257 }
258}
259node {
260 name: "Const_2"
261 op: "Const"
262 attr {
263 key: "dtype"
264 value {
265 type: DT_FLOAT
266 }
267 }
268 attr {
269 key: "value"
270 value {
271 tensor {
272 dtype: DT_FLOAT
273 tensor_shape {
274 dim {
275 size: 1
276 }
277 }
278 float_val: 15.0
279 }
280 }
281 }
282}
283node {
284 name: "Add"
285 op: "Add"
286 input: "MatMul"
287 input: "Const_1"
288 attr {
289 key: "T"
290 value {
291 type: DT_FLOAT
292 }
293 }
294}
295node {
296 name: "Add_1"
297 op: "Add"
298 input: "MatMul"
299 input: "Const_2"
300 attr {
301 key: "T"
302 value {
303 type: DT_FLOAT
304 }
305 }
306}
307node {
308 name: "output"
309 op: "Add"
310 input: "Add"
311 input: "Add_1"
312 attr {
313 key: "T"
314 value {
315 type: DT_FLOAT
316 }
317 }
318}
319 )";
320 SetupSingleInputSingleOutput({ 1, 1 }, "input", "output");
321 }
322};
323
324BOOST_FIXTURE_TEST_CASE(MatMulUsedInTwoFc, MatMulUsedInTwoFcFixture)
325{
326 RunTest<1>({ 3 }, { 32 });
327 // Ideally we would check here that the armnn network has 5 layers:
328 // Input, 2 x FullyConnected (biased), Add and Output.
329 // This would make sure the parser hasn't incorrectly added some unconnected layers corresponding to the MatMul
330}
331
332// Similar to MatMulUsedInTwoFc, but this time the Adds are 'staggered' (see diagram), which means that only one
333// FullyConnected layer can be created (the other should just be an Add).
334// I
335// |
336// M -- C1
337// / \'
338// C2 -- A |
339// \ /
340// A
341struct MatMulUsedInTwoFcStaggeredFixture : public ParserPrototxtFixture<armnnTfParser::ITfParser>
342{
343 MatMulUsedInTwoFcStaggeredFixture()
344 {
345 // input = tf.placeholder(tf.float32, shape=[1,1], name = "input")
346 // const1 = tf.constant([17], tf.float32, [1,1])
347 // mul = tf.matmul(input, const1)
348 // const2 = tf.constant([7], tf.float32, [1])
349 // fc = tf.add(mul, const2)
350 // output = tf.add(mul, fc, name="output")
351 m_Prototext = R"(
352node {
353 name: "input"
354 op: "Placeholder"
355 attr {
356 key: "dtype"
357 value {
358 type: DT_FLOAT
359 }
360 }
361 attr {
362 key: "shape"
363 value {
364 shape {
365 dim {
366 size: 1
367 }
368 dim {
369 size: 1
370 }
371 }
372 }
373 }
374}
375node {
376 name: "Const"
377 op: "Const"
378 attr {
379 key: "dtype"
380 value {
381 type: DT_FLOAT
382 }
383 }
384 attr {
385 key: "value"
386 value {
387 tensor {
388 dtype: DT_FLOAT
389 tensor_shape {
390 dim {
391 size: 1
392 }
393 dim {
394 size: 1
395 }
396 }
397 float_val: 17.0
398 }
399 }
400 }
401}
402node {
403 name: "MatMul"
404 op: "MatMul"
405 input: "input"
406 input: "Const"
407 attr {
408 key: "T"
409 value {
410 type: DT_FLOAT
411 }
412 }
413 attr {
414 key: "transpose_a"
415 value {
416 b: false
417 }
418 }
419 attr {
420 key: "transpose_b"
421 value {
422 b: false
423 }
424 }
425}
426node {
427 name: "Const_1"
428 op: "Const"
429 attr {
430 key: "dtype"
431 value {
432 type: DT_FLOAT
433 }
434 }
435 attr {
436 key: "value"
437 value {
438 tensor {
439 dtype: DT_FLOAT
440 tensor_shape {
441 dim {
442 size: 1
443 }
444 }
445 float_val: 7.0
446 }
447 }
448 }
449}
450node {
451 name: "Add"
452 op: "Add"
453 input: "MatMul"
454 input: "Const_1"
455 attr {
456 key: "T"
457 value {
458 type: DT_FLOAT
459 }
460 }
461}
462node {
463 name: "output"
464 op: "Add"
465 input: "MatMul"
466 input: "Add"
467 attr {
468 key: "T"
469 value {
470 type: DT_FLOAT
471 }
472 }
473}
474 )";
475 SetupSingleInputSingleOutput({ 1, 1 }, "input", "output");
476 }
477};
478
479BOOST_FIXTURE_TEST_CASE(MatMulUsedInTwoFcStaggered, MatMulUsedInTwoFcStaggeredFixture)
480{
481 RunTest<1>({ 2 }, { 75 });
482 // Ideally we would check here that the armnn network has 5 layers:
483 // Input, FullyConnected (biased), FullyConnected (non biased), Add and Output.
484}
485
486// A MatMul in isolation, not connected to an add. Should result in a non-biased FullyConnected layer.
487struct MatMulFixture : public ParserPrototxtFixture<armnnTfParser::ITfParser>
488{
489 MatMulFixture()
490 {
491 // input = tf.placeholder(tf.float32, shape = [1, 1], name = "input")
492 // const = tf.constant([17], tf.float32, [1, 1])
493 // output = tf.matmul(input, const, name = "output")
494 m_Prototext = R"(
495node {
496 name: "input"
497 op: "Placeholder"
498 attr {
499 key: "dtype"
500 value {
501 type: DT_FLOAT
502 }
503 }
504 attr {
505 key: "shape"
506 value {
507 shape {
508 dim {
509 size: 1
510 }
511 dim {
512 size: 1
513 }
514 }
515 }
516 }
517}
518node {
519 name: "Const"
520 op: "Const"
521 attr {
522 key: "dtype"
523 value {
524 type: DT_FLOAT
525 }
526 }
527 attr {
528 key: "value"
529 value {
530 tensor {
531 dtype: DT_FLOAT
532 tensor_shape {
533 dim {
534 size: 1
535 }
536 dim {
537 size: 1
538 }
539 }
540 float_val: 17.0
541 }
542 }
543 }
544}
545node {
546 name: "output"
547 op: "MatMul"
548 input: "input"
549 input: "Const"
550 attr {
551 key: "T"
552 value {
553 type: DT_FLOAT
554 }
555 }
556 attr {
557 key: "transpose_a"
558 value {
559 b: false
560 }
561 }
562 attr {
563 key: "transpose_b"
564 value {
565 b: false
566 }
567 }
568}
569 )";
570 SetupSingleInputSingleOutput({ 1, 1 }, "input", "output");
571 }
572};
573
574BOOST_FIXTURE_TEST_CASE(MatMul, MatMulFixture)
575{
576 RunTest<1>({ 2 }, { 34 });
577}
578
579BOOST_AUTO_TEST_SUITE_END()