ef9ace903a730cbc2182f9dc7839a7f5ee172646
[platform/core/ml/nnfw.git] / compiler / luci-interpreter / src / kernels / Conv2D.test.cpp
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *    http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "kernels/Conv2D.h"
18 #include "kernels/TestUtils.h"
19
20 namespace luci_interpreter
21 {
22 namespace kernels
23 {
24 namespace
25 {
26
27 using namespace testing;
28
29 TEST(Conv2DTest, Float)
30 {
31   Shape input_shape{1, 4, 3, 2};
32   Shape filter_shape{2, 2, 2, 2};
33   Shape bias_shape{2};
34   std::vector<float> input_data{
35       1,  2,  3,  4,  5,  6,  // row = 0
36       7,  8,  9,  10, 11, 12, // row = 1
37       13, 14, 15, 16, 17, 18, // row = 2
38       19, 20, 21, 22, 23, 24, // row = 3
39   };
40   std::vector<float> filter_data{
41       1,  2,  -3, -4, // out = 0, row = 0
42       -5, 6,  -7, 8,  // out = 1, row = 0
43       4,  -2, 3,  -1, // out = 0, row = 1
44       -8, -6, 7,  5,  // out = 1, row = 1
45   };
46   std::vector<float> bias_data{1, 2};
47   Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
48   Tensor filter_tensor = makeInputTensor<DataType::FLOAT32>(filter_shape, filter_data);
49   Tensor bias_tensor = makeInputTensor<DataType::FLOAT32>(bias_shape, bias_data);
50   Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
51
52   Conv2DParams params{};
53   params.padding = Padding::VALID;
54   params.stride_height = 2;
55   params.stride_width = 1;
56   params.dilation_height_factor = 1;
57   params.dilation_width_factor = 1;
58   params.activation = Activation::RELU;
59
60   Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, params);
61   kernel.configure();
62   kernel.execute();
63
64   std::vector<float> ref_output_data{
65       11, 16, 7, 20, // row = 0
66       0,  40, 0, 44, // row = 1
67   };
68   std::vector<int32_t> ref_output_shape{1, 2, 2, 2};
69   EXPECT_THAT(extractTensorData<float>(output_tensor),
70               ElementsAreArray(ArrayFloatNear(ref_output_data)));
71   EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
72 }
73
74 TEST(Conv2DTest, FloatCheck)
75 {
76   Shape input_shape{2, 2, 4, 1};
77   Shape filter_shape{3, 2, 2, 1};
78   Shape bias_shape{3};
79   std::vector<float> input_data{
80       // First batch
81       1, 1, 1, 1, // row = 1
82       2, 2, 2, 2, // row = 2
83       // Second batch
84       1, 2, 3, 4, // row = 1
85       1, 2, 3, 4, // row = 2
86   };
87   std::vector<float> filter_data{
88       1,  2,  3,  4, // first 2x2 filter
89       -1, 1,  -1, 1, // second 2x2 filter
90       -1, -1, 1,  1, // third 2x2 filter
91   };
92   std::vector<float> bias_data{1, 2, 3};
93   Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
94   Tensor filter_tensor = makeInputTensor<DataType::FLOAT32>(filter_shape, filter_data);
95   Tensor bias_tensor = makeInputTensor<DataType::FLOAT32>(bias_shape, bias_data);
96   Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
97
98   Conv2DParams params{};
99   params.padding = Padding::VALID;
100   params.stride_height = 2;
101   params.stride_width = 2;
102   params.dilation_height_factor = 1;
103   params.dilation_width_factor = 1;
104   params.activation = Activation::NONE;
105
106   Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, params);
107   kernel.configure();
108   kernel.execute();
109
110   std::vector<float> ref_output_data{
111       18, 2, 5, // first batch, left
112       18, 2, 5, // first batch, right
113       17, 4, 3, // second batch, left
114       37, 4, 3, // second batch, right
115   };
116   std::vector<int32_t> ref_output_shape{2, 1, 2, 3};
117   EXPECT_THAT(extractTensorData<float>(output_tensor),
118               ElementsAreArray(ArrayFloatNear(ref_output_data)));
119   EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
120 }
121
122 TEST(Conv2DTest, Uint8)
123 {
124   std::pair<float, int32_t> input_quant_param = quantizationParams<uint8_t>(-63.5, 64);
125   std::pair<float, int32_t> output_quant_param = quantizationParams<uint8_t>(-127, 128);
126   Shape bias_shape = {3};
127   Tensor input_tensor{
128       DataType::U8, {2, 2, 4, 1}, {{input_quant_param.first}, {input_quant_param.second}}, ""};
129   Tensor filter_tensor{
130       DataType::U8, {3, 2, 2, 1}, {{input_quant_param.first}, {input_quant_param.second}}, ""};
131   Tensor bias_tensor{
132       DataType::S32, bias_shape, {{input_quant_param.first * input_quant_param.first}, {0}}, ""};
133   Tensor output_tensor =
134       makeOutputTensor(DataType::U8, output_quant_param.first, output_quant_param.second);
135   std::vector<uint8_t> quantized_input = quantize<uint8_t>(
136       {
137           // First batch
138           1, 1, 1, 1, // row = 1
139           2, 2, 2, 2, // row = 2
140           // Second batch
141           1, 2, 3, 4, // row = 1
142           1, 2, 3, 4, // row = 2
143       },
144       input_quant_param.first, input_quant_param.second);
145   std::vector<uint8_t> quantized_filter = quantize<uint8_t>(
146       {
147           1, 2, 3, 4,   // first 2x2 filter
148           -1, 1, -1, 1, // second 2x2 filter
149           -1, -1, 1, 1, // third 2x2 filter
150       },
151       input_quant_param.first, input_quant_param.second);
152   std::vector<int32_t> bias_data =
153       quantize<int32_t>({1, 2, 3}, input_quant_param.first * input_quant_param.first, 0);
154   input_tensor.writeData(quantized_input.data(), quantized_input.size() * sizeof(uint8_t));
155   filter_tensor.writeData(quantized_filter.data(), quantized_filter.size() * sizeof(uint8_t));
156   bias_tensor.writeData(bias_data.data(), bias_data.size() * sizeof(int32_t));
157
158   Conv2DParams params{};
159   params.padding = Padding::VALID;
160   params.stride_height = 2;
161   params.stride_width = 2;
162   params.dilation_height_factor = 1;
163   params.dilation_width_factor = 1;
164   params.activation = Activation::NONE;
165
166   Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, params);
167   kernel.configure();
168   kernel.execute();
169
170   std::vector<float> ref_output_data{
171       18, 2, 5, // first batch, left
172       18, 2, 5, // first batch, right
173       17, 4, 3, // second batch, left
174       37, 4, 3, // second batch, right
175   };
176   std::vector<int32_t> ref_output_shape{2, 1, 2, 3};
177   EXPECT_THAT(dequantize<uint8_t>(extractTensorData<uint8_t>(output_tensor),
178                                   output_quant_param.first, output_quant_param.second),
179               ElementsAreArray(ArrayFloatNear(ref_output_data)));
180   EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
181 }
182
183 } // namespace
184 } // namespace kernels
185 } // namespace luci_interpreter