1 // SPDX-License-Identifier: Apache-2.0
3 * Copyright (C) 2021 Jihoon Lee <jhoon.it.lee@samsung.com>
5 * @file unittest_realizer.h
6 * @date 09 October 2021
7 * @brief NNTrainer graph realizer related tests
8 * @see https://github.com/nnstreamer/nntrainer
9 * @author Jihoon Lee <jhoon.it.lee@samsung.com>
10 * @bug No known bugs except for NYI items
12 #include <gtest/gtest.h>
16 #include <activation_realizer.h>
17 #include <bn_realizer.h>
18 #include <connection.h>
19 #include <flatten_realizer.h>
20 #include <input_realizer.h>
21 #include <loss_realizer.h>
22 #include <multiout_realizer.h>
23 #include <nntrainer_error.h>
24 #include <previous_input_realizer.h>
26 #include <recurrent_realizer.h>
27 #include <remap_realizer.h>
28 #include <slice_realizer.h>
30 #include <compiler_test_util.h>
31 #include <nntrainer_test_util.h>
33 using namespace nntrainer;
36 * @brief check realize and equal
38 * @param realizer realizer to use
40 * @param expected expected output
42 static void realizeAndEqual(GraphRealizer &realizer,
43 const std::vector<LayerRepresentation> &input,
44 const std::vector<LayerRepresentation> &expected) {
45 auto processed = realizer.realize(makeGraph(input));
46 auto expected_graph = makeGraph(expected);
47 graphEqual(processed, expected_graph);
50 static void compileAndRealizeAndEqual(
51 GraphRealizer &realizer,
52 std::vector<std::unique_ptr<GraphRealizer>> &realizers,
53 const std::vector<LayerRepresentation> &input,
54 const std::vector<LayerRepresentation> &expected) {
55 auto processed = realizer.realize(makeCompiledGraph(input, realizers));
56 std::vector<std::unique_ptr<nntrainer::GraphRealizer>> defalute_realizers;
57 auto expected_graph = makeCompiledGraph(expected, realizers);
59 graphEqual(processed, expected_graph);
62 TEST(FlattenRealizer, flatten_p) {
65 LayerRepresentation input1 = {
67 {"name=layer1", "flatten=true"},
69 LayerRepresentation expected1 = {"fully_connected", {"name=layer1"}};
70 LayerRepresentation expected2 = {
72 {"name=layer1/flatten_realized", "input_layers=layer1"},
75 EXPECT_NO_THROW(realizeAndEqual(fr, {input1}, {expected1, expected2}));
78 TEST(RecurrentRealizer, recurrent_no_return_sequence_p) {
82 {"unroll_for=3", "recurrent_input=fc_in", "recurrent_output=fc_out"},
83 {C("source")}, {C("fc_out")});
85 std::vector<LayerRepresentation> before = {
86 {"fully_connected", {"name=fc_in", "input_layers=source"}},
87 {"fully_connected", {"name=fc_out", "input_layers=fc_in"}}};
89 std::vector<LayerRepresentation> expected = {
92 {"name=fc_in/0", "input_layers=source", "shared_from=fc_in/0"}},
94 {"name=fc_out/0", "input_layers=fc_in/0", "shared_from=fc_out/0"}},
98 {"name=fc_in/1", "input_layers=fc_out/0", "shared_from=fc_in/0"}},
100 {"name=fc_out/1", "input_layers=fc_in/1", "shared_from=fc_out/0"}},
104 {"name=fc_in/2", "input_layers=fc_out/1", "shared_from=fc_in/0"}},
106 {"name=fc_out/2", "input_layers=fc_in/2", "shared_from=fc_out/0"}},
109 {"identity", {"name=fc_out", "input_layers=fc_out/2"}},
112 EXPECT_NO_THROW(realizeAndEqual(r, before, expected));
115 TEST(RecurrentRealizer, recurrent_input_is_sequence_p) {
116 using C = Connection;
118 RecurrentRealizer r({"unroll_for=3", "input_is_sequence=source",
119 "recurrent_input=fc_out", "recurrent_output=fc_out"},
120 {C("source")}, {C("fc_out")});
122 std::vector<LayerRepresentation> before = {
123 {"fully_connected", {"name=fc_in", "input_layers=source"}},
124 {"fully_connected", {"name=fc_out", "input_layers=fc_in"}}};
126 std::vector<LayerRepresentation> expected = {
129 {"name=fc_in/0", "input_layers=source/0", "shared_from=fc_in/0"}},
131 {"name=fc_out/0", "input_layers=fc_in/0", "shared_from=fc_out/0"}},
135 {"name=fc_in/1", "input_layers=source/1", "shared_from=fc_in/0"}},
137 {"name=fc_out/1", "input_layers=fc_out/0", "shared_from=fc_out/0"}},
141 {"name=fc_in/2", "input_layers=source/2", "shared_from=fc_in/0"}},
143 {"name=fc_out/2", "input_layers=fc_out/1", "shared_from=fc_out/0"}},
146 {"identity", {"name=fc_out", "input_layers=fc_out/2"}},
149 EXPECT_NO_THROW(realizeAndEqual(r, before, expected));
152 TEST(RecurrentRealizer, recurrent_return_sequence_single_p) {
153 using C = Connection;
154 RecurrentRealizer r({"unroll_for=3", "as_sequence=fc_out",
155 "recurrent_input=lstmcell", "recurrent_output=fc_out"},
156 {C("source")}, {C("fc_out")});
158 std::vector<LayerRepresentation> before = {
159 {"lstmcell", {"name=lstmcell", "input_layers=source"}},
160 {"fully_connected", {"name=fc_out", "input_layers=lstmcell"}}};
162 std::vector<LayerRepresentation> expected = {
165 {"name=lstmcell/0", "input_layers=source", "shared_from=lstmcell/0"}},
167 {"name=fc_out/0", "input_layers=lstmcell/0", "shared_from=fc_out/0"}},
171 {"name=lstmcell/1", "input_layers=fc_out/0", "shared_from=lstmcell/0"}},
173 {"name=fc_out/1", "input_layers=lstmcell/1", "shared_from=fc_out/0"}},
177 {"name=lstmcell/2", "input_layers=fc_out/1", "shared_from=lstmcell/0"}},
179 {"name=fc_out/2", "input_layers=lstmcell/2", "shared_from=fc_out/0"}},
183 {"name=fc_out/concat_0", "input_layers=fc_out/0,fc_out/1,fc_out/2"}},
184 {"identity", {"name=fc_out", "input_layers=fc_out/concat_0"}},
187 EXPECT_NO_THROW(realizeAndEqual(r, before, expected));
190 TEST(RecurrentRealizer, recurrent_multi_inout_return_seq_p) {
191 using C = Connection;
195 "as_sequence=fc_out",
196 "recurrent_input=lstmcell,add(2)",
197 "recurrent_output=fc_out,split(1)",
199 {C("source"), C("source2"), C("source3")}, {C("fc_out")});
201 /// @note for below graph,
202 /// 1. fc_out feds back to lstmcell
203 /// 2. ouput_dummy feds back to source2_dummy
204 /// ========================================================
205 /// lstmcell -------- addition - split ---- fc_out (to_lstmcell)
206 /// source2_dummy --/ \----- (to addition 3)
207 std::vector<LayerRepresentation> before = {
208 {"lstmcell", {"name=lstmcell", "input_layers=source"}},
209 {"addition", {"name=add", "input_layers=lstmcell,source2,source3"}},
210 {"split", {"name=split", "input_layers=add"}},
211 {"fully_connected", {"name=fc_out", "input_layers=split(0)"}},
214 std::vector<LayerRepresentation> expected = {
217 {"name=lstmcell/0", "input_layers=source", "shared_from=lstmcell/0"}},
219 {"name=add/0", "input_layers=lstmcell/0,source2,source3",
220 "shared_from=add/0"}},
221 {"split", {"name=split/0", "input_layers=add/0", "shared_from=split/0"}},
223 {"name=fc_out/0", "input_layers=split/0(0)", "shared_from=fc_out/0"}},
227 {"name=lstmcell/1", "input_layers=fc_out/0", "shared_from=lstmcell/0"}},
229 {"name=add/1", "input_layers=lstmcell/1,source2,split/0(1)",
230 "shared_from=add/0"}},
231 {"split", {"name=split/1", "input_layers=add/1", "shared_from=split/0"}},
233 {"name=fc_out/1", "input_layers=split/1(0)", "shared_from=fc_out/0"}},
237 {"name=lstmcell/2", "input_layers=fc_out/1", "shared_from=lstmcell/0"}},
239 {"name=add/2", "input_layers=lstmcell/2,source2,split/1(1)",
240 "shared_from=add/0"}},
241 {"split", {"name=split/2", "input_layers=add/2", "shared_from=split/0"}},
243 {"name=fc_out/2", "input_layers=split/2(0)", "shared_from=fc_out/0"}},
247 {"name=fc_out/concat_0", "input_layers=fc_out/0,fc_out/1,fc_out/2"}},
248 {"identity", {"name=fc_out", "input_layers=fc_out/concat_0"}},
251 EXPECT_NO_THROW(realizeAndEqual(r, before, expected));
254 TEST(RecurrentRealizer, recurrent_multi_inout_using_connection_p) {
255 using C = Connection;
259 "recurrent_input=lstmcell,add(2)",
260 "recurrent_output=fc_out,split(1)",
262 {C("source"), C("source2"), C("source3")}, {C("fc_out")});
264 /// @note for below graph,
265 /// 1. fc_out feds back to lstmcell
266 /// 2. ouput_dummy feds back to source2_dummy
267 /// ========================================================
268 /// lstmcell -------- addition - split ---- fc_out (to_lstmcell)
269 /// source2_dummy --/ \----- (to addition 3)
270 std::vector<LayerRepresentation> before = {
271 {"lstmcell", {"name=lstmcell", "input_layers=source"}},
272 {"addition", {"name=add", "input_layers=lstmcell,source2,source3"}},
273 {"split", {"name=split", "input_layers=add"}},
274 {"fully_connected", {"name=fc_out", "input_layers=split(0)"}},
277 std::vector<LayerRepresentation> expected = {
280 {"name=lstmcell/0", "input_layers=source", "shared_from=lstmcell/0"}},
282 {"name=add/0", "input_layers=lstmcell/0,source2,source3",
283 "shared_from=add/0"}},
284 {"split", {"name=split/0", "input_layers=add/0", "shared_from=split/0"}},
286 {"name=fc_out/0", "input_layers=split/0(0)", "shared_from=fc_out/0"}},
290 {"name=lstmcell/1", "input_layers=fc_out/0", "shared_from=lstmcell/0"}},
292 {"name=add/1", "input_layers=lstmcell/1,source2,split/0(1)",
293 "shared_from=add/0"}},
294 {"split", {"name=split/1", "input_layers=add/1", "shared_from=split/0"}},
296 {"name=fc_out/1", "input_layers=split/1(0)", "shared_from=fc_out/0"}},
300 {"name=lstmcell/2", "input_layers=fc_out/1", "shared_from=lstmcell/0"}},
302 {"name=add/2", "input_layers=lstmcell/2,source2,split/1(1)",
303 "shared_from=add/0"}},
304 {"split", {"name=split/2", "input_layers=add/2", "shared_from=split/0"}},
306 {"name=fc_out/2", "input_layers=split/2(0)", "shared_from=fc_out/0"}},
309 {"identity", {"name=fc_out", "input_layers=fc_out/2"}},
312 EXPECT_NO_THROW(realizeAndEqual(r, before, expected));
315 TEST(RecurrentRealizer, recurrent_multi_inout_multi_connection_end_p) {
316 using C = Connection;
320 "recurrent_input=lstmcell,add(2)",
321 "recurrent_output=fc_out,split(1)",
322 "as_sequence=split(1)",
334 /// @note for below graph,
335 /// 1. fc_out feds back to lstmcell
336 /// 2. ouput_dummy feds back to source2_dummy
337 /// ========================================================
338 /// lstmcell -------- addition - split ---- fc_out (to_lstmcell)
339 /// source2_dummy --/ \----- (to addition 3)
340 std::vector<LayerRepresentation> before = {
341 {"lstmcell", {"name=lstmcell", "input_layers=source"}},
342 {"addition", {"name=add", "input_layers=lstmcell,source2,source3"}},
343 {"split", {"name=split", "input_layers=add"}},
344 {"fully_connected", {"name=fc_out", "input_layers=split(0)"}},
347 std::vector<LayerRepresentation> expected = {
350 {"name=lstmcell/0", "input_layers=source", "shared_from=lstmcell/0"}},
352 {"name=add/0", "input_layers=lstmcell/0,source2,source3",
353 "shared_from=add/0"}},
354 {"split", {"name=split/0", "input_layers=add/0", "shared_from=split/0"}},
356 {"name=fc_out/0", "input_layers=split/0(0)", "shared_from=fc_out/0"}},
360 {"name=lstmcell/1", "input_layers=fc_out/0", "shared_from=lstmcell/0"}},
362 {"name=add/1", "input_layers=lstmcell/1,source2,split/0(1)",
363 "shared_from=add/0"}},
364 {"split", {"name=split/1", "input_layers=add/1", "shared_from=split/0"}},
366 {"name=fc_out/1", "input_layers=split/1(0)", "shared_from=fc_out/0"}},
370 {"name=lstmcell/2", "input_layers=fc_out/1", "shared_from=lstmcell/0"}},
372 {"name=add/2", "input_layers=lstmcell/2,source2,split/1(1)",
373 "shared_from=add/0"}},
374 {"split", {"name=split/2", "input_layers=add/2", "shared_from=split/0"}},
376 {"name=fc_out/2", "input_layers=split/2(0)", "shared_from=fc_out/0"}},
380 {"name=split/concat_1", "input_layers=split/0(1),split/1(1),split/2(1)"}},
381 {"identity", {"name=split", "input_layers=split/2(0),split/concat_1"}},
384 EXPECT_NO_THROW(realizeAndEqual(r, before, expected));
387 TEST(RemapRealizer, remap_01_n) {
388 std::function<void(std::string &, unsigned &)> remap_connection_function =
391 EXPECT_THROW(RemapRealizer r(remap_connection_function),
392 std::invalid_argument);
395 TEST(RemapRealizer, remap_02_n) {
396 std::function<void(std::string &)> remap_function = nullptr;
398 EXPECT_THROW(RemapRealizer r(remap_function), std::invalid_argument);
401 TEST(RemapRealizer, remap_03_n) {
402 auto model_graph = NetworkGraph();
403 LayerRepresentation input = {"input", {"name=layer1", "input_shape=1:1:1"}};
405 auto graph = makeGraph({input});
406 EXPECT_NO_THROW(model_graph.addLayer(graph[0]));
407 EXPECT_EQ(model_graph.compile("mse"), ML_ERROR_NONE);
408 EXPECT_NO_THROW(model_graph.finalizeContext(graph[0], {}));
410 RemapRealizer r([](std::string &name) { name = "scoped/" + name; });
411 EXPECT_THROW(r.realize(graph), std::invalid_argument);
414 TEST(RemapRealizer, remap_04_n) {
415 auto model_graph = NetworkGraph();
416 LayerRepresentation input = {"input", {"name=layer1", "input_shape=1:1:1"}};
418 auto graph = makeGraph({input});
419 EXPECT_NO_THROW(model_graph.addLayer(graph[0]));
420 EXPECT_EQ(model_graph.compile("mse"), ML_ERROR_NONE);
421 EXPECT_NO_THROW(model_graph.finalizeContext(graph[0], {}));
424 [](std::string &name, unsigned &_) { name = "scoped/" + name; });
425 EXPECT_THROW(r.realize(graph), std::invalid_argument);
428 TEST(RemapRealizer, remap_05_p) {
429 LayerRepresentation input1 = {
430 "fully_connected", {"name=layer1", "flatten=true", "input_layers=1,2"}};
433 RemapRealizer r([](std::string &name) { name = "scoped/" + name; });
435 LayerRepresentation expected1 = {
437 {"name=scoped/layer1", "flatten=true", "input_layers=scoped/1,scoped/2"}};
439 EXPECT_NO_THROW(realizeAndEqual(r, {input1}, {expected1}));
443 [](std::string &name, unsigned &_) { name = "scoped/" + name; });
445 LayerRepresentation expected2 = {
447 {"name=layer1", "flatten=true", "input_layers=scoped/1,scoped/2"}};
449 EXPECT_NO_THROW(realizeAndEqual(r2, {input1}, {expected2}));
453 TEST(SliceRealizer, slice_01_p) {
465 std::vector<LayerRepresentation> before = {
466 {"fully_connected", {"name=a1"}},
467 {"fully_connected", {"name=a2"}},
468 {"fully_connected", {"name=b1", "input_layers=a1"}},
469 {"fully_connected", {"name=b2", "input_layers=a2"}},
470 {"fully_connected", {"name=b3"}},
471 {"fully_connected", {"name=c1", "input_layers=b1,b2"}},
472 {"fully_connected", {"name=c2", "input_layers=b2,b3"}},
473 {"fully_connected", {"name=d1", "input_layers=c1"}},
474 {"fully_connected", {"name=d2", "input_layers=c1"}},
479 * start_layer = a1, b1, b2
480 * end_layer = a1, d1, d2
482 * a1 (was input port)
490 std::vector<LayerRepresentation> after = {
491 {"fully_connected", {"name=a1"}},
492 {"fully_connected", {"name=b1", "input_layers=a1"}},
493 {"fully_connected", {"name=b2", "input_layers=a2"}},
494 {"fully_connected", {"name=c1", "input_layers=b1,b2"}},
495 {"fully_connected", {"name=d1", "input_layers=c1"}},
496 {"fully_connected", {"name=d2", "input_layers=c1"}},
499 using C = Connection;
512 EXPECT_NO_THROW(realizeAndEqual(r, before, after));
515 TEST(SliceRealizer, slice_02_p) {
525 std::vector<LayerRepresentation> before = {
526 {"fully_connected", {"name=a1"}},
527 {"fully_connected", {"name=b1", "input_layers=a1"}},
528 {"concat", {"name=c1", "input_layers=a1, b1"}},
538 std::vector<LayerRepresentation> after = {
539 {"fully_connected", {"name=a1"}},
540 {"fully_connected", {"name=b1", "input_layers=a1"}},
541 {"concat", {"name=c1", "input_layers=a1, b1"}},
544 SliceRealizer r({Connection("a1")}, {Connection("c1")});
546 EXPECT_NO_THROW(realizeAndEqual(r, before, after));
549 TEST(SliceRealizer, slice_03_n) {
550 std::vector<LayerRepresentation> before = {
551 {"fully_connected", {"name=a1", "input_layers=a2"}},
552 {"fully_connected", {"name=a2", "input_layers=a1"}},
555 std::vector<LayerRepresentation> after = {};
557 using C = Connection;
558 SliceRealizer r({}, {C("a2")});
560 EXPECT_THROW(realizeAndEqual(r, before, after), std::runtime_error);
563 TEST(SliceRealizer, slice_04_n) {
564 std::vector<LayerRepresentation> before = {
565 {"fully_connected", {"name=a1", "input_layers=a2"}},
566 {"fully_connected", {"name=a2", "input_layers=a1"}},
569 std::vector<LayerRepresentation> after = {};
571 using C = Connection;
572 SliceRealizer r({C("a1")}, {});
574 EXPECT_THROW(realizeAndEqual(r, before, after), std::runtime_error);
577 TEST(SliceRealizer, slice_05_n) {
578 std::vector<LayerRepresentation> before = {
579 {"fully_connected", {"name=a1"}},
580 {"fully_connected", {"name=a2", "input_layers=a1"}},
583 std::vector<LayerRepresentation> after = {};
585 using C = Connection;
586 SliceRealizer r({C("a2")}, {C("a1")});
588 EXPECT_THROW(realizeAndEqual(r, before, after), std::invalid_argument);
591 TEST(InputRealizer, input_p) {
592 std::vector<LayerRepresentation> before = {
593 {"fully_connected", {"name=fc1"}},
594 {"fully_connected", {"name=fc2", "input_layers=none1,fc1"}},
595 {"fully_connected", {"name=fc3", "input_layers=none2,fc2,none3"}},
598 std::vector<LayerRepresentation> after = {
599 {"fully_connected", {"name=fc1", "input_layers=in1(0)"}},
600 {"fully_connected", {"name=fc2", "input_layers=in2,fc1"}},
601 {"fully_connected", {"name=fc3", "input_layers=in3(3),fc2,in4"}},
604 using C = Connection;
618 EXPECT_NO_THROW(realizeAndEqual(r, before, after));
621 TEST(InputRealizer, input_start_num_not_match_n) {
622 using C = Connection;
623 EXPECT_ANY_THROW(InputRealizer r(
635 TEST(InputRealizer, start_empty_conn_not_defined_n) {
636 std::vector<LayerRepresentation> before = {
637 {"fully_connected", {"name=fc1"}},
638 {"fully_connected", {"name=fc2", "input_layers=none1,fc1"}},
639 {"fully_connected", {"name=fc3", "input_layers=none2,fc2,none3"}},
642 std::vector<LayerRepresentation> after = {
643 {"fully_connected", {"name=fc1", "input_layers=in1(0)"}},
644 {"fully_connected", {"name=fc2", "input_layers=in2,fc1"}},
645 {"fully_connected", {"name=fc3", "input_layers=in3(3),fc2,in4"}},
648 using C = Connection;
651 C("fc1(2)"), /**< connection not defined, although fc1(0) is allowed */
662 EXPECT_ANY_THROW(realizeAndEqual(r, before, after));
665 TEST(InputRealizer, intermediate_conn_not_defined_n) {
666 std::vector<LayerRepresentation> before = {
667 {"fully_connected", {"name=fc1"}},
668 {"fully_connected", {"name=fc2", "input_layers=none1,fc1"}},
669 {"fully_connected", {"name=fc3", "input_layers=none2,fc2,none3"}},
672 std::vector<LayerRepresentation> after = {
673 {"fully_connected", {"name=fc1", "input_layers=in1(0)"}},
674 {"fully_connected", {"name=fc2", "input_layers=in2,fc1"}},
675 {"fully_connected", {"name=fc3", "input_layers=in3(3),fc2,in4"}},
678 using C = Connection;
682 C("fc2(4)"), /**< connection not defined */
692 EXPECT_ANY_THROW(realizeAndEqual(r, before, after));
695 TEST(PreviousInputRealizer, previous_p) {
696 { /// realization without identifying custom input
697 std::vector<LayerRepresentation> before = {
698 {"fully_connected", {"name=fc1", "input_shape=1"}}, // model input
699 {"fully_connected", {"name=fc2"}}, // auto connected to fc 1
700 {"fully_connected", {"name=fc3", "input_layers=fc1"}},
701 {"fully_connected", {"name=fc4"}}, // auto connected to fc 3
704 std::vector<LayerRepresentation> after = {
705 {"fully_connected", {"name=fc1", "input_shape=1"}},
706 {"fully_connected", {"name=fc2", "input_layers=fc1"}},
707 {"fully_connected", {"name=fc3", "input_layers=fc1"}},
708 {"fully_connected", {"name=fc4", "input_layers=fc3"}},
710 PreviousInputRealizer r({});
711 EXPECT_NO_THROW(realizeAndEqual(r, before, after));
713 { /// realization identifying fc1, fc4 is input layer
714 std::vector<LayerRepresentation> before = {
715 {"fully_connected", {"name=fc1"}}, // will be identified as model input
716 {"fully_connected", {"name=fc2"}}, // auto connected to fc 1
717 {"fully_connected", {"name=fc3", "input_layers=fc1"}},
718 {"fully_connected", {"name=fc4"}}, // will be identified as model input
720 std::vector<LayerRepresentation> after = {
721 {"fully_connected", {"name=fc1"}},
722 {"fully_connected", {"name=fc2", "input_layers=fc1"}},
723 {"fully_connected", {"name=fc3", "input_layers=fc1"}},
724 {"fully_connected", {"name=fc4"}},
726 PreviousInputRealizer r({Connection("fc1"), Connection("fc4")});
727 EXPECT_NO_THROW(realizeAndEqual(r, before, after));
729 { /// intermediate node is auto input
730 std::vector<LayerRepresentation> before = {
732 {"name=fc1", "input_layers=fc2"}}, // intermediate node
733 {"fully_connected", {"name=fc2", "input_shape=1"}}, // model input
734 {"fully_connected", {"name=fc3"}}, // auto connected to fc3
735 {"fully_connected", {"name=fc4"}}, // auto connected to fc 3
738 std::vector<LayerRepresentation> after = {
739 {"fully_connected", {"name=fc1", "input_layers=fc2"}},
740 {"fully_connected", {"name=fc2", "input_shape=1"}},
741 {"fully_connected", {"name=fc3", "input_layers=fc2"}},
742 {"fully_connected", {"name=fc4", "input_layers=fc3"}},
744 PreviousInputRealizer r({});
745 EXPECT_NO_THROW(realizeAndEqual(r, before, after));
749 TEST(PreviousInputRealizer, user_not_identifying_first_input_n) {
750 /// realization without identifying custom input
751 std::vector<LayerRepresentation> before = {
752 {"fully_connected", {"name=fc1"}}, // this should be model input but
753 // nothing has been connected
754 {"fully_connected", {"name=fc2"}}, // auto connected to fc 1
755 {"fully_connected", {"name=fc3", "input_layers=fc1"}},
756 {"fully_connected", {"name=fc4"}}, // auto connected to fc 3
758 PreviousInputRealizer r({});
759 EXPECT_ANY_THROW(realizeAndEqual(r, before, {}));
761 TEST(MultioutRealizer, multiout_p) {
762 { // source has single output, referred multiple times
763 std::vector<LayerRepresentation> before = {
764 {"fully_connected", {"name=a"}},
765 {"fully_connected", {"name=b", "input_layers=a"}},
766 {"fully_connected", {"name=c", "input_layers=a"}},
767 {"fully_connected", {"name=d", "input_layers=a"}},
769 std::vector<LayerRepresentation> after = {
770 {"fully_connected", {"name=a"}},
771 {"multiout", {"name=a/generated_out_0", "input_layers=a"}},
772 {"fully_connected", {"name=b", "input_layers=a/generated_out_0(0)"}},
773 {"fully_connected", {"name=c", "input_layers=a/generated_out_0(1)"}},
774 {"fully_connected", {"name=d", "input_layers=a/generated_out_0(2)"}},
778 EXPECT_NO_THROW(realizeAndEqual(r, before, after));
781 { // source has single output, some are referred multiple times
782 std::vector<LayerRepresentation> before = {
783 {"split", {"name=a", "input_shape=1:1:1:2", "axis=3"}},
784 {"fully_connected", {"name=b", "input_layers=a(0)"}},
785 {"fully_connected", {"name=c", "input_layers=a(0)"}},
786 {"fully_connected", {"name=d", "input_layers=a(1)"}},
788 std::vector<LayerRepresentation> after = {
789 {"split", {"name=a", "input_shape=1:1:1:2", "axis=3"}},
790 {"multiout", {"name=a/generated_out_0", "input_layers=a(0)"}},
791 {"fully_connected", {"name=b", "input_layers=a/generated_out_0(0)"}},
792 {"fully_connected", {"name=c", "input_layers=a/generated_out_0(1)"}},
793 {"fully_connected", {"name=d", "input_layers=a(1)"}},
797 EXPECT_NO_THROW(realizeAndEqual(r, before, after));
801 TEST(MultioutRealizer, multiout_clashing_name_n) {
802 std::vector<LayerRepresentation> before = {
803 {"split", {"name=a", "input_shape=1:1:1:2", "axis=3"}},
804 {"fully_connected", {"name=a", "input_layers=a(0)"}},
808 EXPECT_ANY_THROW(realizeAndEqual(r, before, {}));
811 TEST(ActivationRealizer, activation_p) {
812 ActivationRealizer r;
814 std::vector<LayerRepresentation> before = {
815 {"fully_connected", {"name=a"}},
817 {"name=b", "activation=relu", "input_layers=a"}}, /// not realized
819 {"name=c", "input_layers=b", "activation=softmax"}}, // realized
822 std::vector<LayerRepresentation> after = {
823 {"fully_connected", {"name=a"}},
824 {"activation", {"name=b", "activation=relu", "input_layers=a"}},
825 {"fully_connected", {"name=c", "input_layers=b", "activation=none"}},
827 {"name=c/activation_realized", "input_layers=c", "activation=softmax"}},
830 EXPECT_NO_THROW(realizeAndEqual(r, before, after));
833 TEST(ActivationRealizer, activation_unknown_n) {
834 ActivationRealizer r;
836 std::vector<LayerRepresentation> before = {
837 {"fully_connected", {"name=a"}},
839 {"name=b", "activation=relu", "input_layers=a"}}, /// not realized
841 {"name=c", "input_layers=b", "activation=unknown"}}, // unknown
844 EXPECT_ANY_THROW(realizeAndEqual(r, before, {}));
847 TEST(BnRealizer, bn_realizer_p) {
848 /// realization without identifying custom input
849 std::vector<LayerRepresentation> before = {
850 {"fully_connected", {"name=fc1"}},
851 {"batch_normalization", {"name=bn1", "input_layers=fc1"}},
852 {"activation", {"name=ac1", "activation=relu", "input_layers=bn1"}},
853 {"fully_connected", {"name=fc2", "input_layers=ac1"}},
854 {"batch_normalization", {"name=bn2", "input_layers=fc2"}},
855 {"activation", {"name=ac2", "activation=relu", "input_layers=bn2"}},
856 {"fully_connected", {"name=fc3", "input_layers=ac2"}},
858 std::vector<LayerRepresentation> after = {
859 {"fully_connected", {"name=fc1"}},
860 {"activation", {"name=ac1", "activation=relu", "input_layers=fc1"}},
861 {"fully_connected", {"name=fc2", "input_layers=ac1"}},
862 {"activation", {"name=ac2", "activation=relu", "input_layers=fc2"}},
863 {"fully_connected", {"name=fc3", "input_layers=ac2"}},
866 std::vector<std::unique_ptr<nntrainer::GraphRealizer>> realizers;
867 EXPECT_NO_THROW(compileAndRealizeAndEqual(r, realizers, before, after));
870 TEST(BnRealizer, bn_realizer_resblock_p) {
871 std::vector<LayerRepresentation> before = {
872 {"input", {"name=input0"}},
873 {"conv2d", {"name=conv0", "kernel_size=3,3", "input_layers=input0"}},
874 {"batch_normalization", {"name=first_bn", "input_layers=conv0"}},
875 {"activation", {"name=ac0", "activation=relu", "input_layers=first_bn"}},
876 {"conv2d", {"name=a1", "kernel_size=3,3", "input_layers=ac0"}},
877 {"batch_normalization", {"name=bn1", "input_layers=a1"}},
878 {"activation", {"name=ac1", "activation=relu", "input_layers=bn1"}},
879 {"conv2d", {"name=a2", "kernel_size=3,3", "input_layers=ac1"}},
880 {"conv2d", {"name=b1", "kernel_size=3,3", "input_layers=ac0"}},
881 {"addition", {"name=c1", "input_layers=a2,b1"}},
882 {"batch_normalization", {"name=bn2", "input_layers=c1"}},
883 {"activation", {"name=ac2", "activation=relu", "input_layers=bn2"}},
884 {"fully_connected", {"name=fc3", "input_layers=ac2"}},
886 std::vector<LayerRepresentation> after = {
887 {"input", {"name=input0"}},
888 {"conv2d", {"name=conv0", "kernel_size=3,3", "input_layers=input0"}},
889 {"activation", {"name=ac0", "activation=relu", "input_layers=conv0"}},
890 {"conv2d", {"name=a1", "kernel_size=3,3", "input_layers=ac0"}},
891 {"activation", {"name=ac1", "activation=relu", "input_layers=a1"}},
892 {"conv2d", {"name=a2", "kernel_size=3,3", "input_layers=ac1"}},
893 {"conv2d", {"name=b1", "kernel_size=3,3", "input_layers=ac0"}},
894 {"addition", {"name=c1", "input_layers=a2,b1"}},
895 {"activation", {"name=ac2", "activation=relu", "input_layers=c1"}},
896 {"fully_connected", {"name=fc3", "input_layers=ac2"}},
898 std::vector<std::unique_ptr<nntrainer::GraphRealizer>> realizers;
899 realizers.emplace_back(new nntrainer::MultioutRealizer());
901 EXPECT_NO_THROW(compileAndRealizeAndEqual(r, realizers, before, after));
904 TEST(LossRealizer, loss_realizer_p) {
905 /// realization without identifying custom input
906 std::vector<LayerRepresentation> before = {
907 {"fully_connected", {"name=fc1"}},
908 {"activation", {"name=ac1", "activation=relu", "input_layers=fc1"}},
909 {"fully_connected", {"name=fc2", "input_layers=ac1"}},
910 {"activation", {"name=ac2", "activation=relu", "input_layers=fc2"}},
911 {"fully_connected", {"name=fc3", "input_layers=ac2"}},
912 {"mse", {"name=loss", "input_layers=fc3"}},
914 std::vector<LayerRepresentation> after = {
915 {"fully_connected", {"name=fc1"}},
916 {"activation", {"name=ac1", "activation=relu", "input_layers=fc1"}},
917 {"fully_connected", {"name=fc2", "input_layers=ac1"}},
918 {"activation", {"name=ac2", "activation=relu", "input_layers=fc2"}},
919 {"fully_connected", {"name=fc3", "input_layers=ac2"}},
922 std::vector<std::unique_ptr<nntrainer::GraphRealizer>> realizers;
923 compileAndRealizeAndEqual(r, realizers, before, after);