1 /* Copyright 2019 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/kernels/kernel_runner.h"
19 #include "tensorflow/lite/micro/test_helpers.h"
20 #include "tensorflow/lite/micro/testing/micro_test.h"
21 
22 namespace tflite {
23 namespace testing {
24 namespace {
25 
26 template <typename T>
ValidatePreluGoldens(TfLiteTensor * tensors,int tensors_size,const T * golden,const int output_length,T * output_data)27 void ValidatePreluGoldens(TfLiteTensor* tensors, int tensors_size,
28                           const T* golden, const int output_length,
29                           T* output_data) {
30   int inputs_array_data[] = {2, 0, 1};
31   TfLiteIntArray* inputs_array = IntArrayFromInts(inputs_array_data);
32   int outputs_array_data[] = {1, 2};
33   TfLiteIntArray* outputs_array = IntArrayFromInts(outputs_array_data);
34 
35   const TfLiteRegistration registration = tflite::ops::micro::Register_PRELU();
36   micro::KernelRunner runner(registration, tensors, tensors_size, inputs_array,
37                              outputs_array,
38                              /*builtin_data=*/nullptr);
39 
40   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.InitAndPrepare());
41   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.Invoke());
42 
43   for (int i = 0; i < output_length; ++i) {
44     TF_LITE_MICRO_EXPECT_NEAR(golden[i], output_data[i], 1e-5f);
45   }
46 }
47 
TestPreluFloat(int * input_dims_data,const float * input_data,int * alpha_dims_data,const float * alpha_data,const float * expected_output_data,int * output_dims_data,float * output_data)48 void TestPreluFloat(int* input_dims_data, const float* input_data,
49                     int* alpha_dims_data, const float* alpha_data,
50                     const float* expected_output_data, int* output_dims_data,
51                     float* output_data) {
52   TfLiteIntArray* input_dims = IntArrayFromInts(input_dims_data);
53   TfLiteIntArray* alpha_dims = IntArrayFromInts(alpha_dims_data);
54   TfLiteIntArray* output_dims = IntArrayFromInts(output_dims_data);
55   const int output_dims_count = ElementCount(*output_dims);
56   constexpr int inputs_size = 2;
57   constexpr int outputs_size = 1;
58   constexpr int tensors_size = inputs_size + outputs_size;
59   TfLiteTensor tensors[tensors_size] = {
60       CreateTensor(input_data, input_dims),
61       CreateTensor(alpha_data, alpha_dims),
62       CreateTensor(output_data, output_dims),
63   };
64 
65   ValidatePreluGoldens(tensors, tensors_size, expected_output_data,
66                        output_dims_count, output_data);
67 }
68 
69 // Template argument T can be either uint8_t or int8_t depending on which type
70 // of quantization required to be tested.
71 template <typename T>
TestPreluQuantized(int * input_dims_data,const float * input_data,T * input_quantized,const float input_scale,const int input_zero_point,int * alpha_dims_data,const float * alpha_data,T * alpha_quantized,const float alpha_scale,const int alpha_zero_point,const float * golden,T * golden_quantized,const float output_scale,const int output_zero_point,int * output_dims_data,T * output_data)72 void TestPreluQuantized(int* input_dims_data, const float* input_data,
73                         T* input_quantized, const float input_scale,
74                         const int input_zero_point, int* alpha_dims_data,
75                         const float* alpha_data, T* alpha_quantized,
76                         const float alpha_scale, const int alpha_zero_point,
77                         const float* golden, T* golden_quantized,
78                         const float output_scale, const int output_zero_point,
79                         int* output_dims_data, T* output_data) {
80   TfLiteIntArray* input_dims = IntArrayFromInts(input_dims_data);
81   TfLiteIntArray* alpha_dims = IntArrayFromInts(alpha_dims_data);
82   TfLiteIntArray* output_dims = IntArrayFromInts(output_dims_data);
83   const int output_dims_count = ElementCount(*output_dims);
84   constexpr int inputs_size = 2;
85   constexpr int outputs_size = 1;
86   constexpr int tensors_size = inputs_size + outputs_size;
87   TfLiteTensor tensors[tensors_size] = {
88       CreateQuantizedTensor(input_data, input_quantized, input_dims,
89                             input_scale, input_zero_point),
90       CreateQuantizedTensor(alpha_data, alpha_quantized, alpha_dims,
91                             alpha_scale, alpha_zero_point),
92       CreateQuantizedTensor(output_data, output_dims, output_scale,
93                             output_zero_point),
94   };
95 
96   Quantize(golden, golden_quantized, output_dims_count, output_scale,
97            output_zero_point);
98 
99   ValidatePreluGoldens(tensors, tensors_size, golden_quantized,
100                        output_dims_count, output_data);
101 }
102 }  // namespace
103 }  // namespace testing
104 }  // namespace tflite
105 
106 TF_LITE_MICRO_TESTS_BEGIN
107 
TF_LITE_MICRO_TEST(FloatPreluActivationsOpTest)108 TF_LITE_MICRO_TEST(FloatPreluActivationsOpTest) {
109   int input_shape[] = {3, 2, 2, 3};
110   const float input_values[] = {
111       0.0f,  0.0f,  0.0f,   // Row 1, Column 1
112       1.0f,  1.0f,  1.0f,   // Row 1, Column 2
113       -1.0f, -1.0f, -1.0f,  // Row 2, Column 1
114       -2.0f, -2.0f, -2.0f,  // Row 1, Column 2
115   };
116   int alpha_shape[] = {3, 1, 1, 3};
117   const float alpha_values[] = {0.0f, 1.0f, 2.0f};
118   int output_shape[] = {3, 2, 2, 3};
119   const float golden[] = {
120       0.0f, 0.0f,  0.0f,   // Row 1, Column 1
121       1.0f, 1.0f,  1.0f,   // Row 1, Column 2
122       0.0f, -1.0f, -2.0f,  // Row 2, Column 1
123       0.0f, -2.0f, -4.0f,  // Row 1, Column 2
124   };
125   const int output_dims_count = 12;
126   float output_data[output_dims_count];
127   tflite::testing::TestPreluFloat(input_shape, input_values, alpha_shape,
128                                   alpha_values, golden, output_shape,
129                                   output_data);
130 }
131 
TF_LITE_MICRO_TEST(QuantizedUint8PreluActivationsOpTest)132 TF_LITE_MICRO_TEST(QuantizedUint8PreluActivationsOpTest) {
133   int input_shape[] = {3, 2, 2, 3};
134   const float input_values[] = {
135       0.0f,   0.0f,   0.0f,    // Row 1, Column 1
136       0.5f,   0.5f,   0.5f,    // Row 1, Column 2
137       -1.0f,  -1.0f,  -1.0f,   // Row 2, Column 1
138       -0.25f, -0.25f, -0.25f,  // Row 1, Column 2
139   };
140   int alpha_shape[] = {3, 1, 1, 3};
141   const float alpha_values[] = {0.0f, 0.5f, -0.5f};
142   int output_shape[] = {3, 2, 2, 3};
143   const float golden[] = {
144       0.0f, 0.0f,    0.0f,    // Row 1, Column 1
145       0.5f, 0.5f,    0.5f,    // Row 1, Column 2
146       0.0f, -0.5f,   0.5f,    // Row 2, Column 1
147       0.0f, -0.125f, 0.125f,  // Row 1, Column 2
148   };
149 
150   const int dims_count = 12;
151 
152   uint8_t input_quantized[dims_count];
153   uint8_t alpha_quantized[3];
154   uint8_t golden_quantized[dims_count];
155   float scale = 0.125;
156   int zero_point = 127;
157   uint8_t output_data[dims_count];
158 
159   tflite::testing::TestPreluQuantized(
160       input_shape, input_values, input_quantized, scale, zero_point,
161       alpha_shape, alpha_values, alpha_quantized, scale, zero_point, golden,
162       golden_quantized, scale, zero_point, output_shape, output_data);
163 }
164 
TF_LITE_MICRO_TEST(QuantizedInt8PreluActivationsOpTest)165 TF_LITE_MICRO_TEST(QuantizedInt8PreluActivationsOpTest) {
166   int input_shape[] = {3, 2, 2, 3};
167   const float input_values[] = {
168       0.0f,   0.0f,   0.0f,    // Row 1, Column 1
169       0.5f,   0.5f,   0.5f,    // Row 1, Column 2
170       -1.0f,  -1.0f,  -1.0f,   // Row 2, Column 1
171       -0.25f, -0.25f, -0.25f,  // Row 1, Column 2
172   };
173   int alpha_shape[] = {3, 1, 1, 3};
174   const float alpha_values[] = {0.0f, 0.5f, -0.5f};
175   int output_shape[] = {3, 2, 2, 3};
176   const float golden[] = {
177       0.0f, 0.0f,    0.0f,    // Row 1, Column 1
178       0.5f, 0.5f,    0.5f,    // Row 1, Column 2
179       0.0f, -0.5f,   0.5f,    // Row 2, Column 1
180       0.0f, -0.125f, 0.125f,  // Row 1, Column 2
181   };
182   const int dims_count = 12;
183   int8_t input_quantized[dims_count];
184   int8_t alpha_quantized[3];
185   int8_t golden_quantized[dims_count];
186   float scale = 2.0 / 255.0;
187   int zero_point = 0;
188   int8_t output_data[dims_count];
189   tflite::testing::TestPreluQuantized(
190       input_shape, input_values, input_quantized, scale, zero_point,
191       alpha_shape, alpha_values, alpha_quantized, scale, zero_point, golden,
192       golden_quantized, scale, zero_point, output_shape, output_data);
193 }
194 TF_LITE_MICRO_TESTS_END
195