1 /* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
2
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15
16 #include "tensorflow/lite/c/builtin_op_data.h"
17 #include "tensorflow/lite/c/common.h"
18 #include "tensorflow/lite/micro/all_ops_resolver.h"
19 #include "tensorflow/lite/micro/kernels/kernel_runner.h"
20 #include "tensorflow/lite/micro/test_helpers.h"
21 #include "tensorflow/lite/micro/testing/micro_test.h"
22
23 namespace tflite {
24 namespace testing {
25 namespace {
26
27 // used to set the quantization parameters for the int8_t and uint8_t tests
28 constexpr float kInputMin = -2.0;
29 constexpr float kInputMax = 2.0;
30 constexpr float kOutputMin = -1.0;
31 constexpr float kOutputMax = 127.0 / 128.0;
32
CreateL2NormTensor(const float * data,TfLiteIntArray * dims,bool is_input)33 TfLiteTensor CreateL2NormTensor(const float* data, TfLiteIntArray* dims,
34 bool is_input) {
35 return CreateTensor(data, dims);
36 }
37
38 template <typename T>
CreateL2NormTensor(const T * data,TfLiteIntArray * dims,bool is_input)39 TfLiteTensor CreateL2NormTensor(const T* data, TfLiteIntArray* dims,
40 bool is_input) {
41 float kInputScale = ScaleFromMinMax<T>(kInputMin, kInputMax);
42 int kInputZeroPoint = ZeroPointFromMinMax<T>(kInputMin, kInputMax);
43 float kOutputScale = ScaleFromMinMax<T>(kOutputMin, kOutputMax);
44 int kOutputZeroPoint = ZeroPointFromMinMax<T>(kOutputMin, kOutputMax);
45 TfLiteTensor tensor;
46 if (is_input) {
47 tensor = CreateQuantizedTensor(data, dims, kInputScale, kInputZeroPoint);
48 } else {
49 tensor = CreateQuantizedTensor(data, dims, kOutputScale, kOutputZeroPoint);
50 }
51
52 tensor.quantization.type = kTfLiteAffineQuantization;
53 return tensor;
54 }
55
56 template <typename T>
TestL2Normalization(const int * input_dims_data,const T * input_data,const T * expected_output_data,T * output_data)57 void TestL2Normalization(const int* input_dims_data, const T* input_data,
58 const T* expected_output_data, T* output_data) {
59 TfLiteIntArray* dims = IntArrayFromInts(input_dims_data);
60
61 const int output_dims_count = ElementCount(*dims);
62
63 constexpr int tensors_size = 2;
64 TfLiteTensor tensors[tensors_size] = {
65 CreateL2NormTensor(input_data, dims, true),
66 CreateL2NormTensor(output_data, dims, false),
67 };
68
69 int inputs_array_data[] = {1, 0};
70 TfLiteIntArray* inputs_array = IntArrayFromInts(inputs_array_data);
71 int outputs_array_data[] = {1, 1};
72 TfLiteIntArray* outputs_array = IntArrayFromInts(outputs_array_data);
73
74 TfLiteL2NormParams builtin_data = {
75 .activation = kTfLiteActNone,
76 };
77
78 const TfLiteRegistration registration =
79 ops::micro::Register_L2_NORMALIZATION();
80 micro::KernelRunner runner(registration, tensors, tensors_size, inputs_array,
81 outputs_array,
82 reinterpret_cast<void*>(&builtin_data));
83
84 TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.InitAndPrepare());
85 TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.Invoke());
86
87 for (int i = 0; i < output_dims_count; ++i) {
88 TF_LITE_MICRO_EXPECT_EQ(expected_output_data[i], output_data[i]);
89 }
90 }
91
92 } // namespace
93 } // namespace testing
94 } // namespace tflite
95
96 TF_LITE_MICRO_TESTS_BEGIN
97
TF_LITE_MICRO_TEST(SimpleFloatTest)98 TF_LITE_MICRO_TEST(SimpleFloatTest) {
99 const int input_dims[] = {4, 1, 1, 1, 6};
100 constexpr int data_length = 6;
101 const float input_data[data_length] = {-1.1, 0.6, 0.7, 1.2, -0.7, 0.1};
102 const float expected_output_data[data_length] = {-0.55, 0.3, 0.35,
103 0.6, -0.35, 0.05};
104 float output_data[data_length];
105
106 tflite::testing::TestL2Normalization<float>(
107 input_dims, input_data, expected_output_data, output_data);
108 }
109
TF_LITE_MICRO_TEST(ZerosVectorFloatTest)110 TF_LITE_MICRO_TEST(ZerosVectorFloatTest) {
111 const int input_dims[] = {4, 1, 1, 1, 6};
112 constexpr int data_length = 6;
113 const float input_data[data_length] = {0, 0, 0, 0, 0, 0};
114 const float expected_output_data[data_length] = {0, 0, 0, 0, 0, 0};
115 float output_data[data_length];
116
117 tflite::testing::TestL2Normalization<float>(
118 input_dims, input_data, expected_output_data, output_data);
119 }
120
TF_LITE_MICRO_TEST(SimpleFloatWithRankLessThanFourTest)121 TF_LITE_MICRO_TEST(SimpleFloatWithRankLessThanFourTest) {
122 const int input_dims[] = {4, 1, 1, 1, 6};
123 constexpr int data_length = 6;
124 const float input_data[data_length] = {-1.1, 0.6, 0.7, 1.2, -0.7, 0.1};
125 const float expected_output_data[data_length] = {-0.55, 0.3, 0.35,
126 0.6, -0.35, 0.05};
127 float output_data[data_length];
128
129 tflite::testing::TestL2Normalization<float>(
130 input_dims, input_data, expected_output_data, output_data);
131 }
132
TF_LITE_MICRO_TEST(MultipleBatchFloatTest)133 TF_LITE_MICRO_TEST(MultipleBatchFloatTest) {
134 const int input_dims[] = {4, 3, 1, 1, 6};
135 constexpr int data_length = 18;
136 const float input_data[data_length] = {
137 -1.1, 0.6, 0.7, 1.2, -0.7, 0.1, // batch 1
138 -1.1, 0.6, 0.7, 1.2, -0.7, 0.1, // batch 2
139 -1.1, 0.6, 0.7, 1.2, -0.7, 0.1, // batch 3
140 };
141 const float expected_output_data[data_length] = {
142 -0.55, 0.3, 0.35, 0.6, -0.35, 0.05, // batch 1
143 -0.55, 0.3, 0.35, 0.6, -0.35, 0.05, // batch 2
144 -0.55, 0.3, 0.35, 0.6, -0.35, 0.05, // batch 3
145 };
146 float output_data[data_length];
147
148 tflite::testing::TestL2Normalization<float>(
149 input_dims, input_data, expected_output_data, output_data);
150 }
151
TF_LITE_MICRO_TEST(ZerosVectorUint8Test)152 TF_LITE_MICRO_TEST(ZerosVectorUint8Test) {
153 const int input_dims[] = {4, 1, 1, 1, 6};
154 constexpr int data_length = 6;
155 const uint8_t input_data[data_length] = {127, 127, 127, 127, 127, 127};
156 const uint8_t expected_output[data_length] = {128, 128, 128, 128, 128, 128};
157 uint8_t output_data[data_length];
158
159 tflite::testing::TestL2Normalization<uint8_t>(input_dims, input_data,
160 expected_output, output_data);
161 }
162
TF_LITE_MICRO_TEST(SimpleUint8Test)163 TF_LITE_MICRO_TEST(SimpleUint8Test) {
164 const int input_dims[] = {4, 1, 1, 1, 6};
165 constexpr int data_length = 6;
166 const uint8_t input_data[data_length] = {57, 165, 172, 204, 82, 133};
167 const uint8_t expected_output[data_length] = {
168 58, 166, 173, 205, 83, 134,
169 };
170 uint8_t output_data[data_length];
171
172 tflite::testing::TestL2Normalization<uint8_t>(input_dims, input_data,
173 expected_output, output_data);
174 }
175
TF_LITE_MICRO_TEST(SimpleInt8Test)176 TF_LITE_MICRO_TEST(SimpleInt8Test) {
177 const int input_dims[] = {4, 1, 1, 1, 6};
178 constexpr int data_length = 6;
179 const int8_t input_data[data_length] = {-71, 37, 44, 76, -46, 5};
180 const int8_t expected_output[data_length] = {-70, 38, 45, 77, -45, 6};
181 int8_t output_data[data_length];
182
183 tflite::testing::TestL2Normalization<int8_t>(input_dims, input_data,
184 expected_output, output_data);
185 }
186
TF_LITE_MICRO_TEST(ZerosVectorInt8Test)187 TF_LITE_MICRO_TEST(ZerosVectorInt8Test) {
188 const int input_dims[] = {4, 1, 1, 1, 6};
189 constexpr int data_length = 6;
190 const int8_t input_data[data_length] = {-1, -1, -1, -1, -1, -1};
191 const int8_t expected_output[data_length] = {0, 0, 0, 0, 0, 0};
192 int8_t output_data[data_length];
193
194 tflite::testing::TestL2Normalization<int8_t>(input_dims, input_data,
195 expected_output, output_data);
196 }
197
TF_LITE_MICRO_TEST(MultipleBatchUint8Test)198 TF_LITE_MICRO_TEST(MultipleBatchUint8Test) {
199 const int input_dims[] = {2, 3, 6};
200 constexpr int data_length = 18;
201 const uint8_t input_data[data_length] = {
202 57, 165, 172, 204, 82, 133, // batch 1
203 57, 165, 172, 204, 82, 133, // batch 2
204 57, 165, 172, 204, 82, 133, // batch 3
205 };
206 const uint8_t expected_output[data_length] = {
207 58, 166, 173, 205, 83, 134, // batch 1
208 58, 166, 173, 205, 83, 134, // batch 2
209 58, 166, 173, 205, 83, 134, // batch 3
210 };
211 uint8_t output_data[data_length];
212
213 tflite::testing::TestL2Normalization<uint8_t>(input_dims, input_data,
214 expected_output, output_data);
215 }
216
TF_LITE_MICRO_TEST(MultipleBatchInt8Test)217 TF_LITE_MICRO_TEST(MultipleBatchInt8Test) {
218 const int input_dims[] = {2, 3, 6};
219 constexpr int data_length = 18;
220 const int8_t input_data[data_length] = {
221 -71, 37, 44, 76, -46, 5, // batch 1
222 -71, 37, 44, 76, -46, 5, // batch 2
223 -71, 37, 44, 76, -46, 5, // batch 3
224 };
225 const int8_t expected_output[data_length] = {
226 -70, 38, 45, 77, -45, 6, // batch 1
227 -70, 38, 45, 77, -45, 6, // batch 2
228 -70, 38, 45, 77, -45, 6, // batch 3
229 };
230 int8_t output_data[data_length];
231
232 tflite::testing::TestL2Normalization<int8_t>(input_dims, input_data,
233 expected_output, output_data);
234 }
235
236 TF_LITE_MICRO_TESTS_END
237