Added unit tests and readme for model optimizer (#79)
[platform/upstream/dldt.git] / model-optimizer / mo / middle / passes / fusing / mark_unfused_nodes_test.py
1 """
2  Copyright (c) 2018 Intel Corporation
3
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7
8       http://www.apache.org/licenses/LICENSE-2.0
9
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15 """
16
17 import unittest
18
19 import numpy as np
20
21 from mo.middle.passes.fusing.mark_unfused_nodes import mark_unfused_nodes
22 from mo.utils.unittest.graph import build_graph
23
24 nodes_attributes = {
25     'placeholder_1': {'shape': None, 'type': 'Placeholder', 'kind': 'op', 'op': 'Placeholder'},
26     'placeholder_1_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None},
27     # ScaleShift layer
28     'scaleshift_1': {'type': 'ScaleShift', 'kind': 'op', 'op': 'ScaleShift'},
29     'scaleshift_1_w': {'value': None, 'shape': None, 'kind': 'data'},
30     'scaleshift_1_b': {'value': None, 'shape': None, 'kind': 'data'},
31     'scaleshift_1_data': {'value': None, 'shape': None, 'kind': 'data'},
32     # Mul and Add operations
33     'mul_1': {'type': 'Mul', 'kind': 'op', 'op': 'Mul'},
34     'mul_1_w': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None},
35     'mul_1_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None},
36     'add_1': {'type': 'Add', 'kind': 'op', 'op': 'Add'},
37     'add_1_w': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None},
38     'add_1_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None},
39     # Mul2 and Add2 operations
40     'mul_2': {'type': 'Mul', 'kind': 'op', 'op': 'Mul'},
41     'mul_2_w': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None},
42     'mul_2_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None},
43     'add_2': {'type': 'Add', 'kind': 'op', 'op': 'Add'},
44     'add_2_w': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None},
45     'add_2_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None},
46     # Concat1 operation
47     'concat_1': {'type': 'Concat', 'kind': 'op', 'op': 'Concat'},
48     'concat_1_data': {'value': None, 'shape': None, 'kind': 'data'},
49     # Convolutions
50     'conv_1': {'type': 'Convolution', 'kind': 'op', 'op': 'Conv2D', 'layout': 'NHWC'},
51     'conv_1_w': {'value': None, 'shape': None, 'kind': 'data'},
52     'conv_1_b': {'value': None, 'shape': None, 'kind': 'data'},
53     'conv_1_data': {'value': None, 'shape': None, 'kind': 'data'},
54     'conv_2': {'type': 'Convolution', 'kind': 'op', 'op': 'Conv2D', 'layout': 'NHWC'},
55     'conv_2_w': {'value': None, 'shape': None, 'kind': 'data'},
56     'conv_2_b': {'value': None, 'shape': None, 'kind': 'data'},
57     'conv_2_data': {'value': None, 'shape': None, 'kind': 'data'},
58     # FullyConnected
59     'fc_1': {'type': 'FullyConnected', 'kind': 'op', 'op': 'InnerProduct', 'layout': 'NHWC'},
60     'fc_1_w': {'value': None, 'shape': None, 'kind': 'data'},
61     'fc_1_b': {'value': None, 'shape': None, 'kind': 'data'},
62     'fc_1_data': {'value': None, 'shape': None, 'kind': 'data'},
63     # Placeholders
64     'placeholder_2': {'shape': None, 'type': 'Placeholder', 'kind': 'op', 'op': 'Placeholder'},
65     'placeholder_2_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None},
66     'placeholder_3': {'shape': None, 'type': 'Placeholder', 'kind': 'op', 'op': 'Placeholder'},
67     'placeholder_3_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None},
68 }
69
70
71 # Unit tests for forward and backward bfs (forward_bfs, backward_bfs)
72 class MarkFusedNodes(unittest.TestCase):
73     def test_mark_unfused_nodes_1(self):
74         # Placeholder->ScaleShift->Mul->Add
75         graph = build_graph(nodes_attributes,
76                             [('placeholder_1', 'placeholder_1_data'),
77                              ('placeholder_1_data', 'mul_1'),
78                              ('mul_1_w', 'mul_1'),
79                              ('mul_1', 'mul_1_data'),
80                              ('mul_1_data', 'add_1'),
81                              ('add_1_w', 'add_1'),
82                              ('add_1', 'add_1_data'),
83                              ('add_1_data', 'mul_2'),
84                              ('mul_2_w', 'mul_2'),
85                              ('mul_2', 'mul_2_data'),
86                              ('mul_2_data', 'concat_1'),
87                              ('concat_1', 'concat_1_data'),
88                              ('placeholder_1_data', 'concat_1'),
89                              ],
90                             {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
91                              'mul_1_data': {'shape': np.array([1, 227, 227, 3])},
92                              'add_1_data': {'shape': np.array([1, 227, 227, 3])},
93                              'mul_2_data': {'shape': np.array([1, 227, 227, 3])},
94                              'mul_1_w': {'shape': np.array([1]), 'value': 6},
95                              'add_1_w': {'shape': np.array([1]), 'value': 6},
96                              'mul_2_w': {'shape': np.array([1]), 'value': 6},
97                              'concat_1_data': {'is_output': True}
98                              })
99
100         graph.graph['layout'] = 'NHWC'
101
102         mark_unfused_nodes(graph, '.*mul.*')
103
104         self.assertFalse(graph.node['mul_1']['can_be_fused'], "can_be_fused should be False")
105         self.assertFalse(graph.node['mul_2']['can_be_fused'], "can_be_fused should be False")
106         self.assertTrue(graph.node['add_1']['can_be_fused'], "can_be_fused should be True")
107
108     def test_mark_unfused_nodes_2(self):
109         # Placeholder->ScaleShift->Mul->Add
110         graph = build_graph(nodes_attributes,
111                             [('placeholder_1', 'placeholder_1_data'),
112                              ('placeholder_1_data', 'mul_1'),
113                              ('mul_1_w', 'mul_1'),
114                              ('mul_1', 'mul_1_data'),
115                              ('mul_1_data', 'add_1'),
116                              ('add_1_w', 'add_1'),
117                              ('add_1', 'add_1_data'),
118                              ('add_1_data', 'mul_2'),
119                              ('mul_2_w', 'mul_2'),
120                              ('mul_2', 'mul_2_data'),
121                              ('mul_2_data', 'concat_1'),
122                              ('concat_1', 'concat_1_data'),
123                              ('placeholder_1_data', 'concat_1'),
124                              ],
125                             {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
126                              'mul_1_data': {'shape': np.array([1, 227, 227, 3])},
127                              'add_1_data': {'shape': np.array([1, 227, 227, 3])},
128                              'mul_2_data': {'shape': np.array([1, 227, 227, 3])},
129                              'mul_1_w': {'shape': np.array([1]), 'value': 6},
130                              'add_1_w': {'shape': np.array([1]), 'value': 6},
131                              'mul_2_w': {'shape': np.array([1]), 'value': 6},
132                              'concat_1_data': {'is_output': True}
133                              })
134         graph.graph['layout'] = 'NHWC'
135
136         mark_unfused_nodes(graph, '.*')
137
138         self.assertFalse(graph.node['mul_1']['can_be_fused'], "can_be_fused should be False")
139         self.assertFalse(graph.node['mul_2']['can_be_fused'], "can_be_fused should be False")
140         self.assertFalse(graph.node['add_1']['can_be_fused'], "can_be_fused should be False")
141         self.assertFalse(graph.node['placeholder_1']['can_be_fused'], "can_be_fused should be False")
142         self.assertFalse(graph.node['concat_1']['can_be_fused'], "can_be_fused should be False")
143
144     def test_mark_unfused_nodes_3(self):
145         # Placeholder->ScaleShift->Mul->Add
146         graph = build_graph(nodes_attributes,
147                             [('placeholder_1', 'placeholder_1_data'),
148                              ('placeholder_1_data', 'mul_1'),
149                              ('mul_1_w', 'mul_1'),
150                              ('mul_1', 'mul_1_data'),
151                              ('mul_1_data', 'add_1'),
152                              ('add_1_w', 'add_1'),
153                              ('add_1', 'add_1_data'),
154                              ('add_1_data', 'mul_2'),
155                              ('mul_2_w', 'mul_2'),
156                              ('mul_2', 'mul_2_data'),
157                              ('mul_2_data', 'concat_1'),
158                              ('concat_1', 'concat_1_data'),
159                              ('placeholder_1_data', 'concat_1'),
160                              ],
161                             {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
162                              'mul_1_data': {'shape': np.array([1, 227, 227, 3])},
163                              'add_1_data': {'shape': np.array([1, 227, 227, 3])},
164                              'mul_2_data': {'shape': np.array([1, 227, 227, 3])},
165                              'mul_1_w': {'shape': np.array([1]), 'value': 6},
166                              'add_1_w': {'shape': np.array([1]), 'value': 6},
167                              'mul_2_w': {'shape': np.array([1]), 'value': 6},
168                              'concat_1_data': {'is_output': True}
169                              })
170         graph.graph['layout'] = 'NHWC'
171
172         mark_unfused_nodes(graph, 'mul_1,add_1')
173
174         self.assertFalse(graph.node['mul_1']['can_be_fused'], "can_be_fused should be False")
175         self.assertFalse(graph.node['add_1']['can_be_fused'], "can_be_fused should be False")
176         self.assertTrue(graph.node['mul_2']['can_be_fused'], "can_be_fused should be True")
177
178     def test_mark_unfused_nodes_4(self):
179         # Placeholder->ScaleShift->Mul->Add
180         graph = build_graph(nodes_attributes,
181                             [('placeholder_1', 'placeholder_1_data'),
182                              ('placeholder_1_data', 'mul_1'),
183                              ('mul_1_w', 'mul_1'),
184                              ('mul_1', 'mul_1_data'),
185                              ('mul_1_data', 'add_1'),
186                              ('add_1_w', 'add_1'),
187                              ('add_1', 'add_1_data'),
188                              ('add_1_data', 'mul_2'),
189                              ('mul_2_w', 'mul_2'),
190                              ('mul_2', 'mul_2_data'),
191                              ('mul_2_data', 'concat_1'),
192                              ('concat_1', 'concat_1_data'),
193                              ('placeholder_1_data', 'concat_1'),
194                              ],
195                             {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
196                              'mul_1_data': {'shape': np.array([1, 227, 227, 3])},
197                              'add_1_data': {'shape': np.array([1, 227, 227, 3])},
198                              'mul_2_data': {'shape': np.array([1, 227, 227, 3])},
199                              'mul_1_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
200                              'add_1_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
201                              'mul_2_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
202                              'concat_1_data': {'is_output': True}
203                              })
204         graph.graph['layout'] = 'NHWC'
205
206         mark_unfused_nodes(graph, '')
207
208         self.assertTrue(graph.node['mul_1']['can_be_fused'], "can_be_fused should be True")
209         self.assertTrue(graph.node['add_1']['can_be_fused'], "can_be_fused should be True")
210         self.assertTrue(graph.node['mul_2']['can_be_fused'], "can_be_fused should be True")
211
212     def test_mark_unfused_nodes_5(self):
213         # Placeholder->ScaleShift->Mul->Add
214         graph = build_graph(nodes_attributes,
215                             [('placeholder_1', 'placeholder_1_data'),
216                              ('placeholder_1_data', 'mul_1'),
217                              ('mul_1_w', 'mul_1'),
218                              ('mul_1', 'mul_1_data'),
219                              ('mul_1_data', 'add_1'),
220                              ('add_1_w', 'add_1'),
221                              ('add_1', 'add_1_data'),
222                              ('add_1_data', 'mul_2'),
223                              ('mul_2_w', 'mul_2'),
224                              ('mul_2', 'mul_2_data'),
225                              ('mul_2_data', 'concat_1'),
226                              ('concat_1', 'concat_1_data'),
227                              ('placeholder_1_data', 'concat_1'),
228                              ],
229                             {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
230                              'mul_1_data': {'shape': np.array([1, 227, 227, 3])},
231                              'add_1_data': {'shape': np.array([1, 227, 227, 3])},
232                              'mul_2_data': {'shape': np.array([1, 227, 227, 3])},
233                              'mul_1_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
234                              'add_1_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
235                              'mul_2_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
236                              'concat_1_data': {'is_output': True}
237                              })
238         graph.graph['layout'] = 'NCHW'
239
240         mark_unfused_nodes(graph, '')
241
242         self.assertTrue(graph.node['mul_1']['can_be_fused'], "can_be_fused should be True")
243         self.assertTrue(graph.node['add_1']['can_be_fused'], "can_be_fused should be True")
244         self.assertTrue(graph.node['mul_2']['can_be_fused'], "can_be_fused should be True")
245
246         def test_mark_unfused_nodes_5(self):
247             # Placeholder->ScaleShift->Mul->Add
248             graph = build_graph(nodes_attributes,
249                                 [('placeholder_1', 'placeholder_1_data'),
250                                  ('placeholder_1_data', 'mul_1'),
251                                  ('mul_1_w', 'mul_1'),
252                                  ('mul_1', 'mul_1_data'),
253                                  ('mul_1_data', 'add_1'),
254                                  ('add_1_w', 'add_1'),
255                                  ('add_1', 'add_1_data'),
256                                  ('add_1_data', 'mul_2'),
257                                  ('mul_2_w', 'mul_2'),
258                                  ('mul_2', 'mul_2_data'),
259                                  ('mul_2_data', 'concat_1'),
260                                  ('concat_1', 'concat_1_data'),
261                                  ('placeholder_1_data', 'concat_1'),
262                                  ],
263                                 {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
264                                  'mul_1_data': {'shape': np.array([1, 227, 227, 3])},
265                                  'add_1_data': {'shape': np.array([1, 227, 227, 3])},
266                                  'mul_2_data': {'shape': np.array([1, 227, 227, 3])},
267                                  'mul_1_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
268                                  'add_1_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
269                                  'mul_2_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
270                                  'concat_1_data': {'is_output': True}
271                                  })
272             graph.graph['layout'] = 'NCHW'
273
274             mark_unfused_nodes(graph, '')
275
276             self.assertFalse(graph.node['mul_1']['can_be_fused'], "can_be_fused should be False")
277             self.assertFalse(graph.node['add_1']['can_be_fused'], "can_be_fused should be False")
278             self.assertFalse(graph.node['mul_2']['can_be_fused'], "can_be_fused should be False")
279
280     def test_mark_unfused_nodes_6(self):
281         # Placeholder->ScaleShift->Mul->Add
282         graph = build_graph(nodes_attributes,
283                             [('placeholder_1', 'placeholder_1_data'),
284                              ('placeholder_1_data', 'mul_1'),
285                              ('mul_1_w', 'mul_1'),
286                              ('mul_1', 'mul_1_data'),
287                              ('mul_1_data', 'add_1'),
288                              ('add_1_w', 'add_1'),
289                              ('add_1', 'add_1_data'),
290                              ('add_1_data', 'mul_2'),
291                              ('mul_2_w', 'mul_2'),
292                              ('mul_2', 'mul_2_data'),
293                              ('mul_2_data', 'concat_1'),
294                              ('concat_1', 'concat_1_data'),
295                              ('placeholder_1_data', 'concat_1'),
296                              ],
297                             {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
298                              'mul_1_data': {'shape': np.array([1, 227, 227, 3])},
299                              'add_1_data': {'shape': np.array([1, 227, 227, 3])},
300                              'mul_2_data': {'shape': np.array([1, 227, 227, 3])},
301                              'mul_1_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
302                              'add_1_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
303                              'mul_2_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
304                              'concat_1_data': {'is_output': True}
305                              })
306         graph.graph['layout'] = 'NHWC'
307
308         mark_unfused_nodes(graph, '')
309
310         self.assertTrue(graph.node['mul_1']['can_be_fused'], "can_be_fused should be True")
311         self.assertTrue(graph.node['add_1']['can_be_fused'], "can_be_fused should be True")
312         self.assertTrue(graph.node['mul_2']['can_be_fused'], "can_be_fused should be True")