2 * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "kernels/Conv2D.h"
18 #include "kernels/TestUtils.h"
20 namespace luci_interpreter
27 using namespace testing;
29 TEST(Conv2DTest, Float)
31 Shape input_shape{1, 4, 3, 2};
32 Shape filter_shape{2, 2, 2, 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
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
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);
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;
60 Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, params);
64 std::vector<float> ref_output_data{
65 11, 16, 7, 20, // row = 0
66 0, 40, 0, 44, // row = 1
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));
74 TEST(Conv2DTest, FloatCheck)
76 Shape input_shape{2, 2, 4, 1};
77 Shape filter_shape{3, 2, 2, 1};
79 std::vector<float> input_data{
81 1, 1, 1, 1, // row = 1
82 2, 2, 2, 2, // row = 2
84 1, 2, 3, 4, // row = 1
85 1, 2, 3, 4, // row = 2
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
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);
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;
106 Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, params);
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
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));
122 TEST(Conv2DTest, Uint8)
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};
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}}, ""};
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>(
138 1, 1, 1, 1, // row = 1
139 2, 2, 2, 2, // row = 2
141 1, 2, 3, 4, // row = 1
142 1, 2, 3, 4, // row = 2
144 input_quant_param.first, input_quant_param.second);
145 std::vector<uint8_t> quantized_filter = quantize<uint8_t>(
147 1, 2, 3, 4, // first 2x2 filter
148 -1, 1, -1, 1, // second 2x2 filter
149 -1, -1, 1, 1, // third 2x2 filter
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));
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;
166 Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, params);
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
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));
183 TEST(Conv2DTest, Unsupported_Type_Configure_NEG)
185 Shape input_shape{1, 4, 3, 2};
186 Shape filter_shape{2, 2, 2, 2};
188 std::vector<int32_t> input_data{
189 1, 2, 3, 4, 5, 6, // row = 0
190 7, 8, 9, 10, 11, 12, // row = 1
191 13, 14, 15, 16, 17, 18, // row = 2
192 19, 20, 21, 22, 23, 24, // row = 3
194 std::vector<float> filter_data{
195 1, 2, -3, -4, // out = 0, row = 0
196 -5, 6, -7, 8, // out = 1, row = 0
197 4, -2, 3, -1, // out = 0, row = 1
198 -8, -6, 7, 5, // out = 1, row = 1
200 std::vector<float> bias_data{1, 2};
201 Tensor input_tensor = makeInputTensor<DataType::S32>(input_shape, input_data);
202 Tensor filter_tensor = makeInputTensor<DataType::FLOAT32>(filter_shape, filter_data);
203 Tensor bias_tensor = makeInputTensor<DataType::FLOAT32>(bias_shape, bias_data);
204 Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
206 Conv2DParams params{};
207 params.padding = Padding::VALID;
208 params.stride_height = 2;
209 params.stride_width = 1;
210 params.dilation_height_factor = 1;
211 params.dilation_width_factor = 1;
212 params.activation = Activation::RELU;
214 Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, params);
215 EXPECT_ANY_THROW(kernel.configure());
218 TEST(Conv2DTest, Invalid_Bias_Type_NEG)
220 Shape input_shape{1, 4, 3, 2};
221 Shape filter_shape{2, 2, 2, 2};
223 std::vector<float> input_data{
224 1, 2, 3, 4, 5, 6, // row = 0
225 7, 8, 9, 10, 11, 12, // row = 1
226 13, 14, 15, 16, 17, 18, // row = 2
227 19, 20, 21, 22, 23, 24, // row = 3
229 std::vector<float> filter_data{
230 1, 2, -3, -4, // out = 0, row = 0
231 -5, 6, -7, 8, // out = 1, row = 0
232 4, -2, 3, -1, // out = 0, row = 1
233 -8, -6, 7, 5, // out = 1, row = 1
235 std::vector<uint8_t> bias_data{1, 2};
236 Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
237 Tensor filter_tensor = makeInputTensor<DataType::FLOAT32>(filter_shape, filter_data);
238 Tensor bias_tensor = makeInputTensor<DataType::U8>(bias_shape, bias_data);
239 Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
241 Conv2DParams params{};
242 params.padding = Padding::VALID;
243 params.stride_height = 2;
244 params.stride_width = 1;
245 params.dilation_height_factor = 1;
246 params.dilation_width_factor = 1;
247 params.activation = Activation::RELU;
249 Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, params);
250 EXPECT_ANY_THROW(kernel.configure());
253 TEST(Conv2DTest, Invalid_Bias_Data_NEG)
255 Shape input_shape{1, 4, 3, 2};
256 Shape filter_shape{2, 2, 2, 2};
258 std::vector<float> input_data{
259 1, 2, 3, 4, 5, 6, // row = 0
260 7, 8, 9, 10, 11, 12, // row = 1
261 13, 14, 15, 16, 17, 18, // row = 2
262 19, 20, 21, 22, 23, 24, // row = 3
264 std::vector<float> filter_data{
265 1, 2, -3, -4, // out = 0, row = 0
266 -5, 6, -7, 8, // out = 1, row = 0
267 4, -2, 3, -1, // out = 0, row = 1
268 -8, -6, 7, 5, // out = 1, row = 1
270 std::vector<float> bias_data{1, 2, 3};
271 Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
272 Tensor filter_tensor = makeInputTensor<DataType::FLOAT32>(filter_shape, filter_data);
273 Tensor bias_tensor = makeInputTensor<DataType::FLOAT32>(bias_shape, bias_data);
274 Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
276 Conv2DParams params{};
277 params.padding = Padding::VALID;
278 params.stride_height = 2;
279 params.stride_width = 1;
280 params.dilation_height_factor = 1;
281 params.dilation_width_factor = 1;
282 params.activation = Activation::RELU;
284 Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, params);
285 EXPECT_ANY_THROW(kernel.configure());
288 TEST(Conv2DTest, Invalid_Input_Shape_NEG)
290 Shape input_shape{1, 4, 6, 1};
291 Shape filter_shape{2, 2, 2, 2};
293 std::vector<float> input_data{
294 1, 2, 3, 4, 5, 6, // row = 0
295 7, 8, 9, 10, 11, 12, // row = 1
296 13, 14, 15, 16, 17, 18, // row = 2
297 19, 20, 21, 22, 23, 24, // row = 3
299 std::vector<float> filter_data{
300 1, 2, -3, -4, // out = 0, row = 0
301 -5, 6, -7, 8, // out = 1, row = 0
302 4, -2, 3, -1, // out = 0, row = 1
303 -8, -6, 7, 5, // out = 1, row = 1
305 std::vector<float> bias_data{1, 2};
306 Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
307 Tensor filter_tensor = makeInputTensor<DataType::FLOAT32>(filter_shape, filter_data);
308 Tensor bias_tensor = makeInputTensor<DataType::FLOAT32>(bias_shape, bias_data);
309 Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
311 Conv2DParams params{};
312 params.padding = Padding::VALID;
313 params.stride_height = 2;
314 params.stride_width = 1;
315 params.dilation_height_factor = 1;
316 params.dilation_width_factor = 1;
317 params.activation = Activation::RELU;
319 Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, params);
320 EXPECT_ANY_THROW(kernel.configure());
324 } // namespace kernels
325 } // namespace luci_interpreter