1 // Copyright (C) 2020 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
5 #include "ngraph_functions/low_precision_transformations/add_function.hpp"
6 #include "low_precision/network_helper.hpp"
8 #include <ngraph/opsets/opset1.hpp>
9 #include "ngraph_functions/builders.hpp"
10 #include "ngraph_functions/subgraph_builders.hpp"
12 using namespace ngraph::pass::low_precision;
18 std::shared_ptr<ngraph::Function> AddFunction::getOriginal(
19 const ngraph::element::Type precision,
20 const ngraph::Shape& inputShape,
22 const ngraph::pass::low_precision::LayerTransformation::Params& params,
23 const ngraph::element::Type& precision1,
24 const ngraph::builder::subgraph::DequantizationOperations& dequantization1,
25 const ngraph::element::Type& precision2,
26 const ngraph::builder::subgraph::DequantizationOperations& dequantization2,
28 const std::vector<float>& constValues,
29 const std::string& additionalLayer) {
30 std::shared_ptr<ngraph::Node> input1;
31 if (constInput == 0) {
32 input1 = std::make_shared<ngraph::opset1::Constant>(
37 input1 = std::make_shared<ngraph::opset1::Parameter>(
39 broadcast ? ngraph::Shape({ inputShape[0], inputShape[1], 1, 1 }) : ngraph::Shape(inputShape));
42 const auto dequantizationOp1 = is_type<ngraph::opset1::Constant>(input1) ? input1 : makeDequantization(input1, dequantization1);
44 std::shared_ptr<ngraph::Node> input2;
45 if (constInput == 1) {
46 input2 = std::make_shared<ngraph::opset1::Constant>(
51 input2 = std::make_shared<ngraph::opset1::Parameter>(
52 precision2, ngraph::Shape(inputShape));
55 if (additionalLayer == "convolution") {
56 parent = std::make_shared<ngraph::op::TypeRelaxed<ngraph::opset1::Convolution>>(
57 std::vector<element::Type>{ element::f32, element::f32 },
58 std::vector<element::Type>{ element::f32 },
59 ngraph::op::TemporaryReplaceOutputType(parent, element::f32).get(),
60 ngraph::op::TemporaryReplaceOutputType(
61 std::make_shared<ngraph::opset1::Constant>(element::i8, Shape{ 1, 4, 1, 1 }, std::vector<float>{0.8f, 0.8f, 0.8f, 0.8f}),
63 ngraph::Strides{ 1, 1 },
64 ngraph::CoordinateDiff{ 0, 0 },
65 ngraph::CoordinateDiff{ 0, 0 },
66 ngraph::Strides{ 1, 1 });
68 if (additionalLayer == "group_convolution") {
69 parent = std::make_shared< ngraph::op::TypeRelaxed<ngraph::opset1::GroupConvolution>>(
70 std::vector<element::Type>{ element::f32, element::f32 },
71 std::vector<element::Type>{ element::f32 },
72 ngraph::op::TemporaryReplaceOutputType(parent, element::f32).get(),
73 ngraph::op::TemporaryReplaceOutputType(
74 std::make_shared<ngraph::opset1::Constant>(element::i8, Shape{ 4, 1, 1, 1, 1 }, std::vector<float>{0.8f, 0.8f, 0.8f, 0.8f}),
76 ngraph::Strides{ 1, 1 },
77 ngraph::CoordinateDiff{ 0, 0 },
78 ngraph::CoordinateDiff{ 0, 0 },
79 ngraph::Strides{ 1, 1 });
81 if (additionalLayer != "") {
82 parent = std::make_shared<ngraph::opset1::Add>(
84 std::make_shared<ngraph::opset1::Constant>(element::f32, Shape{ 1, 1, 1, 1 }, std::vector<float>{1.f}));
85 parent = ngraph::builder::subgraph::makeFakeQuantizeTypeRelaxed(
88 {256, Shape{}, { 0 }, { 255 }, { 0 }, { 255 }, element::u8});
90 const auto dequantizationOp2 = is_type<ngraph::opset1::Constant>(parent) ? parent : makeDequantization(parent, dequantization2);
92 const auto add = std::make_shared<ngraph::opset1::Add>(dequantizationOp1, dequantizationOp2);
94 add->set_friendly_name("output");
96 ngraph::ResultVector results{ std::make_shared<ngraph::opset1::Result>(add) };
97 ngraph::ParameterVector parameters;
98 if (constInput == -1) {
99 parameters = { as_type_ptr<ngraph::opset1::Parameter>(input1), as_type_ptr<ngraph::opset1::Parameter>(input2) };
100 } else if (constInput == 0) {
101 parameters = { as_type_ptr<ngraph::opset1::Parameter>(input2) };
102 } else if (constInput == 1) {
103 parameters = { as_type_ptr<ngraph::opset1::Parameter>(input1) };
105 THROW_IE_EXCEPTION << "Unexpected constant input index";
107 return std::make_shared<ngraph::Function>(results, parameters, "AddTransformation");
110 std::shared_ptr<ngraph::Function> AddFunction::getReference(
111 const ngraph::element::Type precision,
112 const ngraph::Shape& inputShape,
113 const bool broadcast,
114 const ngraph::pass::low_precision::LayerTransformation::Params& params,
115 const ngraph::element::Type& precision1,
116 const ngraph::builder::subgraph::DequantizationOperations& dequantization1,
117 const ngraph::element::Type& precision2,
118 const ngraph::builder::subgraph::DequantizationOperations& dequantization2,
119 const ngraph::builder::subgraph::DequantizationOperations& dequantizationAfter,
120 const int constInputIndex,
121 const std::vector<float>& constValues,
122 const std::string& additionalLayer,
123 const std::string& operationType) {
124 std::shared_ptr<ngraph::Node> input1;
125 if (constInputIndex == 0) {
126 input1 = std::make_shared<ngraph::opset1::Constant>(
131 input1 = std::make_shared<ngraph::opset1::Parameter>(
133 broadcast ? ngraph::Shape({ inputShape[0], inputShape[1], 1, 1 }) : ngraph::Shape(inputShape));
136 const auto dequantizationOp1 = is_type<ngraph::opset1::Constant>(input1) ? input1 : makeDequantization(input1, dequantization1);
138 std::shared_ptr<ngraph::Node> input2;
139 if (constInputIndex == 1) {
140 input2 = std::make_shared<ngraph::opset1::Constant>(
145 input2 = std::make_shared<ngraph::opset1::Parameter>(
146 precision2, ngraph::Shape(inputShape));
148 auto parent = input2;
149 if (additionalLayer == "convolution") {
150 parent = std::make_shared<ngraph::op::TypeRelaxed<ngraph::opset1::Convolution>>(
151 std::vector<element::Type>{ element::f32, element::f32 },
152 std::vector<element::Type>{ element::f32 },
153 ngraph::op::TemporaryReplaceOutputType(parent, element::f32).get(),
154 ngraph::op::TemporaryReplaceOutputType(
155 std::make_shared<ngraph::opset1::Constant>(element::i8, Shape{ 1, 4, 1, 1 }, std::vector<float>{0.8f, 0.8f, 0.8f, 0.8f}),
157 ngraph::Strides{ 1, 1 },
158 ngraph::CoordinateDiff{ 0, 0 },
159 ngraph::CoordinateDiff{ 0, 0 },
160 ngraph::Strides{ 1, 1 });
162 if (additionalLayer == "group_convolution") {
163 parent = std::make_shared< ngraph::op::TypeRelaxed<ngraph::opset1::GroupConvolution>>(
164 std::vector<element::Type>{ element::f32, element::f32 },
165 std::vector<element::Type>{ element::f32 },
166 ngraph::op::TemporaryReplaceOutputType(parent, element::f32).get(),
167 ngraph::op::TemporaryReplaceOutputType(
168 std::make_shared<ngraph::opset1::Constant>(element::i8, Shape{ 4, 1, 1, 1, 1 }, std::vector<float>{0.8f, 0.8f, 0.8f, 0.8f}),
170 ngraph::Strides{ 1, 1 },
171 ngraph::CoordinateDiff{ 0, 0 },
172 ngraph::CoordinateDiff{ 0, 0 },
173 ngraph::Strides{ 1, 1 });
175 if (additionalLayer != "") {
176 parent = std::make_shared<ngraph::opset1::Add>(
178 std::make_shared<ngraph::opset1::Constant>(element::f32, Shape{ 1, 1, 1, 1 }, std::vector<float>{1.f}));
179 parent = ngraph::builder::subgraph::makeFakeQuantizeTypeRelaxed(
181 ngraph::element::f32,
182 {256, Shape{}, { 0 }, { 255 }, { 0 }, { 255 }, element::u8});
184 const auto dequantizationOp2 = is_type<ngraph::opset1::Constant>(parent) ? parent : makeDequantization(parent, dequantization2);
186 const std::shared_ptr<Node> add = operationType == "Add" ?
187 std::dynamic_pointer_cast<Node>(std::make_shared<ngraph::op::TypeRelaxed<ngraph::opset1::Add>>(
188 std::vector<element::Type>{ element::f32, element::f32 },
189 std::vector<element::Type>{},
190 ngraph::op::TemporaryReplaceOutputType(dequantizationOp1, element::f32).get(),
191 ngraph::op::TemporaryReplaceOutputType(dequantizationOp2, element::f32).get())) :
192 std::make_shared<ngraph::op::TypeRelaxed<DequantizationSubtract>>(
193 std::vector<element::Type>{ element::f32, element::f32 },
194 std::vector<element::Type>{},
195 ngraph::op::TemporaryReplaceOutputType(dequantizationOp1, element::f32).get(),
196 ngraph::op::TemporaryReplaceOutputType(dequantizationOp2, element::f32).get());
198 NetworkHelper::setOutDataPrecisionForTypeRelaxed(add, precision);
200 const auto dequantizationOpAfter = makeDequantization(add, dequantizationAfter);
202 dequantizationOpAfter->set_friendly_name("output");
204 ngraph::ResultVector results{ std::make_shared<ngraph::opset1::Result>(dequantizationOpAfter) };
205 ngraph::ParameterVector parameters;
206 if (constInputIndex == -1) {
207 parameters = { as_type_ptr<ngraph::opset1::Parameter>(input1), as_type_ptr<ngraph::opset1::Parameter>(input2) };
208 } else if (constInputIndex == 0) {
209 parameters = { as_type_ptr<ngraph::opset1::Parameter>(input2) };
210 } else if (constInputIndex == 1) {
211 parameters = { as_type_ptr<ngraph::opset1::Parameter>(input1) };
213 THROW_IE_EXCEPTION << "Unexpected constant input index";
215 return std::make_shared<ngraph::Function>(results, parameters, "AddTransformation");
218 } // namespace subgraph
219 } // namespace builder
220 } // namespace ngraph