1 //
2 // Copyright © 2019 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5
6 #include "InstanceNormalizationEndToEndTestImpl.hpp"
7 #include "EndToEndTestImpl.hpp"
8 #include "ResolveType.hpp"
9
10 #include <armnnUtils/Permute.hpp>
11 #include <armnnUtils/DataLayoutIndexed.hpp>
12
13 #include <armnn/INetwork.hpp>
14
15 #include <armnnTestUtils/DataLayoutUtils.hpp>
16
17 #include <TestUtils.hpp>
18
19 #include <doctest/doctest.h>
20
21 namespace
22 {
23
24 template<typename armnn::DataType DataType>
CreateInstanceNormalizationNetwork(const armnn::TensorShape & inputShape,const armnn::TensorShape & outputShape,const armnn::DataLayout dataLayout,const float gamma,const float beta,const float eps,const float qScale=1.0f,const int32_t qOffset=0)25 armnn::INetworkPtr CreateInstanceNormalizationNetwork(const armnn::TensorShape& inputShape,
26 const armnn::TensorShape& outputShape,
27 const armnn::DataLayout dataLayout,
28 const float gamma,
29 const float beta,
30 const float eps,
31 const float qScale = 1.0f,
32 const int32_t qOffset = 0)
33 {
34 using namespace armnn;
35
36 // Builds up the structure of the network.
37 INetworkPtr net(INetwork::Create());
38
39 TensorInfo inputTensorInfo(inputShape, DataType, qScale, qOffset, true);
40
41 InstanceNormalizationDescriptor instanceNormalizationDesc;
42 instanceNormalizationDesc.m_Gamma = gamma;
43 instanceNormalizationDesc.m_Beta = beta;
44 instanceNormalizationDesc.m_Eps = eps;
45 instanceNormalizationDesc.m_DataLayout = dataLayout;
46
47 IConnectableLayer* instanceNormalization = net->AddInstanceNormalizationLayer(instanceNormalizationDesc,
48 "InstanceNormalization");
49 IConnectableLayer* input = net->AddInputLayer(0, "input");
50 Connect(input, instanceNormalization, inputTensorInfo, 0, 0);
51
52 TensorInfo outputTensorInfo(outputShape, DataType, qScale, qOffset);
53 IConnectableLayer* output = net->AddOutputLayer(0, "output");
54 Connect(instanceNormalization, output, outputTensorInfo, 0, 0);
55
56 return net;
57 }
58
InstanceNormalizationEndToEnd(const std::vector<armnn::BackendId> & backends,const armnn::DataLayout & dataLayout,armnn::TensorInfo & inputTensorInfo,armnn::TensorInfo & outputTensorInfo,std::vector<float> & inputData,std::vector<float> & expectedOutputData,const float gamma,const float beta,const float eps)59 void InstanceNormalizationEndToEnd(const std::vector<armnn::BackendId>& backends,
60 const armnn::DataLayout& dataLayout,
61 armnn::TensorInfo& inputTensorInfo,
62 armnn::TensorInfo& outputTensorInfo,
63 std::vector<float>& inputData,
64 std::vector<float>& expectedOutputData,
65 const float gamma,
66 const float beta,
67 const float eps)
68 {
69 using namespace armnn;
70
71 if (dataLayout == DataLayout::NCHW)
72 {
73 PermuteTensorNhwcToNchw<float>(inputTensorInfo, inputData);
74 PermuteTensorNhwcToNchw<float>(outputTensorInfo, expectedOutputData);
75 }
76
77 // Builds up the structure of the network
78 INetworkPtr net = CreateInstanceNormalizationNetwork<DataType::Float32>(inputTensorInfo.GetShape(),
79 outputTensorInfo.GetShape(),
80 dataLayout,
81 gamma,
82 beta,
83 eps);
84
85 CHECK(net);
86
87 std::map<int, std::vector<float>> inputTensorData = { { 0, inputData } };
88 std::map<int, std::vector<float>> expectedOutputTensorData = { { 0, expectedOutputData } };
89
90 EndToEndLayerTestImpl<DataType::Float32, DataType::Float32>(move(net),
91 inputTensorData,
92 expectedOutputTensorData,
93 backends);
94 }
95
96 } // anonymous namespace
97
InstanceNormalizationNhwcEndToEndTest1(const std::vector<armnn::BackendId> & defaultBackends)98 void InstanceNormalizationNhwcEndToEndTest1(const std::vector<armnn::BackendId>& defaultBackends)
99 {
100 using namespace armnn;
101
102 const float eps = 0.0001f;
103 const float beta = 0.0f;
104 const float gamma = 1.0f;
105
106 TensorShape inputShape{2, 2, 2, 2};
107 TensorInfo inputTensorInfo(inputShape, DataType::Float32, 0.0f, 0, true);
108
109 TensorShape outputShape{2, 2, 2, 2};
110 TensorInfo outputTensorInfo(outputShape, DataType::Float32);
111
112 std::vector<float> inputData = std::vector<float>(
113 {
114 // Batch 0, Height 0, Width 0 x Channel (2)
115 0.f, 1.f,
116 // Batch 0, Height 0, Width 1 x Channel (2)
117 0.f, 2.f,
118
119 // Batch 0, Height 1, Width 0 x Channel (2)
120 0.f, 2.f,
121 // Batch 0, Height 1, Width 1 x Channel (2)
122 0.f, 4.f,
123
124 // Batch 1, Height 0, Width 0 x Channel (2)
125 1.f, -1.f,
126 // Batch 1, Height 0, Width 1 x Channel (2)
127 -1.f, 2.f,
128
129 // Batch 1, Height 1, Width 0 x Channel (2)
130 -1.f, -2.f,
131 // Batch 1, Height 1, Width 1 x Channel (2)
132 1.f, 4.f
133 });
134
135 std::vector<float> expectedOutputData = std::vector<float>(
136 {
137 // Batch 0, Height 0, Width 0 x Channel (2)
138 0.f, -1.1470304f,
139 // Batch 0, Height 0, Width 1 x Channel (2)
140 0.f, -0.22940612f,
141 // Batch 0, Height 1, Width 0 x Channel (2)
142 0.f, -0.22940612f,
143 // Batch 0, Height 1, Width 1 x Channel (2)
144 0.f, 1.6058424f,
145
146 // Batch 1, Height 0, Width 0 x Channel (2)
147 0.99995005f, -0.7337929f,
148 // Batch 1, Height 0, Width 1 x Channel (2)
149 -0.99995005f, 0.52413774f,
150
151 // Batch 1, Height 1, Width 0 x Channel (2)
152 -0.99995005f, -1.1531031f,
153 // Batch 1, Height 1, Width 1 x Channel (2)
154 0.99995005f, 1.3627582f
155 });
156
157 InstanceNormalizationEndToEnd(defaultBackends,
158 DataLayout::NHWC,
159 inputTensorInfo,
160 outputTensorInfo,
161 inputData,
162 expectedOutputData,
163 gamma,
164 beta,
165 eps);
166 }
167
InstanceNormalizationNchwEndToEndTest1(const std::vector<armnn::BackendId> & defaultBackends)168 void InstanceNormalizationNchwEndToEndTest1(const std::vector<armnn::BackendId>& defaultBackends)
169 {
170 using namespace armnn;
171
172 const float eps = 0.0001f;
173 const float beta = 0.0f;
174 const float gamma = 1.0f;
175
176 TensorShape inputShape{2, 2, 2, 2};
177 TensorInfo inputTensorInfo(inputShape, DataType::Float32, 0.0f, 0, true);
178
179 TensorShape outputShape{2, 2, 2, 2};
180 TensorInfo outputTensorInfo(outputShape, DataType::Float32);
181
182 std::vector<float> inputData = std::vector<float>(
183 {
184 // Batch 0, Height 0, Width 0 x Channel (2)
185 0.f, 1.f,
186 // Batch 0, Height 0, Width 1 x Channel (2)
187 0.f, 2.f,
188
189 // Batch 0, Height 1, Width 0 x Channel (2)
190 0.f, 2.f,
191 // Batch 0, Height 1, Width 1 x Channel (2)
192 0.f, 4.f,
193
194 // Batch 1, Height 0, Width 0 x Channel (2)
195 1.f, -1.f,
196 // Batch 1, Height 0, Width 1 x Channel (2)
197 -1.f, 2.f,
198
199 // Batch 1, Height 1, Width 0 x Channel (2)
200 -1.f, -2.f,
201 // Batch 1, Height 1, Width 1 x Channel (2)
202 1.f, 4.f
203 });
204
205 std::vector<float> expectedOutputData = std::vector<float>(
206 {
207 // Batch 0, Height 0, Width 0 x Channel (2)
208 0.f, -1.1470304f,
209 // Batch 0, Height 0, Width 1 x Channel (2)
210 0.f, -0.22940612f,
211 // Batch 0, Height 1, Width 0 x Channel (2)
212 0.f, -0.22940612f,
213 // Batch 0, Height 1, Width 1 x Channel (2)
214 0.f, 1.6058424f,
215
216 // Batch 1, Height 0, Width 0 x Channel (2)
217 0.99995005f, -0.7337929f,
218 // Batch 1, Height 0, Width 1 x Channel (2)
219 -0.99995005f, 0.52413774f,
220
221 // Batch 1, Height 1, Width 0 x Channel (2)
222 -0.99995005f, -1.1531031f,
223 // Batch 1, Height 1, Width 1 x Channel (2)
224 0.99995005f, 1.3627582f
225 });
226
227
228 InstanceNormalizationEndToEnd(defaultBackends,
229 DataLayout::NCHW,
230 inputTensorInfo,
231 outputTensorInfo,
232 inputData,
233 expectedOutputData,
234 gamma,
235 beta,
236 eps);
237 }
238
InstanceNormalizationNhwcEndToEndTest2(const std::vector<armnn::BackendId> & defaultBackends)239 void InstanceNormalizationNhwcEndToEndTest2(const std::vector<armnn::BackendId>& defaultBackends)
240 {
241 using namespace armnn;
242
243 const float eps = 0.0001f;
244 const float beta = 10.0f;
245 const float gamma = 2.0f;
246
247 TensorShape inputShape{2, 2, 2, 2};
248 TensorShape outputShape{2, 2, 2, 2};
249
250 TensorInfo outputTensorInfo(outputShape, DataType::Float32);
251 TensorInfo inputTensorInfo(inputShape, DataType::Float32, 0.0f, 0, true);
252
253 std::vector<float> inputData = std::vector<float>(
254 {
255 // Batch 0, Height 0, Width 0 x Channel (2)
256 0.f, 1.f,
257 // Batch 0, Height 0, Width 1 x Channel (2)
258 0.f, 2.f,
259
260 // Batch 0, Height 1, Width 0 x Channel (2)
261 0.f, 2.f,
262 // Batch 0, Height 1, Width 1 x Channel (2)
263 0.f, 4.f,
264
265 // Batch 1, Height 0, Width 0 x Channel (2)
266 1.f, -1.f,
267 // Batch 1, Height 0, Width 1 x Channel (2)
268 -1.f, 2.f,
269
270 // Batch 1, Height 1, Width 0 x Channel (2)
271 -1.f, -2.f,
272 // Batch 1, Height 1, Width 1 x Channel (2)
273 1.f, 4.f
274 });
275
276 std::vector<float> expectedOutputData = std::vector<float>(
277 {
278 // Batch 0, Height 0, Width 0 x Channel (2)
279 10.f, 7.7059393f,
280 // Batch 0, Height 0, Width 1 x Channel (2)
281 10.f, 9.541187f,
282
283 // Batch 0, Height 1, Width 0 x Channel (2)
284 10.f, 9.541187f,
285 // Batch 0, Height 1, Width 1 x Channel (2)
286 10.f, 13.211685f,
287
288 // Batch 1, Height 0, Width 0 x Channel (2)
289 11.9999f, 8.532414f,
290 // Batch 1, Height 0, Width 1 x Channel (2)
291 8.0001f, 11.048275f,
292
293 // Batch 1, Height 1, Width 0 x Channel (2)
294 8.0001f, 7.693794f,
295 // Batch 1, Height 1, Width 1 x Channel (2)
296 11.9999f, 12.725516f
297 });
298
299 InstanceNormalizationEndToEnd(defaultBackends,
300 DataLayout::NHWC,
301 inputTensorInfo,
302 outputTensorInfo,
303 inputData,
304 expectedOutputData,
305 gamma,
306 beta,
307 eps);
308 }
309
InstanceNormalizationNchwEndToEndTest2(const std::vector<armnn::BackendId> & defaultBackends)310 void InstanceNormalizationNchwEndToEndTest2(const std::vector<armnn::BackendId>& defaultBackends)
311 {
312 using namespace armnn;
313
314 const float eps = 0.0001f;
315 const float beta = 10.0f;
316 const float gamma = 2.0f;
317
318 TensorShape inputShape{2, 2, 2, 2};
319 TensorShape outputShape{2, 2, 2, 2};
320
321 TensorInfo outputTensorInfo(outputShape, DataType::Float32);
322 TensorInfo inputTensorInfo(inputShape, DataType::Float32, 0.0f, 0, true);
323
324 std::vector<float> inputData = std::vector<float>(
325 {
326 // Batch 0, Height 0, Width 0 x Channel (2)
327 0.f, 1.f,
328 // Batch 0, Height 0, Width 1 x Channel (2)
329 0.f, 2.f,
330
331 // Batch 0, Height 1, Width 0 x Channel (2)
332 0.f, 2.f,
333 // Batch 0, Height 1, Width 1 x Channel (2)
334 0.f, 4.f,
335
336 // Batch 1, Height 0, Width 0 x Channel (2)
337 1.f, -1.f,
338 // Batch 1, Height 0, Width 1 x Channel (2)
339 -1.f, 2.f,
340
341 // Batch 1, Height 1, Width 0 x Channel (2)
342 -1.f, -2.f,
343 // Batch 1, Height 1, Width 1 x Channel (2)
344 1.f, 4.f
345 });
346
347 std::vector<float> expectedOutputData = std::vector<float>(
348 {
349 // Batch 0, Height 0, Width 0 x Channel (2)
350 10.f, 7.7059393f,
351 // Batch 0, Height 0, Width 1 x Channel (2)
352 10.f, 9.541187f,
353
354 // Batch 0, Height 1, Width 0 x Channel (2)
355 10.f, 9.541187f,
356 // Batch 0, Height 1, Width 1 x Channel (2)
357 10.f, 13.211685f,
358
359 // Batch 1, Height 0, Width 0 x Channel (2)
360 11.9999f, 8.532414f,
361 // Batch 1, Height 0, Width 1 x Channel (2)
362 8.0001f, 11.048275f,
363
364 // Batch 1, Height 1, Width 0 x Channel (2)
365 8.0001f, 7.693794f,
366 // Batch 1, Height 1, Width 1 x Channel (2)
367 11.9999f, 12.725516f
368 });
369
370 InstanceNormalizationEndToEnd(defaultBackends,
371 DataLayout::NCHW,
372 inputTensorInfo,
373 outputTensorInfo,
374 inputData,
375 expectedOutputData,
376 gamma,
377 beta,
378 eps);
379 }
380