blob: 1306fd199a5d6d73deebafdf0b8396f0afe0261b [file] [log] [blame]
Sadik Armagan4b227bb2021-01-22 10:53:38 +00001//
Colm Donelan7bcae3c2024-01-22 10:07:14 +00002// Copyright © 2021, 2023-2024 Arm Ltd and Contributors. All rights reserved.
Sadik Armagan4b227bb2021-01-22 10:53:38 +00003// SPDX-License-Identifier: MIT
4//
5
6#pragma once
7
8#include "TestUtils.hpp"
9
10#include <armnn_delegate.hpp>
Matthew Sloyanebe392d2023-03-30 10:12:08 +010011#include <DelegateTestInterpreter.hpp>
Sadik Armagan4b227bb2021-01-22 10:53:38 +000012
Sadik Armagan4b227bb2021-01-22 10:53:38 +000013#include <tensorflow/lite/version.h>
14
Sadik Armagan4b227bb2021-01-22 10:53:38 +000015namespace
16{
17
18std::vector<char> CreateNormalizationTfLiteModel(tflite::BuiltinOperator normalizationOperatorCode,
19 tflite::TensorType tensorType,
20 const std::vector<int32_t>& inputTensorShape,
21 const std::vector<int32_t>& outputTensorShape,
22 int32_t radius,
23 float bias,
24 float alpha,
25 float beta,
26 float quantScale = 1.0f,
27 int quantOffset = 0)
28{
29 using namespace tflite;
30 flatbuffers::FlatBufferBuilder flatBufferBuilder;
31
32 auto quantizationParameters =
33 CreateQuantizationParameters(flatBufferBuilder,
34 0,
35 0,
36 flatBufferBuilder.CreateVector<float>({ quantScale }),
37 flatBufferBuilder.CreateVector<int64_t>({ quantOffset }));
38
39 auto inputTensor = CreateTensor(flatBufferBuilder,
40 flatBufferBuilder.CreateVector<int32_t>(inputTensorShape.data(),
41 inputTensorShape.size()),
42 tensorType,
Ryan OShea238ecd92023-03-07 11:44:23 +000043 1,
Sadik Armagan4b227bb2021-01-22 10:53:38 +000044 flatBufferBuilder.CreateString("input"),
45 quantizationParameters);
46
47 auto outputTensor = CreateTensor(flatBufferBuilder,
48 flatBufferBuilder.CreateVector<int32_t>(outputTensorShape.data(),
49 outputTensorShape.size()),
50 tensorType,
Ryan OShea238ecd92023-03-07 11:44:23 +000051 2,
Sadik Armagan4b227bb2021-01-22 10:53:38 +000052 flatBufferBuilder.CreateString("output"),
53 quantizationParameters);
54
55 std::vector<flatbuffers::Offset<Tensor>> tensors = { inputTensor, outputTensor };
56
57 std::vector<flatbuffers::Offset<tflite::Buffer>> buffers;
Ryan OShea238ecd92023-03-07 11:44:23 +000058 buffers.push_back(CreateBuffer(flatBufferBuilder));
59 buffers.push_back(CreateBuffer(flatBufferBuilder));
60 buffers.push_back(CreateBuffer(flatBufferBuilder));
Sadik Armagan4b227bb2021-01-22 10:53:38 +000061
Keith Davis244b5bf2021-01-31 18:36:58 +000062 std::vector<int32_t> operatorInputs = { 0 };
63 std::vector<int> subgraphInputs = { 0 };
Sadik Armagan4b227bb2021-01-22 10:53:38 +000064
65 tflite::BuiltinOptions operatorBuiltinOptionsType = BuiltinOptions_L2NormOptions;
66 flatbuffers::Offset<void> operatorBuiltinOptions = CreateL2NormOptions(flatBufferBuilder,
67 tflite::ActivationFunctionType_NONE).Union();
68
69 if (normalizationOperatorCode == tflite::BuiltinOperator_LOCAL_RESPONSE_NORMALIZATION)
70 {
71 operatorBuiltinOptionsType = BuiltinOptions_LocalResponseNormalizationOptions;
72 operatorBuiltinOptions =
73 CreateLocalResponseNormalizationOptions(flatBufferBuilder, radius, bias, alpha, beta).Union();
74 }
75
76 // create operator
Keith Davis244b5bf2021-01-31 18:36:58 +000077 const std::vector<int32_t> operatorOutputs{ 1 };
Sadik Armagan4b227bb2021-01-22 10:53:38 +000078 flatbuffers::Offset <Operator> normalizationOperator =
79 CreateOperator(flatBufferBuilder,
80 0,
81 flatBufferBuilder.CreateVector<int32_t>(operatorInputs.data(), operatorInputs.size()),
82 flatBufferBuilder.CreateVector<int32_t>(operatorOutputs.data(), operatorOutputs.size()),
83 operatorBuiltinOptionsType,
84 operatorBuiltinOptions);
85
Keith Davis244b5bf2021-01-31 18:36:58 +000086 const std::vector<int> subgraphOutputs{ 1 };
Sadik Armagan4b227bb2021-01-22 10:53:38 +000087 flatbuffers::Offset <SubGraph> subgraph =
88 CreateSubGraph(flatBufferBuilder,
89 flatBufferBuilder.CreateVector(tensors.data(), tensors.size()),
90 flatBufferBuilder.CreateVector<int32_t>(subgraphInputs.data(), subgraphInputs.size()),
91 flatBufferBuilder.CreateVector<int32_t>(subgraphOutputs.data(), subgraphOutputs.size()),
92 flatBufferBuilder.CreateVector(&normalizationOperator, 1));
93
94 flatbuffers::Offset <flatbuffers::String> modelDescription =
95 flatBufferBuilder.CreateString("ArmnnDelegate: Normalization Operator Model");
96 flatbuffers::Offset <OperatorCode> operatorCode = CreateOperatorCode(flatBufferBuilder,
97 normalizationOperatorCode);
98
99 flatbuffers::Offset <Model> flatbufferModel =
100 CreateModel(flatBufferBuilder,
101 TFLITE_SCHEMA_VERSION,
102 flatBufferBuilder.CreateVector(&operatorCode, 1),
103 flatBufferBuilder.CreateVector(&subgraph, 1),
104 modelDescription,
105 flatBufferBuilder.CreateVector(buffers.data(), buffers.size()));
106
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100107 flatBufferBuilder.Finish(flatbufferModel, armnnDelegate::FILE_IDENTIFIER);
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000108
109 return std::vector<char>(flatBufferBuilder.GetBufferPointer(),
110 flatBufferBuilder.GetBufferPointer() + flatBufferBuilder.GetSize());
111}
112
113template <typename T>
114void NormalizationTest(tflite::BuiltinOperator normalizationOperatorCode,
115 tflite::TensorType tensorType,
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000116 const std::vector<int32_t>& inputShape,
117 std::vector<int32_t>& outputShape,
118 std::vector<T>& inputValues,
119 std::vector<T>& expectedOutputValues,
Colm Donelan7bcae3c2024-01-22 10:07:14 +0000120 const std::vector<armnn::BackendId>& backends = {},
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000121 int32_t radius = 0,
122 float bias = 0.f,
123 float alpha = 0.f,
124 float beta = 0.f,
125 float quantScale = 1.0f,
126 int quantOffset = 0)
127{
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100128 using namespace delegateTestInterpreter;
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000129 std::vector<char> modelBuffer = CreateNormalizationTfLiteModel(normalizationOperatorCode,
130 tensorType,
131 inputShape,
132 outputShape,
133 radius,
134 bias,
135 alpha,
136 beta,
137 quantScale,
138 quantOffset);
139
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100140 // Setup interpreter with just TFLite Runtime.
141 auto tfLiteInterpreter = DelegateTestInterpreter(modelBuffer);
142 CHECK(tfLiteInterpreter.AllocateTensors() == kTfLiteOk);
143 CHECK(tfLiteInterpreter.FillInputTensor<T>(inputValues, 0) == kTfLiteOk);
144 CHECK(tfLiteInterpreter.Invoke() == kTfLiteOk);
145 std::vector<T> tfLiteOutputValues = tfLiteInterpreter.GetOutputResult<T>(0);
146 std::vector<int32_t> tfLiteOutputShape = tfLiteInterpreter.GetOutputShape(0);
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000147
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100148 // Setup interpreter with Arm NN Delegate applied.
Colm Donelan7bcae3c2024-01-22 10:07:14 +0000149 auto armnnInterpreter = DelegateTestInterpreter(modelBuffer, CaptureAvailableBackends(backends));
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100150 CHECK(armnnInterpreter.AllocateTensors() == kTfLiteOk);
151 CHECK(armnnInterpreter.FillInputTensor<T>(inputValues, 0) == kTfLiteOk);
152 CHECK(armnnInterpreter.Invoke() == kTfLiteOk);
153 std::vector<T> armnnOutputValues = armnnInterpreter.GetOutputResult<T>(0);
154 std::vector<int32_t> armnnOutputShape = armnnInterpreter.GetOutputShape(0);
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000155
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100156 armnnDelegate::CompareOutputData<T>(tfLiteOutputValues, armnnOutputValues, expectedOutputValues);
157 armnnDelegate::CompareOutputShape(tfLiteOutputShape, armnnOutputShape, outputShape);
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000158
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100159 tfLiteInterpreter.Cleanup();
160 armnnInterpreter.Cleanup();
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000161}
162
Colm Donelan7bcae3c2024-01-22 10:07:14 +0000163void L2NormalizationTest(const std::vector<armnn::BackendId>& backends = {})
Keith Davis7c67fab2021-04-08 11:47:23 +0100164{
165 // Set input data
166 std::vector<int32_t> inputShape { 1, 1, 1, 10 };
167 std::vector<int32_t> outputShape { 1, 1, 1, 10 };
168
169 std::vector<float> inputValues
170 {
171 1.0f,
172 2.0f,
173 3.0f,
174 4.0f,
175 5.0f,
176 6.0f,
177 7.0f,
178 8.0f,
179 9.0f,
180 10.0f
181 };
182
183 const float approxInvL2Norm = 0.050964719f;
184 std::vector<float> expectedOutputValues
185 {
186 1.0f * approxInvL2Norm,
187 2.0f * approxInvL2Norm,
188 3.0f * approxInvL2Norm,
189 4.0f * approxInvL2Norm,
190 5.0f * approxInvL2Norm,
191 6.0f * approxInvL2Norm,
192 7.0f * approxInvL2Norm,
193 8.0f * approxInvL2Norm,
194 9.0f * approxInvL2Norm,
195 10.0f * approxInvL2Norm
196 };
197
198 NormalizationTest<float>(tflite::BuiltinOperator_L2_NORMALIZATION,
199 ::tflite::TensorType_FLOAT32,
Keith Davis7c67fab2021-04-08 11:47:23 +0100200 inputShape,
201 outputShape,
202 inputValues,
Colm Donelan7bcae3c2024-01-22 10:07:14 +0000203 expectedOutputValues,
204 backends);
Keith Davis7c67fab2021-04-08 11:47:23 +0100205}
206
Colm Donelan7bcae3c2024-01-22 10:07:14 +0000207void LocalResponseNormalizationTest(int32_t radius,
Keith Davis7c67fab2021-04-08 11:47:23 +0100208 float bias,
209 float alpha,
Colm Donelan7bcae3c2024-01-22 10:07:14 +0000210 float beta,
211 const std::vector<armnn::BackendId>& backends = {})
Keith Davis7c67fab2021-04-08 11:47:23 +0100212{
213 // Set input data
214 std::vector<int32_t> inputShape { 2, 2, 2, 1 };
215 std::vector<int32_t> outputShape { 2, 2, 2, 1 };
216
217 std::vector<float> inputValues
218 {
219 1.0f, 2.0f,
220 3.0f, 4.0f,
221 5.0f, 6.0f,
222 7.0f, 8.0f
223 };
224
225 std::vector<float> expectedOutputValues
226 {
227 0.5f, 0.400000006f, 0.300000012f, 0.235294119f,
228 0.192307696f, 0.16216217f, 0.140000001f, 0.123076923f
229 };
230
231 NormalizationTest<float>(tflite::BuiltinOperator_LOCAL_RESPONSE_NORMALIZATION,
232 ::tflite::TensorType_FLOAT32,
Keith Davis7c67fab2021-04-08 11:47:23 +0100233 inputShape,
234 outputShape,
235 inputValues,
236 expectedOutputValues,
Colm Donelan7bcae3c2024-01-22 10:07:14 +0000237 backends,
Keith Davis7c67fab2021-04-08 11:47:23 +0100238 radius,
239 bias,
240 alpha,
241 beta);
242}
243
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000244} // anonymous namespace