8564de01d1466ad5c45b1173235c62dcfd9b815e
[platform/core/ml/nnfw.git] / compiler / luci-interpreter / src / kernels / TransposeConv.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/TransposeConv.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 template <typename T, typename B>
30 void Check(std::initializer_list<int32_t> output_shape_shape,
31            std::initializer_list<int32_t> weight_shape, std::initializer_list<int32_t> input_shape,
32            std::initializer_list<int32_t> bias_shape, std::initializer_list<int32_t> output_shape,
33            std::initializer_list<int32_t> output_shape_data, std::initializer_list<T> weight_data,
34            std::initializer_list<T> input_data, std::initializer_list<B> bias_data,
35            std::initializer_list<T> output_data, luci::Padding padding, int32_t stride_height,
36            int32_t stride_width)
37 {
38   constexpr DataType element_type = getElementType<T>();
39   Tensor output_shape_tensor =
40       makeInputTensor<DataType::S32>(output_shape_shape, output_shape_data);
41   Tensor weight_tensor = makeInputTensor<element_type>(weight_shape, weight_data);
42   Tensor input_data_tensor = makeInputTensor<element_type>(input_shape, input_data);
43   Tensor output_tensor = makeOutputTensor(element_type);
44
45   TransposeConvParams params{};
46   params.padding = padding;
47   params.stride_height = stride_height;
48   params.stride_width = stride_width;
49
50   if (bias_data.size() != 0)
51   {
52     Tensor bias_tensor = makeInputTensor<getElementType<B>()>(bias_shape, bias_data);
53     TransposeConv kernel(&output_shape_tensor, &weight_tensor, &input_data_tensor, &bias_tensor,
54                          &output_tensor, params);
55     kernel.configure();
56     kernel.execute();
57   }
58   else
59   {
60     TransposeConv kernel(&output_shape_tensor, &weight_tensor, &input_data_tensor, nullptr,
61                          &output_tensor, params);
62     kernel.configure();
63     kernel.execute();
64   }
65   EXPECT_THAT(extractTensorData<T>(output_tensor), ::testing::ElementsAreArray(output_data));
66 }
67
68 TEST(TransposeConvTest, FloatSimple)
69 {
70   Check<float, float>(
71       /*output_shape_shape=*/{4}, /*weight_shape=*/{1, 3, 3, 1}, /*input_shape=*/{1, 4, 4, 1},
72       /*bias_shape=*/{}, /*output_shape=*/{1, 4, 4, 1}, /*output_shape_data=*/{1, 4, 4, 1},
73       /*weight_data=*/{1, 2, 3, 4, 5, 6, 7, 8, 9},
74       /*input_data=*/{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
75       /*bias_data=*/{},
76       /*output_data=*/{29, 62, 83, 75, 99, 192, 237, 198, 207, 372, 417, 330, 263, 446, 485, 365},
77       /*params.padding=*/luci::Padding::SAME, /*stride_height=*/1, /*stride_width=*/1);
78
79   SUCCEED();
80 }
81
82 TEST(TransposeConvTest, FloatTwoFiltersTest)
83 {
84   Check<float, float>(
85       /*output_shape_shape=*/{4}, /*weight_shape=*/{1, 3, 3, 2}, /*input_shape=*/{1, 4, 4, 2},
86       /*bias_shape=*/{}, /*output_shape=*/{1, 4, 4, 1}, /*output_shape_data=*/{1, 4, 4, 1},
87       /*weight_data=*/{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18},
88       /*input_data=*/{1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15, 16,
89                       17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32},
90       /*bias_data=*/{},
91       /*output_data=*/
92       {184, 412, 568, 528, 678, 1347, 1689, 1434, 1494, 2715, 3057, 2442, 1968, 3352, 3652, 2760},
93       /*params.padding=*/luci::Padding::SAME, /*stride_height=*/1, /*stride_width=*/1);
94
95   SUCCEED();
96 }
97
98 TEST(TransposeConvTest, SimpleBiasTest)
99 {
100   Check<float, float>(
101       /*output_shape_shape=*/{4}, /*weight_shape=*/{2, 3, 3, 1},
102       /*input_shape=*/{1, 2, 2, 1},
103       /*bias_shape=*/{2}, /*output_shape=*/{1, 4, 4, 1}, /*output_shape_data=*/{1, 5, 5, 2},
104       /*weight_data=*/{1, 3, 5, 7, 9, 11, 13, 15, 17, 2, 4, 6, 8, 10, 12, 14, 16, 18},
105       /*input_data=*/{1, 2, 3, 4},
106       /*bias_data=*/{3, 4},
107       /*output_data=*/{4,  6,  6,  8,  10, 14, 9,  12, 13, 16, 10,  12,  12, 14, 28, 32, 21,
108                        24, 25, 28, 19, 24, 27, 32, 65, 76, 45, 52,  57,  64, 24, 28, 30, 34,
109                        64, 72, 39, 44, 47, 52, 42, 46, 48, 52, 106, 114, 63, 68, 71, 76},
110       /*params.padding=*/luci::Padding::VALID, /*stride_height=*/2, /*stride_width=*/2);
111
112   SUCCEED();
113 }
114
115 TEST(TransposeConvTest, UInt8)
116 {
117   std::vector<float> input_data{1, 2, 3, 4};
118   std::vector<float> filter_data{1, 3, 5, 7, 9, 11, 13, 15, 17, 2, 4, 6, 8, 10, 12, 14, 16, 18};
119   std::vector<float> bias_data{3, 4};
120   std::vector<int32_t> output_shape_data{1, 5, 5, 2};
121   std::vector<float> ref_output_data{
122       4,  6,  6,  8,  10,  14,  9,  12, 13, 16, //
123       10, 12, 12, 14, 28,  32,  21, 24, 25, 28, //
124       19, 24, 27, 32, 65,  76,  45, 52, 57, 64, //
125       24, 28, 30, 34, 64,  72,  39, 44, 47, 52, //
126       42, 46, 48, 52, 106, 114, 63, 68, 71, 76, //
127   };
128
129   // Choose quantization parameters carefully.
130   auto input_quant = quantizationParams<uint8_t>(-8.0, 7.9375);  // s = 1 / 16, zp = 128
131   auto filter_quant = quantizationParams<uint8_t>(-24.0, 39.75); // s = 1 / 4, zp = 96
132   auto output_quant = quantizationParams<uint8_t>(-64.0, 191.0); // s = 1, zp = 64
133
134   Tensor input_tensor = makeInputTensor<DataType::U8>({1, 2, 2, 1}, input_quant.first,
135                                                       input_quant.second, input_data);
136   Tensor filter_tensor = makeInputTensor<DataType::U8>({2, 3, 3, 1}, filter_quant.first,
137                                                        filter_quant.second, filter_data);
138   Tensor bias_tensor =
139       makeInputTensor<DataType::S32>({2}, input_quant.first * filter_quant.first, 0, bias_data);
140   Tensor output_shape_tensor = makeInputTensor<DataType::S32>({4}, output_shape_data);
141   Tensor output_tensor = makeOutputTensor(DataType::U8, output_quant.first, output_quant.second);
142
143   TransposeConvParams params{};
144   params.padding = Padding::VALID;
145   params.stride_height = 2;
146   params.stride_width = 2;
147
148   TransposeConv kernel(&output_shape_tensor, &filter_tensor, &input_tensor, &bias_tensor,
149                        &output_tensor, params);
150   kernel.configure();
151   kernel.execute();
152
153   EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape_data));
154   EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
155 }
156
157 TEST(TransposeConvTest, SInt16)
158 {
159   std::vector<float> input_data{1, 2, 3, 4};
160   std::vector<float> filter_data{1, 3, 5, 7, 9, 11, 13, 15, 17, 2, 4, 6, 8, 10, 12, 14, 16, 18};
161   std::vector<float> bias_data{3, 4};
162   std::vector<int32_t> output_shape_data{1, 5, 5, 2};
163   std::vector<float> ref_output_data{
164       4,  6,  6,  8,  10,  14,  9,  12, 13, 16, //
165       10, 12, 12, 14, 28,  32,  21, 24, 25, 28, //
166       19, 24, 27, 32, 65,  76,  45, 52, 57, 64, //
167       24, 28, 30, 34, 64,  72,  39, 44, 47, 52, //
168       42, 46, 48, 52, 106, 114, 63, 68, 71, 76, //
169   };
170
171   Tensor input_tensor = makeInputTensor<DataType::S16>({1, 2, 2, 1}, 0.25, 0, input_data);
172   Tensor filter_tensor = makeInputTensor<DataType::S16>({2, 3, 3, 1}, 0.2, 0, filter_data);
173   Tensor bias_tensor = makeInputTensor<DataType::S64>({2}, 0.25 * 0.2, 0, bias_data);
174   Tensor output_shape_tensor = makeInputTensor<DataType::S32>({4}, output_shape_data);
175   Tensor output_tensor = makeOutputTensor(DataType::S16, 0.5, 0);
176
177   TransposeConvParams params{};
178   params.padding = Padding::VALID;
179   params.stride_height = 2;
180   params.stride_width = 2;
181
182   TransposeConv kernel(&output_shape_tensor, &filter_tensor, &input_tensor, &bias_tensor,
183                        &output_tensor, params);
184   kernel.configure();
185   kernel.execute();
186
187   EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape_data));
188   EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
189 }
190
191 TEST(TransposeConvTest, SInt16_CWQ_weights)
192 {
193   const int output_channels = 2;
194   const Shape input_shape{1, 2, 2, 1};
195   const Shape filter_shape{output_channels, 3, 3, 1};
196   const Shape bias_shape{output_channels};
197   std::vector<int32_t> output_shape_data{1, 5, 5, output_channels};
198
199   std::vector<float> input_data{1, 2, 3, 4};
200   std::vector<float> filter_data{1, 3, 5, 7, 9, 11, 13, 15, 17, 2, 4, 6, 8, 10, 12, 14, 16, 18};
201   std::vector<float> bias_data{3, 4};
202
203   std::vector<float> ref_output_data{
204       4,  6,  6,  8,  10,  14,  9,  12, 13, 16, //
205       10, 12, 12, 14, 28,  32,  21, 24, 25, 28, //
206       19, 24, 27, 32, 65,  76,  45, 52, 57, 64, //
207       24, 28, 30, 34, 64,  72,  39, 44, 47, 52, //
208       42, 46, 48, 52, 106, 114, 63, 68, 71, 76, //
209   };
210
211   const float input_scale = 0.25;
212   const float output_scale = 0.5;
213   const std::vector<float> filter_scales{0.2f, 0.5f};
214   std::vector<float> bias_scales{filter_scales[0] * input_scale, filter_scales[1] * input_scale};
215   const std::vector<int32_t> zerop(2, 0);
216
217   Tensor input_tensor = makeInputTensor<DataType::S16>(input_shape, input_scale, 0, input_data);
218   Tensor filter_tensor =
219       makeInputTensor<DataType::S16>(filter_shape, filter_scales, zerop, 0, filter_data);
220   Tensor bias_tensor = makeInputTensor<DataType::S64>(bias_shape, bias_scales, zerop, 0, bias_data);
221   Tensor output_shape_tensor = makeInputTensor<DataType::S32>({4}, output_shape_data);
222   Tensor output_tensor = makeOutputTensor(DataType::S16, output_scale, 0);
223
224   TransposeConvParams params{};
225   params.padding = Padding::VALID;
226   params.stride_height = 2;
227   params.stride_width = 2;
228
229   TransposeConv kernel(&output_shape_tensor, &filter_tensor, &input_tensor, &bias_tensor,
230                        &output_tensor, params);
231   kernel.configure();
232   kernel.execute();
233
234   EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape_data));
235   EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
236 }
237
238 } // namespace
239 } // namespace kernels
240 } // namespace luci_interpreter