1#
2# Copyright (C) 2018 The Android Open Source Project
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
17layout = BoolScalar("layout", False) # NHWC
18
19# TEST 1: TRANSPOSE_CONV2D, pad = valid, stride = 2
20i1 = Input("op1", "TENSOR_FLOAT32", "{1, 2, 2, 1}") # input 0
21w1 = Parameter("op2", "TENSOR_FLOAT32", "{2, 3, 3, 1}", [1, 3, 5, 7, 9, 11, 13, 15, 17, 2, 4, 6, 8, 10, 12, 14, 16, 18]) # weight
22b1 = Parameter("op3", "TENSOR_FLOAT32", "{2}", [-1.5, -2]) # bias
23s1 = Int32Vector("shape", [1, 5, 5, 2]) # output shape
24act = Int32Scalar("act", 0) # act = none
25o1 = Output("op4", "TENSOR_FLOAT32", "{1, 5, 5, 2}") # output
26Model().Operation("TRANSPOSE_CONV_2D", i1, w1, b1, s1, 2, 2, 2, act, layout).To(o1)
27
28# Additional data type
29quant8 = DataTypeConverter().Identify({
30    i1: ("TENSOR_QUANT8_ASYMM", 0.5, 0),
31    w1: ("TENSOR_QUANT8_ASYMM", 0.5, 0),
32    b1: ("TENSOR_INT32", 0.25, 0),
33    o1: ("TENSOR_QUANT8_ASYMM", 0.5, 0)
34})
35
36quant8_mult_gt_1 = DataTypeConverter().Identify({
37    i1: ("TENSOR_QUANT8_ASYMM", 0.5, 100),
38    w1: ("TENSOR_QUANT8_ASYMM", 0.5, 128),
39    b1: ("TENSOR_INT32", 0.25, 0),
40    o1: ("TENSOR_QUANT8_ASYMM", 0.1, 80)
41})
42
43# Per-channel quantization
44channelQuant8 = DataTypeConverter().Identify({
45    i1: ("TENSOR_QUANT8_ASYMM", 0.25, 100),
46    w1: ("TENSOR_QUANT8_SYMM_PER_CHANNEL", 0, 0, SymmPerChannelQuantParams(channelDim=0, scales=[0.25, 0.5])),
47    b1: ("TENSOR_INT32", 0.0, 0, SymmPerChannelQuantParams(channelDim=0, scales=[0.0625, 0.125], hide=True)),
48    o1: ("TENSOR_QUANT8_ASYMM", 0.5, 80)
49})
50
51channelQuant8_mult_gt_1 = DataTypeConverter().Identify({
52    i1: ("TENSOR_QUANT8_ASYMM", 0.25, 100),
53    w1: ("TENSOR_QUANT8_SYMM_PER_CHANNEL", 0, 0, SymmPerChannelQuantParams(channelDim=0, scales=[0.25, 0.5])),
54    b1: ("TENSOR_INT32", 0.0, 0, SymmPerChannelQuantParams(channelDim=0, scales=[0.0625, 0.125], hide=True)),
55    o1: ("TENSOR_QUANT8_ASYMM", 0.1, 80)
56})
57
58Example({
59    i1: [1, 2, 3, 4],
60    o1: [-0.5,  0,  1.5,  2,   5.5,   8,  4.5,  6,  8.5, 10,
61          5.5,  6,  7.5,  8,  23.5,  26, 16.5, 18, 20.5, 22,
62         14.5, 18, 22.5, 26,  60.5,  70, 40.5, 46, 52.5, 58,
63         19.5, 22, 25.5, 28,  59.5,  66, 34.5, 38, 42.5, 46,
64         37.5, 40, 43.5, 46, 101.5, 108, 58.5, 62, 66.5, 70]
65}).AddNchw(i1, o1, s1, layout).AddAllActivations(o1, act).AddVariations("relaxed", quant8, quant8_mult_gt_1, channelQuant8, channelQuant8_mult_gt_1, "float16").AddInput(w1, b1)
66
67
68# TEST 2: TRANSPOSE_CONV2D_LARGE, pad = same, stride = 3, act = relu
69i2 = Input("op1", "TENSOR_FLOAT32", "{1, 1, 2, 1}") # input 0
70w2 = Parameter("op2", "TENSOR_FLOAT32", "{1, 3, 3, 1}", [9, 5, 6, 9, 8, 5, 3, 1, 4]) # weight
71b2 = Parameter("op3", "TENSOR_FLOAT32", "{1}", [-1000]) # bias
72s2 = Int32Vector("shape", [1, 3, 4, 1]) # output shape
73o2 = Output("op4", "TENSOR_FLOAT32", "{1, 3, 4, 1}") # output
74Model().Operation("TRANSPOSE_CONV_2D", i2, w2, b2, s2, 1, 3, 3, 1, layout).To(o2)
75
76# Additional data type
77quant8 = DataTypeConverter().Identify({
78    i2: ("TENSOR_QUANT8_ASYMM", 2.0, 0),
79    w2: ("TENSOR_QUANT8_ASYMM", 0.25, 128),
80    b2: ("TENSOR_INT32", 0.5, 0),
81    o2: ("TENSOR_QUANT8_ASYMM", 20.0, 50)
82})
83
84# Per-channel quantization
85channelQuant8 = DataTypeConverter().Identify({
86    i2: ("TENSOR_QUANT8_ASYMM", 2.0, 0),
87    w2: ("TENSOR_QUANT8_SYMM_PER_CHANNEL", 0, 0, SymmPerChannelQuantParams(channelDim=0, scales=[0.25])),
88    b2: ("TENSOR_INT32", 0.0, 0, SymmPerChannelQuantParams(channelDim=0, scales=[0.5], hide=True)),
89    o2: ("TENSOR_QUANT8_ASYMM", 20.0, 50)
90})
91
92Example({
93    i2: [300, 500],
94    o2: [500.,  800.,  3500., 1500.,
95         1400., 500.,  3500., 3000.,
96         0.,    200.,  500.,  0.]
97}).AddNchw(i2, o2, s2, layout).AddVariations("relaxed", quant8, channelQuant8, "float16").AddInput(w2, b2)
98
99
100# TEST 3: TRANSPOSE_CONV2D_SAME, outputShape = [1, 4, 4, 1], pad = same, stride = 1, act = none
101i3 = Input("op1", "TENSOR_FLOAT32", "{1, 4, 4, 2}") # input 0
102w3 = Parameter("op2", "TENSOR_FLOAT32", "{1, 3, 3, 2}", [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]) # weight
103b3 = Parameter("op3", "TENSOR_FLOAT32", "{1}", [0]) # bias
104s3 = Int32Vector("shape", [1, 4, 4, 1]) # output shape
105o3 = Output("op4", "TENSOR_FLOAT32", "{1, 4, 4, 1}") # output
106Model().Operation("TRANSPOSE_CONV_2D", i3, w3, b3, s3, 1, 1, 1, 0, layout).To(o3)
107
108# Additional data type
109quant8 = DataTypeConverter().Identify({
110    i3: ("TENSOR_QUANT8_ASYMM", 0.5, 100),
111    w3: ("TENSOR_QUANT8_ASYMM", 0.5, 128),
112    b3: ("TENSOR_INT32", 0.25, 0),
113    o3: ("TENSOR_QUANT8_ASYMM", 16.0, 0)
114})
115
116Example({
117    i3: [1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15, 16,
118         17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32],
119    o3: [184,  412,  568,  528,
120         678,  1347, 1689, 1434,
121         1494, 2715, 3057, 2442,
122         1968, 3352, 3652, 2760]
123}).AddNchw(i3, o3, s3, layout).AddVariations("relaxed", quant8, "float16").AddInput(w3, b3)
124
125
126# TEST 4: TRANSPOSE_CONV2D_VALID, outputShape = [1, 6, 6, 1], pad = valid, stride = 1, act = none
127i4 = Input("op1", "TENSOR_FLOAT32", "{1, 4, 4, 2}") # input 0
128w4 = Parameter("op2", "TENSOR_FLOAT32", "{1, 3, 3, 2}", [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]) # weight
129b4 = Parameter("op3", "TENSOR_FLOAT32", "{1}", [0]) # bias
130s4 = Int32Vector("shape", [1, 6, 6, 1]) # output shape
131o4 = Output("op4", "TENSOR_FLOAT32", "{1, 6, 6, 1}") # output
132Model().Operation("TRANSPOSE_CONV_2D", i4, w4, b4, s4, 2, 1, 1, 0, layout).To(o4)
133
134# Additional data type
135quant8 = DataTypeConverter().Identify({
136    i4: ("TENSOR_QUANT8_ASYMM", 0.25, 10),
137    w4: ("TENSOR_QUANT8_ASYMM", 0.5, 128),
138    b4: ("TENSOR_INT32", 0.125, 0),
139    o4: ("TENSOR_QUANT8_ASYMM", 32.0, 80)
140})
141
142Example({
143    i4: [1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15, 16,
144         17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32],
145    o4: [5,    22,   59,   101,  114,  83,
146         52,   184,  412,  568,  528,  344,
147         237,  678,  1347, 1689, 1434, 879,
148         597,  1494, 2715, 3057, 2442, 1431,
149         856,  1968, 3352, 3652, 2760, 1548,
150         689,  1534, 2543, 2729, 2010, 1103]
151}).AddNchw(i4, o4, s4, layout).AddVariations("relaxed", quant8, "float16").AddInput(w4, b4)
152
153
154# TEST 5: TRANSPOSE_CONV2D_EXPLICIT, pad = [1, 2, 2, 1], stride = 1, act = none
155i5 = Input("op1", "TENSOR_FLOAT32", "{1, 4, 4, 2}") # input 0
156w5 = Parameter("op2", "TENSOR_FLOAT32", "{1, 3, 3, 2}", [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]) # weight
157b5 = Parameter("op3", "TENSOR_FLOAT32", "{1}", [0]) # bias
158o5 = Output("op4", "TENSOR_FLOAT32", "{1, 3, 3, 1}") # output
159Model().Operation("TRANSPOSE_CONV_2D", i5, w5, b5, 1, 2, 2, 1, 1, 1, 0, layout).To(o5)
160
161# Additional data type
162quant8 = DataTypeConverter().Identify({
163    i5: ("TENSOR_QUANT8_ASYMM", 0.5, 100),
164    w5: ("TENSOR_QUANT8_ASYMM", 0.25, 128),
165    b5: ("TENSOR_INT32", 0.125, 0),
166    o5: ("TENSOR_QUANT8_ASYMM", 20.0, 50)
167})
168
169Example({
170    i5: [1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15, 16,
171         17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32],
172    o5: [678,  1347, 1689,
173         1494, 2715, 3057,
174         1968, 3352, 3652]
175}).AddNchw(i5, o5, layout).AddVariations("relaxed", quant8, "float16").AddInput(w5, b5)
176
177
178# TEST 6: zero-sized input, implicit padding
179
180# Use BOX_WITH_NMS_LIMIT op to generate a zero-sized internal tensor for box cooridnates.
181p1 = Parameter("scores", "TENSOR_FLOAT32", "{1, 2}", [0.90, 0.10]) # scores
182p2 = Parameter("roi", "TENSOR_FLOAT32", "{1, 8}", [1, 1, 10, 10, 0, 0, 10, 10]) # roi
183o1 = Output("scoresOut", "TENSOR_FLOAT32", "{0}") # scores out
184o2 = Output("classesOut", "TENSOR_INT32", "{0}") # classes out
185tmp1 = Internal("roiOut", "TENSOR_FLOAT32", "{0, 4}") # roi out
186tmp2 = Internal("batchSplitOut", "TENSOR_INT32", "{0}") # batch split out
187model = Model("zero_sized").Operation("BOX_WITH_NMS_LIMIT", p1, p2, [0], 0.3, -1, 0, 0.4, 1.0, 0.3).To(o1, tmp1, o2, tmp2)
188
189# Use ROI_ALIGN op to convert into zero-sized feature map.
190i1 = Input("in", "TENSOR_FLOAT32", "{1, 1, 1, 1}")
191zero_sized = Internal("featureMap", "TENSOR_FLOAT32", "{0, 2, 2, 1}")
192model = model.Operation("ROI_ALIGN", i1, tmp1, tmp2, 2, 2, 2.0, 2.0, 4, 4, layout).To(zero_sized)
193
194# TRANSPOSE_CONV_2D op with numBatches = 0.
195w = Parameter("weights", "TENSOR_FLOAT32", "{2, 3, 3, 1}", [1, 3, 5, 7, 9, 11, 9, 7, 5, 2, 4, 6, 8, 10, 12, 10, 8, 6]) # weight
196b = Parameter("bias", "TENSOR_FLOAT32", "{2}", [-1.5, -2]) # bias
197s = Int32Vector("shape", [0, 5, 5, 2]) # output shape
198o3 = Output("out", "TENSOR_FLOAT32", "{0, 5, 5, 2}") # out
199model = model.Operation("TRANSPOSE_CONV_2D", zero_sized, w, b, s, 2, 2, 2, 0, layout).To(o3)
200
201quant8 = DataTypeConverter().Identify({
202    p1: ("TENSOR_QUANT8_ASYMM", 0.1, 128),
203    p2: ("TENSOR_QUANT16_ASYMM", 0.125, 0),
204    o1: ("TENSOR_QUANT8_ASYMM", 0.1, 128),
205    tmp1: ("TENSOR_QUANT16_ASYMM", 0.125, 0),
206    i1: ("TENSOR_QUANT8_ASYMM", 0.1, 128),
207    zero_sized: ("TENSOR_QUANT8_ASYMM", 0.1, 128),
208    w: ("TENSOR_QUANT8_ASYMM", 0.1, 128),
209    b: ("TENSOR_INT32", 0.01, 0),
210    o3: ("TENSOR_QUANT8_ASYMM", 0.1, 128)
211})
212
213# Create test case with dummy values.
214Example({
215    i1: [1],
216    o1: [0],
217    o2: [0],
218    o3: [0],
219}).AddNchw(i1, zero_sized, o3, s, layout).AddVariations("relaxed", quant8, "float16")
220
221
222# TEST 7: zero-sized input, explicit padding
223
224# Use BOX_WITH_NMS_LIMIT op to generate a zero-sized internal tensor for box cooridnates.
225p1 = Parameter("scores", "TENSOR_FLOAT32", "{1, 2}", [0.90, 0.10]) # scores
226p2 = Parameter("roi", "TENSOR_FLOAT32", "{1, 8}", [1, 1, 10, 10, 0, 0, 10, 10]) # roi
227o1 = Output("scoresOut", "TENSOR_FLOAT32", "{0}") # scores out
228o2 = Output("classesOut", "TENSOR_INT32", "{0}") # classes out
229tmp1 = Internal("roiOut", "TENSOR_FLOAT32", "{0, 4}") # roi out
230tmp2 = Internal("batchSplitOut", "TENSOR_INT32", "{0}") # batch split out
231model = Model("zero_sized").Operation("BOX_WITH_NMS_LIMIT", p1, p2, [0], 0.3, -1, 0, 0.4, 1.0, 0.3).To(o1, tmp1, o2, tmp2)
232
233# Use ROI_ALIGN op to convert into zero-sized feature map.
234i1 = Input("in", "TENSOR_FLOAT32", "{1, 1, 1, 1}")
235zero_sized = Internal("featureMap", "TENSOR_FLOAT32", "{0, 4, 4, 1}")
236model = model.Operation("ROI_ALIGN", i1, tmp1, tmp2, 4, 4, 2.0, 2.0, 4, 4, layout).To(zero_sized)
237
238# TRANSPOSE_CONV_2D op with numBatches = 0.
239w = Parameter("weights", "TENSOR_FLOAT32", "{1, 3, 3, 1}", [1, 3, 5, 7, 9, 11, 9, 7, 5]) # weight
240b = Parameter("bias", "TENSOR_FLOAT32", "{1}", [-1.5]) # bias
241o3 = Output("out", "TENSOR_FLOAT32", "{0, 3, 3, 1}") # out
242model = model.Operation("TRANSPOSE_CONV_2D", zero_sized, w, b, 1, 2, 2, 1, 1, 1, 0, layout).To(o3)
243
244quant8 = DataTypeConverter().Identify({
245    p1: ("TENSOR_QUANT8_ASYMM", 0.1, 128),
246    p2: ("TENSOR_QUANT16_ASYMM", 0.125, 0),
247    o1: ("TENSOR_QUANT8_ASYMM", 0.1, 128),
248    tmp1: ("TENSOR_QUANT16_ASYMM", 0.125, 0),
249    i1: ("TENSOR_QUANT8_ASYMM", 0.1, 128),
250    zero_sized: ("TENSOR_QUANT8_ASYMM", 0.1, 128),
251    w: ("TENSOR_QUANT8_ASYMM", 0.1, 128),
252    b: ("TENSOR_INT32", 0.01, 0),
253    o3: ("TENSOR_QUANT8_ASYMM", 0.1, 128)
254})
255
256# Create test case with dummy values.
257Example({
258    i1: [1],
259    o1: [0],
260    o2: [0],
261    o3: [0],
262}).AddNchw(i1, zero_sized, o3, layout).AddVariations("relaxed", quant8, "float16")
263
264
265# TEST 8: TRANSPOSE_CONV2D_SAME, outputShape = [1, 4, 4, 1], pad = same, stride = 2, act = none
266i8 = Input("op1", "TENSOR_FLOAT32", "{1, 2, 2, 1}") # input 0
267w8 = Parameter("op2", "TENSOR_FLOAT32", "{1, 1, 1, 1}", [2]) # weight
268b8 = Parameter("op3", "TENSOR_FLOAT32", "{1}", [0]) # bias
269s8 = Int32Vector("shape", [1, 4, 4, 1]) # output shape
270o8 = Output("op4", "TENSOR_FLOAT32", "{1, 4, 4, 1}") # output
271Model().Operation("TRANSPOSE_CONV_2D", i8, w8, b8, s8, 1, 2, 2, 0, layout).To(o8)
272
273# Additional data type
274quant8 = DataTypeConverter().Identify({
275    i8: ("TENSOR_QUANT8_ASYMM", 0.5, 100),
276    w8: ("TENSOR_QUANT8_ASYMM", 0.5, 128),
277    b8: ("TENSOR_INT32", 0.25, 0),
278    o8: ("TENSOR_QUANT8_ASYMM", 16.0, 0)
279})
280
281Example({
282    i8: [1,  2,  3,  4],
283    o8: [2, 0, 4, 0, 0, 0, 0, 0, 6, 0, 8, 0, 0, 0, 0, 0]
284}).AddNchw(i8, o8, s8, layout).AddVariations("relaxed", quant8, "float16").AddInput(w8, b8)
285