1 // Copyright (C) 2020 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
5 #include "ngraph_functions/low_precision_transformations/concat_function.hpp"
7 #include <ngraph/opsets/opset1.hpp>
8 #include "ngraph_ops/type_relaxed.hpp"
9 #include "low_precision/network_helper.hpp"
11 #include "ngraph_functions/subgraph_builders.hpp"
12 #include "ngraph_functions/low_precision_transformations/common/fake_quantize_on_data.hpp"
13 #include "ngraph_functions/low_precision_transformations/common/dequantization_operations.hpp"
14 #include "ngraph_functions/low_precision_transformations/common/builders.hpp"
20 using namespace ngraph::pass;
22 std::shared_ptr<ngraph::Function> ConcatFunction::getOriginal(
23 const ngraph::element::Type precision,
24 const ngraph::Shape& inputShape,
25 const FakeQuantizeOnData& fqOnData1,
26 const FakeQuantizeOnData& fqOnData2) {
27 const auto input1 = std::make_shared<ngraph::opset1::Parameter>(precision, inputShape);
28 input1->set_friendly_name("input1");
29 const auto fakeQuantize1 = makeFakeQuantize(input1, precision, fqOnData1);
31 const std::vector<size_t> inputShape2 = inputShape;
32 const auto input2 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape2));
33 input2->set_friendly_name("input2");
34 const auto fakeQuantize2 = makeFakeQuantize(input2, precision, fqOnData2);
36 const std::shared_ptr<ngraph::opset1::Concat> concat = std::make_shared<ngraph::opset1::Concat>(
37 ngraph::OutputVector{ fakeQuantize1->output(0), fakeQuantize2->output(0) }, 1);
38 concat->set_friendly_name("output");
39 auto& rtInfo = concat->get_rt_info();
40 rtInfo["Variant::std::string"] = std::make_shared<VariantWrapper<std::string>>("concat");
42 ngraph::ResultVector results{ std::make_shared<ngraph::opset1::Result>(concat) };
43 std::shared_ptr<ngraph::Function> function = std::make_shared<ngraph::Function>(
45 ngraph::ParameterVector{ input1, input2 },
46 "ConcatTransformation");
51 std::shared_ptr<ngraph::Function> ConcatFunction::getOriginal(
52 const ngraph::element::Type precision,
53 const ngraph::Shape& inputShape,
54 const FakeQuantizeOnDataWithConstant& fqOnData1,
55 const FakeQuantizeOnDataWithConstant& fqOnData2) {
56 const auto input1 = std::make_shared<ngraph::opset1::Parameter>(precision, inputShape);
57 input1->set_friendly_name("input1");
58 const auto fakeQuantize1 = makeFakeQuantize(input1, precision, fqOnData1);
60 const std::vector<size_t> inputShape2 = inputShape;
61 const auto input2 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape2));
62 input2->set_friendly_name("input2");
63 const auto fakeQuantize2 = makeFakeQuantize(input2, precision, fqOnData2);
65 const std::shared_ptr<ngraph::opset1::Concat> concat = std::make_shared<ngraph::opset1::Concat>(
66 ngraph::OutputVector{ fakeQuantize1->output(0), fakeQuantize2->output(0) }, 1);
67 concat->set_friendly_name("output");
69 auto& rtInfo = concat->get_rt_info();
70 rtInfo["Variant::std::string"] = std::make_shared<VariantWrapper<std::string>>("concat");
72 ngraph::ResultVector results{ std::make_shared<ngraph::opset1::Result>(concat) };
73 std::shared_ptr<ngraph::Function> function = std::make_shared<ngraph::Function>(
75 ngraph::ParameterVector{ input1, input2 },
76 "ConcatTransformation");
81 std::shared_ptr<ngraph::Function> ConcatFunction::getOriginalWithNeighbors(
82 const ngraph::element::Type precision,
83 const ngraph::Shape& inputShape,
84 const FakeQuantizeOnData& fqOnData1,
85 const FakeQuantizeOnData& fqOnData2,
86 const FakeQuantizeOnData& fqOnData3) {
87 const auto input1 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape));
88 input1->set_friendly_name("input1");
89 const auto fakeQuantize1 = makeFakeQuantize(input1, precision, fqOnData1);
90 fakeQuantize1->set_friendly_name("fakeQuantize1");
92 const auto input2 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape));
93 input2->set_friendly_name("input2");
94 const auto fakeQuantize2 = makeFakeQuantize(input2, precision, fqOnData2);
95 fakeQuantize2->set_friendly_name("fakeQuantize2");
97 const auto input3 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape));
98 input3->set_friendly_name("input3");
99 const auto fakeQuantize3 = makeFakeQuantize(input3, precision, fqOnData3);
100 fakeQuantize3->set_friendly_name("fakeQuantize3");
102 const auto concat1 = std::make_shared<ngraph::opset1::Concat>(
103 ngraph::OutputVector { fakeQuantize1->output(0), fakeQuantize2->output(0) },
105 concat1->set_friendly_name("concat1");
107 auto& rtInfo1 = concat1->get_rt_info();
108 rtInfo1["Variant::std::string"] = std::make_shared<VariantWrapper<std::string>>("concat1");
110 const auto concat2 = std::make_shared<ngraph::opset1::Concat>(
111 ngraph::OutputVector { fakeQuantize2->output(0), fakeQuantize3->output(0) },
113 concat2->set_friendly_name("concat2");
115 auto& rtInfo2 = concat2->get_rt_info();
116 rtInfo2["Variant::std::string"] = std::make_shared<VariantWrapper<std::string>>("concat2");
118 const ngraph::ResultVector results {
119 std::make_shared<ngraph::opset1::Result>(concat1),
120 std::make_shared<ngraph::opset1::Result>(concat2)
123 std::shared_ptr<ngraph::Function> function = std::make_shared<ngraph::Function>(
125 ngraph::ParameterVector { input1, input2, input3 },
126 "ConcatWithNeighborsTransformation");
131 std::shared_ptr<ngraph::Function> ConcatFunction::getOriginalWithIntermediate(
132 const ngraph::element::Type precision,
133 const ngraph::Shape& inputShape,
134 const bool transparentIntermediate,
135 const FakeQuantizeOnData& fqOnData1,
136 const FakeQuantizeOnData& fqOnData2) {
137 const std::vector<size_t> inputShape1 = {
140 inputShape[2] - (transparentIntermediate ? 2 : 0),
141 inputShape[3] - (transparentIntermediate ? 2 : 0)
144 const auto input1 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape1));
145 input1->set_friendly_name("input1");
146 const auto fakeQuantize1 = makeFakeQuantize(input1, precision, fqOnData1);
147 fakeQuantize1->set_friendly_name("fakeQuantize1");
149 const std::vector<size_t> inputShape2 = { inputShape[0], inputShape[1], inputShape[2], inputShape[3] };
150 const auto input2 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape2));
151 input2->set_friendly_name("input2");
153 const auto fakeQuantize2 = makeFakeQuantize(input2, precision, fqOnData2);
154 fakeQuantize2->set_friendly_name("fakeQuantize2");
156 const std::vector<size_t> kernel = { 3, 3 };
157 const std::vector<size_t> stride = { 1, 1 };
158 const std::vector<size_t> padBegin = { 0, 0 };
159 const std::vector<size_t> padEnd = { 0, 0 };
160 const ngraph::op::PadType padType = ngraph::op::PadType::NOTSET;
161 const ngraph::op::RoundingType roundingType = ngraph::op::RoundingType::FLOOR;
162 std::shared_ptr<ngraph::op::Op> intermediateOp;
164 if (transparentIntermediate) {
165 intermediateOp = std::make_shared<ngraph::opset1::MaxPool>(
166 fakeQuantize2->output(0),
174 auto weights = ngraph::opset1::Constant::create(
176 ngraph::Shape{ inputShape[1], inputShape[1], 1, 1 },
177 std::vector<float>(inputShape[1] * inputShape[1], 1));
179 intermediateOp = std::make_shared<ngraph::opset1::Convolution>(
180 fakeQuantize2->output(0),
182 ngraph::Strides{ 1, 1 },
183 ngraph::CoordinateDiff{ 0, 0 },
184 ngraph::CoordinateDiff{ 0, 0 },
185 ngraph::Strides{ 1, 1 });
188 intermediateOp->set_friendly_name("intermediate");
190 const std::shared_ptr<ngraph::opset1::Concat> concat = std::make_shared<ngraph::opset1::Concat>(
191 ngraph::OutputVector{ fakeQuantize1->output(0), intermediateOp->output(0) }, 1);
192 concat->set_friendly_name("concat");
194 auto& rtInfo = concat->get_rt_info();
195 rtInfo["Variant::std::string"] = std::make_shared<VariantWrapper<std::string>>("concat");
197 auto weights = ngraph::opset1::Constant::create(precision, ngraph::Shape{ inputShape[1], inputShape[1], 1, 1 }, { 1 });
198 auto convolution = std::make_shared<ngraph::opset1::Convolution>(
201 ngraph::Strides { 1, 1 },
202 ngraph::CoordinateDiff { 0, 0 },
203 ngraph::CoordinateDiff { 0, 0 },
204 ngraph::Strides { 1, 1 });
205 convolution->set_friendly_name("convolution");
207 ngraph::ResultVector results {
208 std::make_shared<ngraph::opset1::Result>(concat),
209 std::make_shared<ngraph::opset1::Result>(convolution)
212 std::shared_ptr<ngraph::Function> function = std::make_shared<ngraph::Function>(
214 ngraph::ParameterVector{ input1, input2 },
215 "ConcatWithIntermediateTransformation");
220 std::shared_ptr<ngraph::Function> ConcatFunction::getOriginalWithSplitedIntermediate(
221 const ngraph::element::Type precision,
222 const ngraph::Shape& inputShape,
223 const FakeQuantizeOnData& fqOnData1,
224 const FakeQuantizeOnData& fqOnData2) {
226 size_t splitedAxis = 1;
229 const std::vector<size_t> inputShape1 = {
231 inputShape[1] / numSplit,
236 const auto input1 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape1));
237 input1->set_friendly_name("input1");
238 const auto fakeQuantize1 = makeFakeQuantize(input1, precision, fqOnData1);
239 fakeQuantize1->set_friendly_name("fakeQuantize1");
241 const std::vector<size_t> inputShape2 = { inputShape[0], inputShape[1], inputShape[2], inputShape[3] };
242 const auto input2 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape2));
243 input2->set_friendly_name("input2");
245 const auto fakeQuantize2 = makeFakeQuantize(input2, precision, fqOnData2);
246 fakeQuantize2->set_friendly_name("fakeQuantize2");
248 std::shared_ptr<ngraph::op::Op> intermediateOp;
250 const auto constant = std::make_shared<ngraph::opset1::Constant>(element::i64, Shape{ }, splitedAxis);
251 intermediateOp = std::make_shared<ngraph::opset1::Split>(fakeQuantize2->output(0), constant, numSplit);
253 intermediateOp->set_friendly_name("intermediate");
255 const std::shared_ptr<ngraph::opset1::Concat> concat = std::make_shared<ngraph::opset1::Concat>(
256 ngraph::OutputVector{ fakeQuantize1->output(0), intermediateOp->output(0) }, splitedAxis);
257 concat->set_friendly_name("concat");
259 auto& rtInfo = concat->get_rt_info();
260 rtInfo["Variant::std::string"] = std::make_shared<VariantWrapper<std::string>>("concat");
262 auto weights = ngraph::opset1::Constant::create(precision, ngraph::Shape{ inputShape[1] / numSplit, inputShape[1] / numSplit, 1, 1 }, { 1 });
263 auto convolution = std::make_shared<ngraph::opset1::Convolution>(
264 intermediateOp->output(1),
266 ngraph::Strides{ 1, 1 },
267 ngraph::CoordinateDiff{ 0, 0 },
268 ngraph::CoordinateDiff{ 0, 0 },
269 ngraph::Strides{ 1, 1 });
270 convolution->set_friendly_name("convolution");
272 ngraph::ResultVector results{
273 std::make_shared<ngraph::opset1::Result>(concat),
274 std::make_shared<ngraph::opset1::Result>(convolution),
277 std::shared_ptr<ngraph::Function> function = std::make_shared<ngraph::Function>(
279 ngraph::ParameterVector{ input1, input2 },
280 "ConcatWithIntermediateTransformation");
285 std::shared_ptr<ngraph::Function> ConcatFunction::getOriginalSelectionWithIntermediate(
286 const ngraph::element::Type precision,
287 const ngraph::Shape& inputShape,
288 const bool transparentIntermediate,
289 const FakeQuantizeOnData& fqOnData1,
290 const FakeQuantizeOnData& fqOnData2) {
291 const std::vector<size_t> inputShape1 = {
294 inputShape[2] - (transparentIntermediate ? 2 : 0),
295 inputShape[3] - (transparentIntermediate ? 2 : 0)
298 const auto input1 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape1));
299 input1->set_friendly_name("input1");
300 const auto fakeQuantize1 = makeFakeQuantize(input1, precision, fqOnData1);
301 fakeQuantize1->set_friendly_name("fakeQuantize1");
303 const std::vector<size_t> inputShape2 = { inputShape[0], inputShape[1], inputShape[2], inputShape[3] };
304 const auto input2 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape2));
305 input2->set_friendly_name("input2");
307 const auto fakeQuantize2 = makeFakeQuantize(input2, precision, fqOnData2);
308 fakeQuantize2->set_friendly_name("fakeQuantize2");
310 const std::vector<size_t> kernel = { 3, 3 };
311 const std::vector<size_t> stride = { 1, 1 };
312 const std::vector<size_t> padBegin = { 0, 0 };
313 const std::vector<size_t> padEnd = { 0, 0 };
314 const ngraph::op::PadType padType = ngraph::op::PadType::NOTSET;
315 const ngraph::op::RoundingType roundingType = ngraph::op::RoundingType::FLOOR;
316 std::shared_ptr<ngraph::op::Op> intermediateOp;
318 if (transparentIntermediate) {
319 intermediateOp = std::make_shared<ngraph::opset1::MaxPool>(
320 fakeQuantize2->output(0),
328 auto weights = ngraph::opset1::Constant::create(
330 ngraph::Shape{ inputShape[1], inputShape[1], 1, 1 },
331 std::vector<float>(inputShape[1] * inputShape[1], 1));
333 intermediateOp = std::make_shared<ngraph::opset1::Convolution>(
334 fakeQuantize2->output(0),
336 ngraph::Strides{ 1, 1 },
337 ngraph::CoordinateDiff{ 0, 0 },
338 ngraph::CoordinateDiff{ 0, 0 },
339 ngraph::Strides{ 1, 1 });
342 intermediateOp->set_friendly_name("intermediate");
344 const std::shared_ptr<ngraph::opset1::Concat> concat = std::make_shared<ngraph::opset1::Concat>(
345 ngraph::OutputVector{ fakeQuantize1->output(0), intermediateOp->output(0) }, 1);
346 concat->set_friendly_name("concat");
348 auto& rtInfo = concat->get_rt_info();
349 rtInfo["Variant::std::string"] = std::make_shared<VariantWrapper<std::string>>("concat");
351 auto weights = ngraph::opset1::Constant::create(precision, ngraph::Shape{ inputShape[1], inputShape[1], 1, 1 }, { 1 });
352 auto convolution = std::make_shared<ngraph::opset1::Convolution>(
355 ngraph::Strides { 1, 1 },
356 ngraph::CoordinateDiff { 0, 0 },
357 ngraph::CoordinateDiff { 0, 0 },
358 ngraph::Strides { 1, 1 });
359 convolution->set_friendly_name("convolution");
361 ngraph::ResultVector results {
362 std::make_shared<ngraph::opset1::Result>(concat),
363 std::make_shared<ngraph::opset1::Result>(convolution)
366 std::shared_ptr<ngraph::Function> function = std::make_shared<ngraph::Function>(
368 ngraph::ParameterVector{ input1, input2 },
369 "ConcatWithIntermediateTransformation");
374 std::shared_ptr<ngraph::Function> ConcatFunction::getOriginalWithDifferentPrecisionOnChilds(
375 const ngraph::element::Type precision,
376 const ngraph::Shape& inputShape,
377 const FakeQuantizeOnData& fqOnData1,
378 const FakeQuantizeOnData& fqOnData2) {
379 const auto input1 = std::make_shared<ngraph::opset1::Parameter>(precision, inputShape);
380 input1->set_friendly_name("input1");
381 const auto fakeQuantize1 = makeFakeQuantize(input1, precision, fqOnData1);
383 const std::vector<size_t> inputShape2 = inputShape;
384 const auto input2 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape2));
385 input2->set_friendly_name("input2");
386 const auto fakeQuantize2 = makeFakeQuantize(input2, precision, fqOnData2);
388 const std::shared_ptr<ngraph::opset1::Concat> concat = std::make_shared<ngraph::opset1::Concat>(
389 ngraph::OutputVector{ fakeQuantize1->output(0), fakeQuantize2->output(0) }, 1);
391 auto& rtInfo = concat->get_rt_info();
392 rtInfo["Variant::std::string"] = std::make_shared<VariantWrapper<std::string>>("concat");
394 const std::vector<size_t> kernel = { 3, 3 };
395 const std::vector<size_t> stride = { 1, 1 };
396 const std::vector<size_t> padBegin = { 0, 0 };
397 const std::vector<size_t> padEnd = { 0, 0 };
398 const ngraph::op::PadType padType = ngraph::op::PadType::NOTSET;
399 const ngraph::op::RoundingType roundingType = ngraph::op::RoundingType::FLOOR;
401 const auto avgPool = std::make_shared<ngraph::opset1::AvgPool>(
410 avgPool->set_friendly_name("AvgPool");
412 const auto maxPool = std::make_shared<ngraph::opset1::MaxPool>(
420 maxPool->set_friendly_name("MaxPool");
422 ngraph::ResultVector results;
423 results.push_back(std::make_shared<ngraph::opset1::Result>(avgPool));
424 results.push_back(std::make_shared<ngraph::opset1::Result>(maxPool));
426 std::shared_ptr<ngraph::Function> function = std::make_shared<ngraph::Function>(
428 ngraph::ParameterVector{ input1, input2 },
429 "ConcatWithDifferentChildsTransformation");
434 std::shared_ptr<ngraph::Function> ConcatFunction::getOriginalWithIntermediateWithConstant(
435 const ngraph::element::Type precision,
436 const ngraph::Shape& inputShape,
437 const bool transparentIntermediate,
438 const FakeQuantizeOnData& fqOnData1,
439 const FakeQuantizeOnData& fqOnData2) {
440 const auto input1 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape));
441 input1->set_friendly_name("input");
442 const auto fakeQuantize1 = makeFakeQuantizeTypeRelaxed(input1, precision, fqOnData1);
443 fakeQuantize1->set_friendly_name("fakeQuantize1");
445 const auto input2 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape));
446 input2->set_friendly_name("input");
447 const auto fakeQuantize2 = makeFakeQuantizeTypeRelaxed(input2, precision, fqOnData2);
448 fakeQuantize2->set_friendly_name("fakeQuantize2");
451 std::shared_ptr<ngraph::op::Op> intermediateOp;
453 if (transparentIntermediate) {
454 const std::vector<size_t> kernel = { 3, 3 };
455 const std::vector<size_t> stride = { 1, 1 };
456 const std::vector<size_t> padBegin = { 0, 0 };
457 const std::vector<size_t> padEnd = { 0, 0 };
458 const ngraph::op::PadType padType = ngraph::op::PadType::NOTSET;
459 const ngraph::op::RoundingType roundingType = ngraph::op::RoundingType::FLOOR;
461 const auto pooling = std::make_shared<ngraph::opset1::MaxPool>(
462 fakeQuantize1->output(0),
470 ngraph::op::v0::InterpolateAttrs attributes;
471 attributes.axes = ngraph::AxisSet{ 2, 3 };
472 attributes.mode = "nearest";
473 attributes.align_corners = false;
474 attributes.antialias = false;
475 attributes.pads_begin = { 0 };
476 attributes.pads_end = { 0 };
477 const auto outputShape = op::Constant::create(
478 ngraph::element::i64, ngraph::Shape{ 2 },
479 ngraph::Shape{ inputShape[2], inputShape[3] });
480 intermediateOp = std::make_shared<ngraph::opset1::Interpolate>(pooling->output(0), outputShape, attributes);
481 intermediateOp->set_friendly_name("intermediate");
483 intermediateOp = fakeQuantize1;
486 const std::shared_ptr<ngraph::opset1::Concat> concat = std::make_shared<ngraph::opset1::Concat>(
487 ngraph::OutputVector{ fakeQuantize2->output(0), intermediateOp->output(0) }, 1);
488 concat->set_friendly_name("concat");
490 auto& rtInfo = concat->get_rt_info();
491 rtInfo["Variant::std::string"] = std::make_shared<VariantWrapper<std::string>>("concat");
493 ngraph::ResultVector results{
494 std::make_shared<ngraph::opset1::Result>(concat),
497 std::shared_ptr<ngraph::Function> function = std::make_shared<ngraph::Function>(
499 ngraph::ParameterVector{ input1, input2 },
500 "ConcatWithIntermediateWithConstantTransformation");
505 std::shared_ptr<ngraph::Function> ConcatFunction::getReference(
506 const ngraph::element::Type precision,
507 const ngraph::Shape& inputShape,
508 const FakeQuantizeOnData& fqOnData1,
509 const FakeQuantizeOnData& fqOnData2,
510 const DequantizationOperations& dequantizationOperations) {
511 const auto input1 = std::make_shared<ngraph::opset1::Parameter>(precision, inputShape);
512 input1->set_friendly_name("input1");
513 const auto fakeQuantize1 = ngraph::builder::subgraph::makeFakeQuantizeTypeRelaxed(input1, precision, fqOnData1);
515 const std::vector<size_t> inputShape2 = inputShape;
516 const auto input2 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape2));
517 input2->set_friendly_name("input2");
518 const auto fakeQuantize2 = ngraph::builder::subgraph::makeFakeQuantizeTypeRelaxed(input2, precision, fqOnData2);
520 const std::shared_ptr<ngraph::opset1::Concat> concat = std::make_shared<ngraph::op::TypeRelaxed<ngraph::opset1::Concat>>(
521 ngraph::OutputVector{ fakeQuantize1->output(0), fakeQuantize2->output(0) }, 1);
522 auto& rtInfo = concat->get_rt_info();
523 rtInfo["Variant::std::string"] = std::make_shared<VariantWrapper<std::string>>("concat");
525 const std::shared_ptr<ngraph::Node> lastDequantization = makeDequantization(concat, dequantizationOperations);
526 lastDequantization->set_friendly_name("output");
528 ngraph::ResultVector results{ std::make_shared<ngraph::opset1::Result>(lastDequantization) };
529 std::shared_ptr<ngraph::Function> function = std::make_shared<ngraph::Function>(
531 ngraph::ParameterVector{ input1, input2 },
532 "ConcatTransformation");
534 if (fqOnData1.outputPrecision != fqOnData2.outputPrecision) {
535 THROW_IE_EXCEPTION << "FakeQuantize expected precisions are different";
537 const ngraph::element::Type fqOnDataPrecision = fqOnData1.outputPrecision;
538 if (fqOnDataPrecision != ngraph::element::undefined) {
539 if (fakeQuantize1->get_output_element_type(0) != fakeQuantize2->get_output_element_type(0)) {
540 THROW_IE_EXCEPTION << "FakeQuantize operation precisions are different";
542 const ngraph::element::Type fakeQuantizePrecision = fakeQuantize1->get_output_element_type(0);
544 if (fqOnDataPrecision != fakeQuantizePrecision) {
545 ngraph::pass::low_precision::NetworkHelper::setOutDataPrecision(fakeQuantize1, fqOnDataPrecision);
546 ngraph::pass::low_precision::NetworkHelper::setOutDataPrecision(fakeQuantize2, fqOnDataPrecision);
547 ngraph::pass::low_precision::NetworkHelper::setOutDataPrecision(concat, fqOnDataPrecision);
554 std::shared_ptr<ngraph::Function> ConcatFunction::getReference(
555 const ngraph::element::Type precision,
556 const ngraph::Shape& inputShape,
557 const FakeQuantizeOnDataWithConstant& fqOnData1,
558 const FakeQuantizeOnDataWithConstant& fqOnData2,
559 const DequantizationOperations& dequantizationOperations) {
560 const auto input1 = std::make_shared<ngraph::opset1::Parameter>(precision, inputShape);
561 input1->set_friendly_name("input1");
562 const auto fakeQuantize1 = ngraph::builder::subgraph::makeFakeQuantizeTypeRelaxed(input1, precision, fqOnData1);
564 const std::vector<size_t> inputShape2 = inputShape;
565 const auto input2 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape2));
566 input2->set_friendly_name("input2");
567 const auto fakeQuantize2 = ngraph::builder::subgraph::makeFakeQuantizeTypeRelaxed(input2, precision, fqOnData2);
569 const std::shared_ptr<ngraph::opset1::Concat> concat = std::make_shared<ngraph::op::TypeRelaxed<ngraph::opset1::Concat>>(
570 ngraph::OutputVector{ fakeQuantize1->output(0), fakeQuantize2->output(0) }, 1);
572 auto& rtInfo = concat->get_rt_info();
573 rtInfo["Variant::std::string"] = std::make_shared<VariantWrapper<std::string>>("concat");
575 const std::shared_ptr<ngraph::Node> lastDequantization = makeDequantization(concat, dequantizationOperations);
576 lastDequantization->set_friendly_name("output");
578 ngraph::ResultVector results{ std::make_shared<ngraph::opset1::Result>(lastDequantization) };
579 std::shared_ptr<ngraph::Function> function = std::make_shared<ngraph::Function>(
581 ngraph::ParameterVector{ input1, input2 },
582 "ConcatTransformation");
584 if (fqOnData1.outputPrecision != fqOnData2.outputPrecision) {
585 THROW_IE_EXCEPTION << "FakeQuantize expected precisions are different";
587 const ngraph::element::Type fqOnDataPrecision = fqOnData1.outputPrecision;
588 if (fqOnDataPrecision != ngraph::element::undefined) {
589 if (fakeQuantize1->get_output_element_type(0) != fakeQuantize2->get_output_element_type(0)) {
590 THROW_IE_EXCEPTION << "FakeQuantize operation precisions are different";
592 const ngraph::element::Type fakeQuantizePrecision = fakeQuantize1->get_output_element_type(0);
594 if (fqOnDataPrecision != fakeQuantizePrecision) {
595 ngraph::pass::low_precision::NetworkHelper::setOutDataPrecision(fakeQuantize1, fqOnDataPrecision);
596 ngraph::pass::low_precision::NetworkHelper::setOutDataPrecision(fakeQuantize2, fqOnDataPrecision);
597 ngraph::pass::low_precision::NetworkHelper::setOutDataPrecision(concat, fqOnDataPrecision);
604 std::shared_ptr<ngraph::Function> ConcatFunction::getReferenceWithNeighbors(
605 const ngraph::element::Type precision,
606 const ngraph::Shape& inputShape,
607 const FakeQuantizeOnData& fqOnData1,
608 const FakeQuantizeOnData& fqOnData2,
609 const FakeQuantizeOnData& fqOnData3,
610 const DequantizationOperations& dequantizationOperations1,
611 const DequantizationOperations& dequantizationOperations2) {
612 const auto input1 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape));
613 input1->set_friendly_name("input1");
614 const auto fakeQuantize1 = makeFakeQuantizeTypeRelaxed(input1, precision, fqOnData1);
615 fakeQuantize1->set_friendly_name("fakeQuantize1");
617 const auto input2 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape));
618 input2->set_friendly_name("input2");
619 const auto fakeQuantize2 = makeFakeQuantizeTypeRelaxed(input2, precision, fqOnData2);
620 fakeQuantize2->set_friendly_name("fakeQuantize2");
622 const auto input3 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape));
623 input3->set_friendly_name("input3");
624 const auto fakeQuantize3 = makeFakeQuantizeTypeRelaxed(input3, precision, fqOnData3);
625 fakeQuantize3->set_friendly_name("fakeQuantize3");
627 const auto concat1 = std::make_shared<ngraph::opset1::Concat>(
628 ngraph::OutputVector { fakeQuantize1->output(0), fakeQuantize2->output(0) },
630 concat1->set_friendly_name("concat1");
632 auto& rtInfo1 = concat1->get_rt_info();
633 rtInfo1["Variant::std::string"] = std::make_shared<VariantWrapper<std::string>>("concat1");
635 const auto concat2 = std::make_shared<ngraph::opset1::Concat>(
636 ngraph::OutputVector { fakeQuantize2->output(0), fakeQuantize3->output(0) },
638 concat2->set_friendly_name("concat2");
640 auto& rtInfo2 = concat2->get_rt_info();
641 rtInfo2["Variant::std::string"] = std::make_shared<VariantWrapper<std::string>>("concat2");
643 const std::shared_ptr<ngraph::Node> lastDequantization1 = makeDequantization(concat1, dequantizationOperations1);
644 lastDequantization1->set_friendly_name("concat1");
646 const std::shared_ptr<ngraph::Node> lastDequantization2 = makeDequantization(concat2, dequantizationOperations2);
647 lastDequantization2->set_friendly_name("concat2");
649 const ngraph::ResultVector results {
650 std::make_shared<ngraph::opset1::Result>(lastDequantization1),
651 std::make_shared<ngraph::opset1::Result>(lastDequantization2)
654 std::shared_ptr<ngraph::Function> function = std::make_shared<ngraph::Function>(
656 ngraph::ParameterVector { input1, input2, input3 },
657 "ConcatWithNeighborsTransformation");
659 if ((fqOnData1.outputPrecision != fqOnData2.outputPrecision) || (fqOnData2.outputPrecision != fqOnData3.outputPrecision)) {
660 THROW_IE_EXCEPTION << "FakeQuantize expected precisions are different";
662 const ngraph::element::Type fqOnDataPrecision = fqOnData1.outputPrecision;
663 if (fqOnDataPrecision != ngraph::element::undefined) {
664 if ((fakeQuantize1->get_output_element_type(0) != fakeQuantize2->get_output_element_type(0)) ||
665 (fakeQuantize2->get_output_element_type(0) != fakeQuantize3->get_output_element_type(0))) {
666 THROW_IE_EXCEPTION << "FakeQuantize operation precisions are different";
668 const ngraph::element::Type fakeQuantizePrecision = fakeQuantize1->get_output_element_type(0);
670 if (fqOnDataPrecision != fakeQuantizePrecision) {
671 ngraph::pass::low_precision::NetworkHelper::setOutDataPrecision(fakeQuantize1, fqOnDataPrecision);
672 ngraph::pass::low_precision::NetworkHelper::setOutDataPrecision(fakeQuantize2, fqOnDataPrecision);
673 ngraph::pass::low_precision::NetworkHelper::setOutDataPrecision(fakeQuantize3, fqOnDataPrecision);
674 ngraph::pass::low_precision::NetworkHelper::setOutDataPrecision(concat1, fqOnDataPrecision);
675 ngraph::pass::low_precision::NetworkHelper::setOutDataPrecision(concat2, fqOnDataPrecision);
682 std::shared_ptr<ngraph::Function> ConcatFunction::getReferenceWithIntermediate(
683 const ngraph::element::Type precision,
684 const ngraph::Shape& inputShape,
685 const bool transparentIntermediate,
686 const FakeQuantizeOnData& fqOnData1,
687 const FakeQuantizeOnData& fqOnData2,
688 const DequantizationOperations& dequantizationOperations1,
689 const DequantizationOperations& dequantizationOperations2) {
690 const std::vector<size_t> inputShape1 = {
693 inputShape[2] - (transparentIntermediate ? 2 : 0),
694 inputShape[3] - (transparentIntermediate ? 2 : 0)
697 const auto input1 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape1));
698 input1->set_friendly_name("input1");
699 const auto fakeQuantize1 = makeFakeQuantizeTypeRelaxed(input1, precision, fqOnData1);
700 fakeQuantize1->set_friendly_name("fakeQuantize1");
702 const std::vector<size_t> inputShape2 = { inputShape[0], inputShape[1], inputShape[2], inputShape[3] };
703 const auto input2 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape2));
704 input2->set_friendly_name("input2");
706 const auto fakeQuantize2 = makeFakeQuantizeTypeRelaxed(input2, precision, fqOnData2);
707 fakeQuantize2->set_friendly_name("fakeQuantize2");
709 const std::vector<size_t> kernel = { 3, 3 };
710 const std::vector<size_t> stride = { 1, 1 };
711 const std::vector<size_t> padBegin = { 0, 0 };
712 const std::vector<size_t> padEnd = { 0, 0 };
713 const ngraph::op::PadType padType = ngraph::op::PadType::NOTSET;
714 const ngraph::op::RoundingType roundingType = ngraph::op::RoundingType::FLOOR;
715 std::shared_ptr<Node> intermediateOp;
717 if (transparentIntermediate) {
718 intermediateOp = std::make_shared<ngraph::opset1::MaxPool>(
719 fakeQuantize2->output(0),
727 auto weights = ngraph::opset1::Constant::create(
729 ngraph::Shape{ inputShape[1], inputShape[1], 1, 1 },
730 std::vector<float>(inputShape[1] * inputShape[1], 1));
732 intermediateOp = std::make_shared<ngraph::opset1::Convolution>(
733 fakeQuantize2->output(0),
735 ngraph::Strides{ 1, 1 },
736 ngraph::CoordinateDiff{ 0, 0 },
737 ngraph::CoordinateDiff{ 0, 0 },
738 ngraph::Strides{ 1, 1 });
741 intermediateOp->set_friendly_name("intermediate");
743 const std::shared_ptr<ngraph::opset1::Concat> concat = std::make_shared<ngraph::opset1::Concat>(
744 ngraph::OutputVector { fakeQuantize1->output(0), intermediateOp->output(0) },
746 concat->set_friendly_name("concat");
748 auto& rtInfo = concat->get_rt_info();
749 rtInfo["Variant::std::string"] = std::make_shared<VariantWrapper<std::string>>("concat");
751 const std::shared_ptr<ngraph::Node> lastDequantization1 = dequantizationOperations1.empty() ?
753 makeDequantization(concat, dequantizationOperations1);
754 lastDequantization1->set_friendly_name("concat");
756 const std::shared_ptr<ngraph::Node> lastDequantization2 = dequantizationOperations2.empty() ?
758 makeDequantization(intermediateOp, dequantizationOperations2);
760 auto weights = ngraph::opset1::Constant::create(precision, ngraph::Shape{ inputShape[1], inputShape[1], 1, 1 }, { 1 });
761 auto convolution = std::make_shared<ngraph::opset1::Convolution>(
762 lastDequantization2 == nullptr ? intermediateOp : lastDequantization2,
764 ngraph::Strides{ 1, 1 },
765 ngraph::CoordinateDiff{ 0, 0 },
766 ngraph::CoordinateDiff{ 0, 0 },
767 ngraph::Strides{ 1, 1 });
768 convolution->set_friendly_name("convolution");
770 ngraph::ResultVector results {
771 std::make_shared<ngraph::opset1::Result>(lastDequantization1),
772 std::make_shared<ngraph::opset1::Result>(convolution)
775 std::shared_ptr<ngraph::Function> function = std::make_shared<ngraph::Function>(
777 ngraph::ParameterVector{ input1, input2 },
778 "ConcatWithIntermediateTransformation");
780 if ((fqOnData1.outputPrecision != fqOnData2.outputPrecision)) {
781 THROW_IE_EXCEPTION << "FakeQuantize expected precisions are different";
783 const ngraph::element::Type fqOnDataPrecision = fqOnData1.outputPrecision;
784 if (fqOnDataPrecision != ngraph::element::undefined) {
785 if (fakeQuantize1->get_output_element_type(0) != fakeQuantize2->get_output_element_type(0)) {
786 THROW_IE_EXCEPTION << "FakeQuantize operation precisions are different";
788 const ngraph::element::Type fakeQuantizePrecision = fakeQuantize1->get_output_element_type(0);
790 if (fqOnDataPrecision != fakeQuantizePrecision) {
791 ngraph::pass::low_precision::NetworkHelper::setOutDataPrecision(fakeQuantize1, fqOnDataPrecision);
792 ngraph::pass::low_precision::NetworkHelper::setOutDataPrecision(fakeQuantize2, fqOnDataPrecision);
793 ngraph::pass::low_precision::NetworkHelper::setOutDataPrecision(concat, fqOnDataPrecision);
795 auto intermediateOpTr = std::dynamic_pointer_cast<ngraph::op::TypeRelaxedBase>(intermediateOp);
796 if (intermediateOpTr != nullptr) {
797 ngraph::pass::low_precision::NetworkHelper::setOutDataPrecisionForTypeRelaxed(intermediateOp, fqOnDataPrecision);
799 // set precision to explicitly to have updated precision during transformation
800 for (size_t i = 0; i < intermediateOp->get_output_size(); ++i) {
801 intermediateOp->set_output_type(i, fqOnDataPrecision, intermediateOp->get_output_partial_shape(i));
810 std::shared_ptr<ngraph::Function> ConcatFunction::getReferenceWithSplitedIntermediate(
811 const ngraph::element::Type precision,
812 const ngraph::Shape& inputShape,
813 const FakeQuantizeOnData& fqOnData1,
814 const FakeQuantizeOnData& fqOnData2,
815 const DequantizationOperations& dequantizationOperations1,
816 const DequantizationOperations& dequantizationOperations2) {
818 size_t splitedAxis = 1;
820 const std::vector<size_t> inputShape1 = {
822 inputShape[1] / numSplit,
827 const auto input1 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape1));
828 input1->set_friendly_name("input1");
829 const auto fakeQuantize1 = makeFakeQuantizeTypeRelaxed(input1, precision, fqOnData1);
830 fakeQuantize1->set_friendly_name("fakeQuantize1");
833 const std::vector<size_t> inputShape2 = { inputShape[0], inputShape[1], inputShape[2], inputShape[3] };
834 const auto input2 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape2));
835 input2->set_friendly_name("input2");
836 const auto fakeQuantize2 = makeFakeQuantizeTypeRelaxed(input2, precision, fqOnData2);
837 fakeQuantize2->set_friendly_name("fakeQuantize2");
839 const ngraph::element::Type fqOnDataPrecision = fqOnData1.outputPrecision;
840 if (fqOnDataPrecision != ngraph::element::undefined) {
841 ngraph::pass::low_precision::NetworkHelper::setOutDataPrecision(fakeQuantize1, fqOnDataPrecision);
842 ngraph::pass::low_precision::NetworkHelper::setOutDataPrecision(fakeQuantize2, fqOnDataPrecision);
845 std::shared_ptr<ngraph::op::Op> intermediateOp;
847 const auto constant = std::make_shared<ngraph::opset1::Constant>(element::i64, Shape{ }, splitedAxis);
848 intermediateOp = std::make_shared<ngraph::opset1::Split>(fakeQuantize2->output(0), constant, numSplit);
850 intermediateOp->set_friendly_name("intermediate");
852 const std::shared_ptr<ngraph::opset1::Concat> concat = std::make_shared<ngraph::opset1::Concat>(
853 ngraph::OutputVector{ fakeQuantize1->output(0), intermediateOp->output(0) }, splitedAxis);
854 concat->set_friendly_name("concat");
856 auto& rtInfo = concat->get_rt_info();
857 rtInfo["Variant::std::string"] = std::make_shared<VariantWrapper<std::string>>("concat");
859 const std::shared_ptr<ngraph::Node> lastDequantization1 = dequantizationOperations1.empty() ?
861 makeDequantization(concat, dequantizationOperations1);
863 const std::shared_ptr<ngraph::Node> lastDequantization2 = dequantizationOperations2.empty() ?
865 makeDequantization(intermediateOp->output(1), dequantizationOperations2);
867 auto weights = ngraph::opset1::Constant::create(
869 ngraph::Shape{ inputShape[1] / numSplit, inputShape[1] / numSplit, 1, 1 }, { 1 });
871 auto convolution = std::make_shared<ngraph::opset1::Convolution>(
872 lastDequantization2 == nullptr ? intermediateOp : lastDequantization2,
874 ngraph::Strides{ 1, 1 },
875 ngraph::CoordinateDiff{ 0, 0 },
876 ngraph::CoordinateDiff{ 0, 0 },
877 ngraph::Strides{ 1, 1 });
878 convolution->set_friendly_name("convolution");
880 ngraph::ResultVector results{
881 std::make_shared<ngraph::opset1::Result>(lastDequantization1),
882 std::make_shared<ngraph::opset1::Result>(convolution)
885 std::shared_ptr<ngraph::Function> function = std::make_shared<ngraph::Function>(
887 ngraph::ParameterVector{ input1, input2 },
888 "ConcatWithIntermediateTransformation");
890 if ((fqOnData1.outputPrecision != fqOnData2.outputPrecision)) {
891 THROW_IE_EXCEPTION << "FakeQuantize expected precisions are different";
893 if (fqOnDataPrecision != ngraph::element::undefined) {
894 if (fakeQuantize1->get_output_element_type(0) != fakeQuantize2->get_output_element_type(0)) {
895 THROW_IE_EXCEPTION << "FakeQuantize operation precisions are different";
902 std::shared_ptr<ngraph::Function> ConcatFunction::getReferenceSelectionWithIntermediate(
903 const ngraph::element::Type precision,
904 const ngraph::Shape& inputShape,
905 const bool transparentIntermediate,
906 const FakeQuantizeOnData& fqOnData1,
907 const FakeQuantizeOnData& fqOnData2,
908 const DequantizationOperations& dequantizationOperations1,
909 const DequantizationOperations& dequantizationOperations2) {
910 const std::vector<size_t> inputShape1 = {
913 inputShape[2] - (transparentIntermediate ? 2 : 0),
914 inputShape[3] - (transparentIntermediate ? 2 : 0)
917 const auto input1 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape1));
918 input1->set_friendly_name("input1");
919 const auto fakeQuantize1 = makeFakeQuantizeTypeRelaxed(input1, precision, fqOnData1);
920 fakeQuantize1->set_friendly_name("fakeQuantize1");
922 const std::vector<size_t> inputShape2 = { inputShape[0], inputShape[1], inputShape[2], inputShape[3] };
923 const auto input2 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape2));
924 input2->set_friendly_name("input2");
926 const auto fakeQuantize2 = makeFakeQuantizeTypeRelaxed(input2, precision, fqOnData2);
927 fakeQuantize2->set_friendly_name("fakeQuantize2");
929 const std::vector<size_t> kernel = { 3, 3 };
930 const std::vector<size_t> stride = { 1, 1 };
931 const std::vector<size_t> padBegin = { 0, 0 };
932 const std::vector<size_t> padEnd = { 0, 0 };
933 const ngraph::op::PadType padType = ngraph::op::PadType::NOTSET;
934 const ngraph::op::RoundingType roundingType = ngraph::op::RoundingType::FLOOR;
935 std::shared_ptr<ngraph::op::Op> intermediateOp;
937 if (transparentIntermediate) {
938 intermediateOp = std::make_shared<ngraph::opset1::MaxPool>(
939 fakeQuantize2->output(0),
947 auto weights = ngraph::opset1::Constant::create(
949 ngraph::Shape{ inputShape[1], inputShape[1], 1, 1 },
950 std::vector<float>(inputShape[1] * inputShape[1], 1));
952 intermediateOp = std::make_shared<ngraph::opset1::Convolution>(
953 fakeQuantize2->output(0),
955 ngraph::Strides{ 1, 1 },
956 ngraph::CoordinateDiff{ 0, 0 },
957 ngraph::CoordinateDiff{ 0, 0 },
958 ngraph::Strides{ 1, 1 });
961 intermediateOp->set_friendly_name("intermediate");
963 const std::shared_ptr<ngraph::opset1::Concat> concat = std::make_shared<ngraph::opset1::Concat>(
964 ngraph::OutputVector { fakeQuantize1->output(0), intermediateOp->output(0) },
966 concat->set_friendly_name("concat");
968 auto& rtInfo = concat->get_rt_info();
969 rtInfo["Variant::std::string"] = std::make_shared<VariantWrapper<std::string>>("concat");
971 const std::shared_ptr<ngraph::Node> lastDequantization1 = dequantizationOperations1.empty() ?
973 makeDequantization(concat, dequantizationOperations1);
974 lastDequantization1->set_friendly_name("concat");
976 const std::shared_ptr<ngraph::Node> lastDequantization2 = dequantizationOperations2.empty() ?
978 makeDequantization(intermediateOp, dequantizationOperations2);
980 auto weights = ngraph::opset1::Constant::create(precision, ngraph::Shape{ inputShape[1], inputShape[1], 1, 1 }, { 1 });
981 auto convolution = std::make_shared<ngraph::opset1::Convolution>(
982 lastDequantization2 == nullptr ? intermediateOp : lastDequantization2,
984 ngraph::Strides{ 1, 1 },
985 ngraph::CoordinateDiff{ 0, 0 },
986 ngraph::CoordinateDiff{ 0, 0 },
987 ngraph::Strides{ 1, 1 });
988 convolution->set_friendly_name("convolution");
990 ngraph::ResultVector results {
991 std::make_shared<ngraph::opset1::Result>(lastDequantization1),
992 std::make_shared<ngraph::opset1::Result>(convolution)
995 std::shared_ptr<ngraph::Function> function = std::make_shared<ngraph::Function>(
997 ngraph::ParameterVector{ input1, input2 },
998 "ConcatWithIntermediateTransformation");
1000 if ((fqOnData1.outputPrecision != fqOnData2.outputPrecision)) {
1001 THROW_IE_EXCEPTION << "FakeQuantize expected precisions are different";
1003 const ngraph::element::Type fqOnDataPrecision = fqOnData1.outputPrecision;
1004 if (fqOnDataPrecision != ngraph::element::undefined) {
1005 if (fakeQuantize1->get_output_element_type(0) != fakeQuantize2->get_output_element_type(0)) {
1006 THROW_IE_EXCEPTION << "FakeQuantize operation precisions are different";
1008 const ngraph::element::Type fakeQuantizePrecision = fakeQuantize1->get_output_element_type(0);
1010 if (fqOnDataPrecision != fakeQuantizePrecision) {
1011 ngraph::pass::low_precision::NetworkHelper::setOutDataPrecision(fakeQuantize1, fqOnDataPrecision);
1012 ngraph::pass::low_precision::NetworkHelper::setOutDataPrecision(fakeQuantize2, fqOnDataPrecision);
1013 ngraph::pass::low_precision::NetworkHelper::setOutDataPrecision(concat, fqOnDataPrecision);
1015 auto intermediateOpTr = std::dynamic_pointer_cast<ngraph::op::TypeRelaxedBase>(intermediateOp);
1016 if (intermediateOpTr != nullptr) {
1017 ngraph::pass::low_precision::NetworkHelper::setOutDataPrecisionForTypeRelaxed(intermediateOp, fqOnDataPrecision);
1025 std::shared_ptr<ngraph::Function> ConcatFunction::getReferenceWithDifferentPrecisionOnChilds(
1026 const ngraph::element::Type precision,
1027 const ngraph::Shape& inputShape,
1028 const bool multiChannel,
1029 const FakeQuantizeOnData& fqOnData1,
1030 const FakeQuantizeOnData& fqOnData2,
1031 const DequantizationOperations& dequantizationOperations1,
1032 const DequantizationOperations& dequantizationOperations2) {
1033 const auto input1 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape));
1034 input1->set_friendly_name("input1");
1035 const auto fakeQuantize1 = makeFakeQuantizeTypeRelaxed(input1, precision, fqOnData1);
1036 fakeQuantize1->set_friendly_name("fakeQuantize1");
1038 const auto input2 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape));
1039 input2->set_friendly_name("input2");
1040 const auto fakeQuantize2 = makeFakeQuantizeTypeRelaxed(input2, precision, fqOnData2);
1041 fakeQuantize2->set_friendly_name("fakeQuantize2");
1043 const ngraph::element::Type fqOnDataPrecision = fqOnData1.outputPrecision;
1044 if (fqOnDataPrecision != ngraph::element::undefined) {
1045 ngraph::pass::low_precision::NetworkHelper::setOutDataPrecision(fakeQuantize1, fqOnDataPrecision);
1046 ngraph::pass::low_precision::NetworkHelper::setOutDataPrecision(fakeQuantize2, fqOnDataPrecision);
1049 const std::shared_ptr<ngraph::opset1::Concat> concat = std::make_shared<ngraph::opset1::Concat>(
1050 ngraph::OutputVector{ fakeQuantize1->output(0), fakeQuantize2->output(0) }, 1);
1051 concat->set_friendly_name("concat");
1053 auto& rtInfo = concat->get_rt_info();
1054 rtInfo["Variant::std::string"] = std::make_shared<VariantWrapper<std::string>>("concat");
1056 const auto lastDequantization1 = makeDequantization(concat->output(0), dequantizationOperations1);
1058 const std::vector<size_t> kernel = { 3, 3 };
1059 const std::vector<size_t> stride = { 1, 1 };
1060 const std::vector<size_t> padBegin = { 0, 0 };
1061 const std::vector<size_t> padEnd = { 0, 0 };
1062 const ngraph::op::PadType padType = ngraph::op::PadType::NOTSET;
1063 const ngraph::op::RoundingType roundingType = ngraph::op::RoundingType::FLOOR;
1065 const auto avgPool = std::make_shared<ngraph::opset1::AvgPool>(
1066 lastDequantization1,
1074 avgPool->set_friendly_name("AvgPool");
1076 ngraph::ResultVector results;
1077 results.push_back(std::make_shared<ngraph::opset1::Result>(avgPool));
1079 if (!dequantizationOperations2.empty()) {
1080 const std::shared_ptr<ngraph::opset1::MaxPool> maxPool = std::make_shared<ngraph::opset1::MaxPool>(
1089 const std::shared_ptr<ngraph::Node> lastDequantization2 = makeDequantization(maxPool, dequantizationOperations2);
1090 lastDequantization2->set_friendly_name("MaxPool");
1091 results.push_back(std::make_shared<ngraph::opset1::Result>(lastDequantization2));
1094 std::shared_ptr<ngraph::Function> function = std::make_shared<ngraph::Function>(
1096 ngraph::ParameterVector{ input1, input2 },
1097 "ConcatWithDifferentChildsTransformation");
1099 if ((fqOnData1.outputPrecision != fqOnData2.outputPrecision)) {
1100 THROW_IE_EXCEPTION << "FakeQuantize expected precisions are different";
1102 if (fqOnDataPrecision != ngraph::element::undefined) {
1103 if (fakeQuantize1->get_output_element_type(0) != fakeQuantize2->get_output_element_type(0)) {
1104 THROW_IE_EXCEPTION << "FakeQuantize operation precisions are different";
1111 std::shared_ptr<ngraph::Function> ConcatFunction::getReferenceWithIntermediateWithConstant(
1112 const ngraph::element::Type precision,
1113 const ngraph::Shape& inputShape,
1114 const bool transparentIntermediate,
1115 const FakeQuantizeOnData& fqOnData1,
1116 const FakeQuantizeOnData& fqOnData2,
1117 const ngraph::element::Type precisionBeforeOp,
1118 const DequantizationOperations& dequantizationBefore,
1119 const ngraph::element::Type precisionAfterOperation,
1120 const DequantizationOperations& dequantizationAfter,
1121 const ngraph::element::Type precisionAfterDequantization) {
1122 const auto input1 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape));
1123 input1->set_friendly_name("input");
1124 const auto fakeQuantize1 = makeFakeQuantizeTypeRelaxed(input1, precision, fqOnData1);
1125 fakeQuantize1->set_friendly_name("fakeQuantize1");
1126 ngraph::pass::low_precision::NetworkHelper::setOutDataPrecision(fakeQuantize1, precisionBeforeOp);
1128 const auto input2 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape));
1129 input2->set_friendly_name("input");
1130 const auto fakeQuantize2 = makeFakeQuantizeTypeRelaxed(input2, precision, fqOnData2);
1131 fakeQuantize2->set_friendly_name("fakeQuantize2");
1132 ngraph::pass::low_precision::NetworkHelper::setOutDataPrecision(fakeQuantize2, precisionBeforeOp);
1134 std::shared_ptr<Node> intermediateOp;
1136 if (transparentIntermediate) {
1137 const auto deqBefore = makeDequantization(fakeQuantize1->output(0), dequantizationBefore);
1138 const std::vector<size_t> kernel = { 3, 3 };
1139 const std::vector<size_t> stride = { 1, 1 };
1140 const std::vector<size_t> padBegin = { 0, 0 };
1141 const std::vector<size_t> padEnd = { 0, 0 };
1142 const ngraph::op::PadType padType = ngraph::op::PadType::NOTSET;
1143 const ngraph::op::RoundingType roundingType = ngraph::op::RoundingType::FLOOR;
1145 const auto pooling = std::make_shared<ngraph::opset1::MaxPool>(
1146 fakeQuantize1->output(0),
1154 ngraph::op::v0::InterpolateAttrs attributes;
1155 attributes.axes = ngraph::AxisSet{ 2, 3 };
1156 attributes.mode = "nearest";
1157 attributes.align_corners = false;
1158 attributes.antialias = false;
1159 attributes.pads_begin = { 0 };
1160 attributes.pads_end = { 0 };
1162 const auto outputShape = op::Constant::create(
1163 ngraph::element::i64, ngraph::Shape{ 2 },
1164 ngraph::Shape{ inputShape[2], inputShape[3] });
1165 intermediateOp = std::make_shared<ngraph::opset1::Interpolate>(pooling->output(0), outputShape, attributes);
1166 intermediateOp->set_friendly_name("intermediate");
1168 intermediateOp = fakeQuantize1;
1171 const std::shared_ptr<ngraph::opset1::Concat> concat = std::make_shared<ngraph::opset1::Concat>(
1172 ngraph::OutputVector{ fakeQuantize2->output(0), intermediateOp->output(0) },
1174 concat->set_friendly_name("concat");
1175 ngraph::pass::low_precision::NetworkHelper::setOutDataPrecision(concat, precisionAfterOperation);
1177 auto& rtInfo = concat->get_rt_info();
1178 rtInfo["Variant::std::string"] = std::make_shared<VariantWrapper<std::string>>("concat");
1180 const auto deqAfter = makeDequantization(concat->output(0), dequantizationAfter);
1181 deqAfter->set_friendly_name("concat");
1183 ngraph::ResultVector results{
1184 std::make_shared<ngraph::opset1::Result>(deqAfter)
1187 std::shared_ptr<ngraph::Function> function = std::make_shared<ngraph::Function>(
1189 ngraph::ParameterVector{ input1, input2 },
1190 "ConcatWithIntermediateTransformation");
1195 } // namespace subgraph
1196 } // namespace builder
1197 } // namespace ngraph