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));
184 } // namespace kernels
185 } // namespace luci_interpreter