1 // Tencent is pleased to support the open source community by making ncnn available.
2 //
3 // Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
4 //
5 // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
6 // in compliance with the License. You may obtain a copy of the License at
7 //
8 // https://opensource.org/licenses/BSD-3-Clause
9 //
10 // Unless required by applicable law or agreed to in writing, software distributed
11 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 // specific language governing permissions and limitations under the License.
14
15 #include "layer/innerproduct.h"
16 #include "testutil.h"
17
test_innerproduct(const ncnn::Mat & a,int outch,int bias)18 static int test_innerproduct(const ncnn::Mat& a, int outch, int bias)
19 {
20 ncnn::ParamDict pd;
21 pd.set(0, outch); // num_output
22 pd.set(1, bias); // bias_term
23 pd.set(2, outch * a.w * a.h * a.c);
24
25 int activation_type = RAND() % 6; // 0 1 2 3 4 5
26 ncnn::Mat activation_params(2);
27 activation_params[0] = RandomFloat(-1, 0); // alpha
28 activation_params[1] = RandomFloat(0, 1); // beta
29 pd.set(9, activation_type);
30 pd.set(10, activation_params);
31
32 std::vector<ncnn::Mat> weights(bias ? 2 : 1);
33 weights[0] = RandomMat(outch * a.w * a.h * a.c);
34 if (bias)
35 weights[1] = RandomMat(outch);
36
37 int ret = test_layer<ncnn::InnerProduct>("InnerProduct", pd, weights, a);
38 if (ret != 0)
39 {
40 fprintf(stderr, "test_innerproduct failed a.dims=%d a=(%d %d %d) outch=%d bias=%d act=%d actparams=[%f,%f]\n", a.dims, a.w, a.h, a.c, outch, bias, activation_type, activation_params[0], activation_params[1]);
41 }
42
43 return ret;
44 }
45
test_innerproduct_0()46 static int test_innerproduct_0()
47 {
48 return 0
49 || test_innerproduct(RandomMat(1, 3, 1), 1, 1)
50 || test_innerproduct(RandomMat(3, 2, 2), 2, 0)
51 || test_innerproduct(RandomMat(9, 3, 8), 7, 1)
52 || test_innerproduct(RandomMat(2, 2, 8), 8, 0)
53 || test_innerproduct(RandomMat(4, 3, 15), 8, 1)
54 || test_innerproduct(RandomMat(6, 2, 16), 16, 0)
55 || test_innerproduct(RandomMat(6, 2, 16), 7, 1)
56 || test_innerproduct(RandomMat(6, 2, 5), 16, 1);
57 }
58
test_innerproduct_1()59 static int test_innerproduct_1()
60 {
61 return 0
62 || test_innerproduct(RandomMat(1, 1), 1, 1)
63 || test_innerproduct(RandomMat(3, 2), 2, 0)
64 || test_innerproduct(RandomMat(9, 8), 7, 1)
65 || test_innerproduct(RandomMat(2, 8), 8, 0)
66 || test_innerproduct(RandomMat(4, 15), 8, 1)
67 || test_innerproduct(RandomMat(6, 16), 16, 0)
68 || test_innerproduct(RandomMat(6, 16), 7, 1)
69 || test_innerproduct(RandomMat(6, 5), 16, 1);
70 }
71
test_innerproduct_2()72 static int test_innerproduct_2()
73 {
74 return 0
75 || test_innerproduct(RandomMat(1), 1, 1)
76 || test_innerproduct(RandomMat(2), 2, 0)
77 || test_innerproduct(RandomMat(8), 7, 1)
78 || test_innerproduct(RandomMat(8), 8, 0)
79 || test_innerproduct(RandomMat(15), 8, 1)
80 || test_innerproduct(RandomMat(15), 15, 1)
81 || test_innerproduct(RandomMat(16), 16, 0)
82 || test_innerproduct(RandomMat(16), 7, 1)
83 || test_innerproduct(RandomMat(5), 16, 0)
84 || test_innerproduct(RandomMat(32), 16, 1)
85 || test_innerproduct(RandomMat(12), 16, 0)
86 || test_innerproduct(RandomMat(16), 12, 1)
87 || test_innerproduct(RandomMat(24), 32, 1);
88 }
89
90 #if NCNN_INT8
test_innerproduct_int8(const ncnn::Mat & a,int outch,int bias)91 static int test_innerproduct_int8(const ncnn::Mat& a, int outch, int bias)
92 {
93 ncnn::ParamDict pd;
94 pd.set(0, outch); // num_output
95 pd.set(1, bias); // bias_term
96 pd.set(2, outch * a.w * a.h * a.c);
97 pd.set(8, 1); // int8_scale_term
98
99 int activation_type = RAND() % 6; // 0 1 2 3 4 5
100 ncnn::Mat activation_params(2);
101 activation_params[0] = RandomFloat(-1, 0); // alpha
102 activation_params[1] = RandomFloat(0, 1); // beta
103 pd.set(9, activation_type);
104 pd.set(10, activation_params);
105
106 std::vector<ncnn::Mat> weights(bias ? 4 : 3);
107 const int k = a.w * a.h * a.c;
108 weights[0] = RandomMat(outch * k);
109 ncnn::Mat weight_scales = scales_mat(weights[0], outch, k, k);
110 ncnn::Mat input_scales = scales_mat(a, 1, k, k);
111
112 if (bias)
113 {
114 weights[1] = RandomMat(outch);
115 weights[2] = weight_scales;
116 weights[3] = input_scales;
117 }
118 else
119 {
120 weights[1] = weight_scales;
121 weights[2] = input_scales;
122 }
123
124 int flag = TEST_LAYER_DISABLE_GPU_TESTING;
125 int ret = test_layer<ncnn::InnerProduct>("InnerProduct", pd, weights, a, 0.001f, 0, flag);
126 if (ret != 0)
127 {
128 fprintf(stderr, "test_innerproduct_int8 failed a.dims=%d a=(%d %d %d) outch=%d bias=%d act=%d actparams=[%f,%f]\n", a.dims, a.w, a.h, a.c, outch, bias, activation_type, activation_params[0], activation_params[1]);
129 }
130
131 return ret;
132 }
133
test_innerproduct_3()134 static int test_innerproduct_3()
135 {
136 return 0
137 || test_innerproduct_int8(RandomMat(1, 3, 1), 1, 1)
138 || test_innerproduct_int8(RandomMat(3, 2, 2), 2, 1)
139 || test_innerproduct_int8(RandomMat(5, 3, 3), 3, 1)
140 || test_innerproduct_int8(RandomMat(7, 2, 3), 12, 1)
141 || test_innerproduct_int8(RandomMat(9, 3, 4), 4, 1)
142 || test_innerproduct_int8(RandomMat(2, 2, 7), 7, 1)
143 || test_innerproduct_int8(RandomMat(4, 3, 8), 3, 1)
144 || test_innerproduct_int8(RandomMat(6, 2, 8), 8, 1)
145 || test_innerproduct_int8(RandomMat(8, 3, 15), 15, 1)
146 || test_innerproduct_int8(RandomMat(7, 2, 16), 4, 1)
147 || test_innerproduct_int8(RandomMat(6, 3, 16), 16, 1);
148 }
149 #endif // NCNN_INT8
150
test_innerproduct_gemm(const ncnn::Mat & a,int outch,int bias)151 static int test_innerproduct_gemm(const ncnn::Mat& a, int outch, int bias)
152 {
153 ncnn::ParamDict pd;
154 pd.set(0, outch);
155 pd.set(1, bias);
156 pd.set(2, outch * a.w);
157
158 int activation_type = RAND() % 6;
159 ncnn::Mat activation_params(2);
160 activation_params[0] = RandomFloat(-1, 0);
161 activation_params[1] = RandomFloat(0, 1);
162 pd.set(9, activation_type);
163 pd.set(10, activation_params);
164
165 std::vector<ncnn::Mat> weights(bias ? 2 : 1);
166 weights[0] = RandomMat(outch * a.w);
167 if (bias)
168 weights[1] = RandomMat(outch);
169
170 int ret = test_layer<ncnn::InnerProduct>("InnerProduct", pd, weights, a);
171 if (ret != 0)
172 {
173 fprintf(stderr, "test_innerproduct_gemm failed a.dims=%d a=(%d %d %d) outch=%d bias=%d act=%d actparams=[%f,%f]\n", a.dims, a.w, a.h, a.c, outch, bias, activation_type, activation_params[0], activation_params[1]);
174 }
175
176 return ret;
177 }
178
test_innerproduct_4()179 static int test_innerproduct_4()
180 {
181 return 0
182 || test_innerproduct_gemm(RandomMat(1, 5), 1, 1)
183 || test_innerproduct_gemm(RandomMat(3, 2), 2, 0)
184 || test_innerproduct_gemm(RandomMat(9, 8), 7, 1)
185 || test_innerproduct_gemm(RandomMat(2, 8), 8, 0)
186 || test_innerproduct_gemm(RandomMat(13, 12), 8, 1)
187 || test_innerproduct_gemm(RandomMat(16, 12), 16, 0)
188 || test_innerproduct_gemm(RandomMat(11, 24), 8, 0)
189 || test_innerproduct_gemm(RandomMat(13, 24), 12, 1)
190 || test_innerproduct_gemm(RandomMat(15, 12), 20, 1)
191 || test_innerproduct_gemm(RandomMat(16, 12), 11, 1)
192 || test_innerproduct_gemm(RandomMat(19, 16), 16, 1)
193 || test_innerproduct_gemm(RandomMat(14, 15), 8, 1)
194 || test_innerproduct_gemm(RandomMat(17, 15), 12, 1)
195 || test_innerproduct_gemm(RandomMat(12, 16), 7, 1);
196 }
197
198 #if NCNN_INT8
test_innerproduct_gemm_int8(const ncnn::Mat & a,int outch,int bias)199 static int test_innerproduct_gemm_int8(const ncnn::Mat& a, int outch, int bias)
200 {
201 ncnn::ParamDict pd;
202 pd.set(0, outch);
203 pd.set(1, bias);
204 pd.set(2, outch * a.w);
205 pd.set(8, 1); // int8_scale_term
206
207 std::vector<ncnn::Mat> weights(bias ? 4 : 3);
208 const int k = a.w;
209 weights[0] = RandomMat(outch * k);
210 ncnn::Mat weight_scales = scales_mat(weights[0], outch, k, k);
211 ncnn::Mat input_scales = scales_mat(a, 1, k, k);
212
213 if (bias)
214 {
215 weights[1] = RandomMat(outch);
216 weights[2] = weight_scales;
217 weights[3] = input_scales;
218 }
219 else
220 {
221 weights[1] = weight_scales;
222 weights[2] = input_scales;
223 }
224
225 int flag = TEST_LAYER_DISABLE_GPU_TESTING;
226 int ret = test_layer<ncnn::InnerProduct>("InnerProduct", pd, weights, a, 0.001f, 0, flag);
227 if (ret != 0)
228 {
229 fprintf(stderr, "test_innerproduct_gemm_int8 failed a.dims=%d a=(%d %d %d) outch=%d bias=%d\n", a.dims, a.w, a.h, a.c, outch, bias);
230 }
231
232 return ret;
233 }
234
test_innerproduct_5()235 static int test_innerproduct_5()
236 {
237 return 0
238 || test_innerproduct_gemm_int8(RandomMat(1, 5), 1, 1)
239 || test_innerproduct_gemm_int8(RandomMat(3, 2), 2, 0)
240 || test_innerproduct_gemm_int8(RandomMat(9, 8), 7, 1)
241 || test_innerproduct_gemm_int8(RandomMat(2, 8), 8, 0)
242 || test_innerproduct_gemm_int8(RandomMat(13, 12), 8, 1)
243 || test_innerproduct_gemm_int8(RandomMat(16, 12), 16, 0)
244 || test_innerproduct_gemm_int8(RandomMat(4, 15), 8, 1)
245 || test_innerproduct_gemm_int8(RandomMat(6, 16), 16, 0)
246 || test_innerproduct_gemm_int8(RandomMat(12, 16), 7, 1);
247 }
248 #endif // NCNN_INT8
249
main()250 int main()
251 {
252 SRAND(7767517);
253
254 #if NCNN_INT8
255 return 0
256 || test_innerproduct_0()
257 || test_innerproduct_1()
258 || test_innerproduct_2()
259 || test_innerproduct_3()
260 || test_innerproduct_4()
261 || test_innerproduct_5();
262 #else
263 return 0
264 || test_innerproduct_0()
265 || test_innerproduct_1()
266 || test_innerproduct_2()
267 || test_innerproduct_4();
268 #endif
269 }
270