[LPT] integration: issue #42391 & issue #43001 (#3201)
[platform/upstream/dldt.git] / inference-engine / tests / functional / inference_engine / lp_transformations / group_convolution_transformation.cpp
1 // Copyright (C) 2020 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 #include "layer_transformation.hpp"
6
7 #include <string>
8 #include <sstream>
9 #include <memory>
10
11 #include <gtest/gtest.h>
12
13 #include <transformations/utils/utils.hpp>
14 #include <transformations/init_node_info.hpp>
15 #include <low_precision/group_convolution.hpp>
16
17 #include "common_test_utils/ngraph_test_utils.hpp"
18 #include "simple_low_precision_transformer.hpp"
19 #include "ngraph_functions/low_precision_transformations/group_convolution_function.hpp"
20
21 #include "ngraph_functions/low_precision_transformations/common/fake_quantize_on_weights.hpp"
22 #include "ngraph_functions/low_precision_transformations/common/dequantization_operations.hpp"
23
24 using namespace testing;
25 using namespace ngraph;
26 using namespace ngraph::pass;
27
28
29 class GroupConvolutionTestValues {
30 public:
31     class Actual {
32     public:
33         ngraph::element::Type precisionBeforeDequantization;
34         ngraph::builder::subgraph::DequantizationOperations dequantization;
35         std::shared_ptr<ngraph::opset1::Constant> weights;
36         builder::subgraph::FakeQuantizeOnWeights fakeQuantizeOnWeights;
37     };
38
39     class Expected {
40     public:
41         ngraph::element::Type precisionBeforeDequantization;
42         ngraph::builder::subgraph::DequantizationOperations dequantizationBefore;
43         std::shared_ptr<ngraph::opset1::Constant> weights;
44         builder::subgraph::FakeQuantizeOnWeights fakeQuantizeOnWeights;
45         ngraph::element::Type precisionAfterOperation;
46         ngraph::builder::subgraph::DequantizationOperations dequantizationAfter;
47         ngraph::element::Type precisionAfterDequantization;
48     };
49
50     low_precision::LayerTransformation::Params params;
51     ngraph::Shape inputShape;
52     ngraph::Shape outputShape;
53     size_t group;
54     Actual actual;
55     Expected expected;
56 };
57
58 class GroupConvolutionTransformation : public LayerTransformation, public testing::WithParamInterface<GroupConvolutionTestValues> {
59 public:
60     void SetUp() override {
61         const GroupConvolutionTestValues testValues = GetParam();
62
63         actualFunction = ngraph::builder::subgraph::GroupConvolutionFunction::getOriginal(
64             testValues.actual.precisionBeforeDequantization,
65             testValues.inputShape,
66             testValues.outputShape,
67             testValues.group,
68             testValues.actual.dequantization,
69             testValues.actual.weights,
70             testValues.actual.fakeQuantizeOnWeights);
71
72         SimpleLowPrecisionTransformer transform;
73         transform.add<ngraph::pass::low_precision::GroupConvolutionTransformation, ngraph::opset1::GroupConvolution>(testValues.params);
74         transform.transform(actualFunction);
75
76         referenceFunction = ngraph::builder::subgraph::GroupConvolutionFunction::getReference(
77             testValues.expected.precisionBeforeDequantization,
78             testValues.inputShape,
79             testValues.outputShape,
80             testValues.group,
81             testValues.expected.dequantizationBefore,
82             testValues.expected.weights,
83             testValues.expected.fakeQuantizeOnWeights,
84             testValues.expected.precisionAfterOperation,
85             testValues.expected.dequantizationAfter,
86             testValues.expected.precisionAfterDequantization);
87     }
88
89     static std::string getTestCaseName(testing::TestParamInfo<GroupConvolutionTestValues> obj) {
90         GroupConvolutionTestValues testValues = obj.param;
91
92         std::ostringstream result;
93         result << toString(testValues.params) << "_" <<
94             testValues.inputShape << "_" <<
95             testValues.outputShape << "_" <<
96             testValues.group << "_" <<
97             testValues.actual.precisionBeforeDequantization << "_" <<
98             testValues.actual.dequantization << "_" << "_weights_" <<
99             testValues.actual.weights->get_element_type() << "_" << "{ " <<
100             testValues.actual.weights->cast_vector<float>()[0] << " }_" <<
101             testValues.actual.fakeQuantizeOnWeights << "_";
102         return result.str();
103     }
104 };
105
106 TEST_P(GroupConvolutionTransformation, CompareFunctions) {
107     actualFunction->validate_nodes_and_infer_types();
108     auto res = compare_functions(referenceFunction, actualFunction, true, true, true);
109     ASSERT_TRUE(res.first) << res.second;
110 }
111
112 const std::vector<GroupConvolutionTestValues> testValues = {
113     // group convolution, tensor quantization, with zero point
114     {
115         LayerTransformation::createParamsU8I8().setSupportAsymmetricQuantization(true),
116         { 1, 6, 224, 224 },
117         { 1, 24, 218, 218 },
118         3ul,
119         // ActualValues
120         {
121             ngraph::element::u8,
122             {{ngraph::element::f32}, { 128.f }, { 0.02f }},
123             op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector<float>{ 2.f }),
124             { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } }
125         },
126         // ExpectedValues
127         {
128             ngraph::element::u8,
129             {{}, { { 128.f }, ngraph::element::f32, { 1, 6, 1, 1 }, false }, {}},
130             op::Constant::create(ngraph::element::i8, ngraph::Shape{}, std::vector<float>{ -125.f }),
131             {},
132             ngraph::element::f32,
133             {{}, {}, {{ 0.0002f }, ngraph::element::f32, { 24, 1, 1 }}} // 0.0002 = 0.02 (on data) * 0.01 (on weights)
134         }
135     },
136     // group convolution, tensor quantization, with zero point
137     {
138         LayerTransformation::createParamsU8I8().setSupportAsymmetricQuantization(false),
139         { 1, 6, 224, 224 },
140         { 1, 24, 218, 218 },
141         3ul,
142         // ActualValues
143         {
144             ngraph::element::u8,
145             {{ngraph::element::f32}, { 128.f }, { 0.02f }},
146             op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector<float>{ 2.f }),
147             { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } }
148         },
149         // ExpectedValues
150         {
151             ngraph::element::u8,
152             {{ ngraph::element::f32 }, { 128.f }, { 0.02f }},
153             op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector<float>{ 2.f }),
154             { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } },
155             ngraph::element::f32,
156             {}
157         }
158     },
159     // group convolution, tensor quantization, with zero point
160     {
161         LayerTransformation::createParamsU8I8().setUpdatePrecisions(false),
162         { 1, 6, 224, 224 },
163         { 1, 24, 218, 218 },
164         3ul,
165         // ActualValues
166         {
167             ngraph::element::f32,
168             {{}, { 128.f }, { 0.02f }},
169             op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector<float>{ 2.f }),
170             { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } }
171         },
172         // ExpectedValues
173         {
174             ngraph::element::f32,
175             {{}, { { 128.f }, ngraph::element::f32, { 1, 6, 1, 1 }, false }, {}},
176             op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector<float>{ -125.f }),
177             {},
178             ngraph::element::f32,
179             {{}, {}, {{ 0.0002f }, ngraph::element::f32, { 24, 1, 1 }}} // 0.0002 = 0.02 (on data) * 0.01 (on weights)
180         }
181     },
182     // group convolution, per-channel quantization with different values, without zero point
183     {
184         LayerTransformation::createParamsU8I8(),
185         { 1, 6, 224, 224 },
186         { 1, 24, 218, 218 },
187         3ul,
188         // ActualValues
189         {
190             ngraph::element::u8,
191             {
192                 {ngraph::element::f32},
193                 {},
194                 {{ 0.02f, 0.02f, 0.04f, 0.04f, 0.08f, 0.08f }, ngraph::element::f32, {1, 6, 1, 1}}
195             },
196             op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector<float>{ 2.f }),
197             { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } }
198         },
199         // ExpectedValues
200         {
201             ngraph::element::u8,
202             {},
203             op::Constant::create(ngraph::element::i8, ngraph::Shape{}, std::vector<float>{ -125.f }),
204             {},
205             ngraph::element::f32,
206             {
207                 {},
208                 {},
209                 {
210                     {
211                         // 0.0002 = 0.02 (on data) * 0.01 (on weights)
212                         0.0002f, 0.0002f, 0.0002f, 0.0002f, 0.0002f, 0.0002f, 0.0002f, 0.0002f,
213                         // 0.0004 = 0.04 (on data) * 0.01 (on weights)
214                         0.0004f, 0.0004f, 0.0004f, 0.0004f, 0.0004f, 0.0004f, 0.0004f, 0.0004f,
215                         // 0.0008 = 0.08 (on data) * 0.01 (on weights)
216                         0.0008f, 0.0008f, 0.0008f, 0.0008f, 0.0008f, 0.0008f, 0.0008f, 0.0008f
217                     },
218                     ngraph::element::f32, {24, 1, 1}
219                 }
220             },
221         }
222     },
223     // group convolution, per-channel quantization with the same values, without zero point
224     {
225         LayerTransformation::createParamsU8I8(),
226         { 1, 6, 224, 224 },
227         { 1, 24, 218, 218 },
228         3ul,
229         // ActualValues
230         {
231             ngraph::element::u8,
232             {
233                 {ngraph::element::f32},
234                 {},
235                 {{ 0.02f }, ngraph::element::f32, {1, 6, 1, 1}}
236             },
237             op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector<float>{ 2.f }),
238             { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } }
239         },
240         // ExpectedValues
241         {
242             ngraph::element::u8,
243             {},
244             op::Constant::create(ngraph::element::i8, ngraph::Shape{}, std::vector<float>{ -125.f }),
245             {},
246             ngraph::element::f32,
247             {
248                 {},
249                 {},
250                 {{ 0.0002f }, ngraph::element::f32, {24, 1, 1}}
251             },
252         }
253     },
254     // group convolution, without zero point, without convert
255     {
256         LayerTransformation::createParamsU8I8(),
257         { 1, 6, 224, 224 },
258         { 1, 24, 218, 218 },
259         3ul,
260         // ActualValues
261         {
262             ngraph::element::f32,
263             {{}, {}, { 0.02f }},
264             op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector<float>{ 2.f }),
265             { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } }
266         },
267         // ExpectedValues
268         {
269             ngraph::element::f32,
270             {{}, {}, { 0.02f }},
271             op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector<float>{ 2.f }),
272             { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } },
273             ngraph::element::f32,
274             {}
275         }
276     },
277     // group convolution, without zero point
278     {
279         LayerTransformation::createParamsU8I8(),
280         { 1, 6, 224, 224 },
281         { 1, 24, 218, 218 },
282         3ul,
283         // ActualValues
284         {
285             ngraph::element::u8,
286             {{element::f32}, {}, { 0.02f }},
287             op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector<float>{ 2.f }),
288             { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } }
289         },
290         // ExpectedValues
291         {
292             ngraph::element::u8,
293             {},
294             op::Constant::create(ngraph::element::i8, ngraph::Shape{}, std::vector<float>{ -125.f }),
295             {},
296             ngraph::element::f32,
297             {{}, {}, {{ 0.0002f }, ngraph::element::f32, { 24, 1, 1 }}}
298         }
299     },
300     // depth-wise convolution, tensor quantization, with zero point
301     {
302         LayerTransformation::createParamsU8I8(),
303         { 1, 6, 224, 224 },
304         { 1, 6, 218, 218 },
305         3ul,
306         // ActualValues
307         {
308             ngraph::element::u8,
309             {{ngraph::element::f32}, { 128.f }, { 0.02f }},
310             op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector<float>{ 2.f }),
311             { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } }
312         },
313         // ExpectedValues
314         {
315             ngraph::element::u8,
316             {{}, { { 128.f }, ngraph::element::f32, { 1, 6, 1, 1 }, false }, {}},
317             op::Constant::create(ngraph::element::i8, ngraph::Shape{}, std::vector<float>{ -125.f }),
318             {},
319             ngraph::element::f32,
320             {{}, {}, {{ 0.0002f }, ngraph::element::f32, { 6, 1, 1 }}}
321         }
322     },
323     // depth-wise convolution, tensor quantization, with zero point
324     {
325         LayerTransformation::createParamsU8I8().setUpdatePrecisions(false),
326         { 1, 6, 224, 224 },
327         { 1, 6, 218, 218 },
328         3ul,
329         // ActualValues
330         {
331             ngraph::element::f32,
332             {{}, { 128.f }, { 0.02f }},
333             op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector<float>{ 2.f }),
334             { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } }
335         },
336         // ExpectedValues
337         {
338             ngraph::element::f32,
339             {{}, { { 128.f }, ngraph::element::f32, { 1, 6, 1, 1 }, false }, {}},
340             op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector<float>{ -125.f }),
341             {},
342             ngraph::element::f32,
343             {{}, {}, {{ 0.0002f }, ngraph::element::f32, { 6, 1, 1 }}}
344         }
345     },
346     // depth-wise convolution, per-channel quantization with different values, without zero point
347     {
348         LayerTransformation::createParamsU8I8(),
349         { 1, 6, 224, 224 },
350         { 1, 6, 218, 218 },
351         6ul,
352         // ActualValues
353         {
354             ngraph::element::u8,
355             {
356                 {ngraph::element::f32},
357                 {},
358                 {{ 0.02f, 0.02f, 0.04f, 0.04f, 0.08f, 0.08f }, ngraph::element::f32, {1, 6, 1, 1}}
359             },
360             op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector<float>{ 2.f }),
361             { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } }
362         },
363         // ExpectedValues
364         {
365             ngraph::element::u8,
366             {},
367             op::Constant::create(ngraph::element::i8, ngraph::Shape{}, std::vector<float>{ -125.f }),
368             {},
369             ngraph::element::f32,
370             {
371                 {},
372                 {},
373                 {
374                     {
375                         0.0002f, 0.0002f,  // 0.0002 = 0.02 (on data) * 0.01 (on weights)
376                         0.0004f, 0.0004f,  // 0.0004 = 0.04 (on data) * 0.01 (on weights)
377                         0.0008f, 0.0008f   // 0.0008 = 0.08 (on data) * 0.01 (on weights)
378                     },
379                     ngraph::element::f32, {6, 1, 1}
380                 }
381             },
382         }
383     },
384     // depth-wise convolution, per-channel quantization with the same values, without zero point
385     {
386         LayerTransformation::createParamsU8I8(),
387         { 1, 6, 224, 224 },
388         { 1, 6, 218, 218 },
389         6ul,
390         // ActualValues
391         {
392             ngraph::element::u8,
393             {
394                 {ngraph::element::f32},
395                 {},
396                 {{ 0.02f }, ngraph::element::f32, {1, 6, 1, 1}}
397             },
398             op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector<float>{ 2.f }),
399             { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } }
400         },
401         // ExpectedValues
402         {
403             ngraph::element::u8,
404             {},
405             op::Constant::create(ngraph::element::i8, ngraph::Shape{}, std::vector<float>{ -125.f }),
406             {},
407             ngraph::element::f32,
408             {
409                 {},
410                 {},
411                 {{ 0.0002f }, ngraph::element::f32, {6, 1, 1}}
412             },
413         }
414     },
415     // depth-wise convolution, without zero point, without convert
416     {
417         LayerTransformation::createParamsU8I8(),
418         { 1, 6, 224, 224 },
419         { 1, 6, 218, 218 },
420         6ul,
421         // ActualValues
422         {
423             ngraph::element::f32,
424             {{}, {}, { 0.02f }},
425             op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector<float>{ 2.f }),
426             { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } }
427         },
428         // ExpectedValues
429         {
430             ngraph::element::f32,
431             {{}, {}, { 0.02f }},
432             op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector<float>{ 2.f }),
433             { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } },
434             ngraph::element::f32,
435             {}
436         }
437     },
438     // depth-wise convolution, without zero point
439     {
440         LayerTransformation::createParamsU8I8(),
441         { 1, 6, 224, 224 },
442         { 1, 6, 218, 218 },
443         6ul,
444         // ActualValues
445         {
446             ngraph::element::u8,
447             {{element::f32}, {}, { 0.02f }},
448             op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector<float>{ 2.f }),
449             { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } }
450         },
451         // ExpectedValues
452         {
453             ngraph::element::u8,
454             {},
455             op::Constant::create(ngraph::element::i8, ngraph::Shape{}, std::vector<float>{ -125.f }),
456             {},
457             ngraph::element::f32,
458             {{}, {}, {{ 0.0002f }, ngraph::element::f32, { 6, 1, 1 }}}
459         }
460     },
461     // without dequantization operations
462     {
463         LayerTransformation::createParamsU8I8(),
464         { 1, 6, 224, 224 },
465         { 1, 6, 218, 218 },
466         6ul,
467         // ActualValues
468         {
469             ngraph::element::f32,
470             {},
471             op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector<float>{ 2.f }),
472             { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } }
473         },
474         // ExpectedValues
475         {
476             ngraph::element::f32,
477             {},
478             op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector<float>{ 2.f }),
479             { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } },
480             ngraph::element::f32,
481             {}
482         }
483     },
484 };
485
486 INSTANTIATE_TEST_CASE_P(
487     LPT,
488     GroupConvolutionTransformation,
489     ::testing::ValuesIn(testValues),
490     GroupConvolutionTransformation::getTestCaseName);