1# Copyright 2019 The TensorFlow Authors. All Rights Reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14# ============================================================================== 15"""Test configs for reduce operators.""" 16import numpy as np 17import tensorflow.compat.v1 as tf 18from tensorflow.lite.testing.zip_test_utils import create_tensor_data 19from tensorflow.lite.testing.zip_test_utils import make_zip_of_tests 20from tensorflow.lite.testing.zip_test_utils import register_make_test_function 21 22 23def make_reduce_tests(reduce_op, 24 min_value=-10, 25 max_value=10, 26 boolean_tensor_only=False, 27 allow_fully_quantize=False): 28 """Make a set of tests to do reduce operation. 29 30 Args: 31 reduce_op: TensorFlow reduce operation to test, i.e. `tf.reduce_mean`. 32 min_value: min value for created tensor data. 33 max_value: max value for created tensor data. 34 boolean_tensor_only: If true, will only generate tensor with boolean value. 35 allow_fully_quantize: bool, whether fully_quantize is allowed. 36 37 Returns: 38 a function representing the true generator with `reduce_op_in` curried. 39 """ 40 41 def f(options): 42 """Actual function that generates examples.""" 43 44 test_parameters = [ 45 { 46 "input_dtype": [tf.float32, tf.int32, tf.int64], 47 "input_shape": [[3, 3, 2, 4]], 48 "axis": [ 49 0, 50 1, 51 2, 52 [0, 1], 53 [0, 2], 54 [1, 2], 55 [0, 1, 2], 56 [1, 0], 57 [2, 0], 58 [2, 1], 59 [2, 1, 0], 60 [2, 0, 1], 61 -1, 62 -2, 63 -3, 64 [1, -1], 65 [0, -1], 66 [-1, 0], 67 [-1, -2, -3], 68 ], 69 "const_axis": [True, False], 70 "keepdims": [True, False], 71 "fully_quantize": [False], 72 }, 73 { 74 "input_dtype": [tf.float32], 75 "input_shape": [[1, 8, 8, 3]], 76 "axis": [ 77 0, 78 1, 79 2, 80 3, 81 [1, 2], 82 [0, 3], 83 [1, 2, 3], 84 [0, 1, 2, 3], 85 [3, 2, 1, 0], 86 [3, 1, 0, 2], 87 [2, 0], 88 [3, 0], 89 [3, 1], 90 [1, 0], 91 -1, 92 -2, 93 -3, 94 -4, 95 [0, -2], 96 [2, 3, 1, 0], 97 [3, 1, 2], 98 [3, -4], 99 ], 100 "const_axis": [True, False], 101 "keepdims": [True, False], 102 "fully_quantize": [False], 103 }, 104 { 105 "input_dtype": [tf.float32], 106 "input_shape": [[], [1, 8, 8, 3], [3, 2, 4]], 107 "axis": [[]], # shape is: [0] 108 "const_axis": [False], 109 "keepdims": [True, False], 110 "fully_quantize": [False], 111 }, 112 { 113 "input_dtype": [tf.float32], 114 "input_shape": [[], [1, 8, 8, 3], [3, 2, 4]], 115 "axis": [None], # shape is: [] 116 "const_axis": [True], 117 "keepdims": [True, False], 118 "fully_quantize": [False], 119 }, 120 { 121 "input_dtype": [tf.float32], 122 "input_shape": [[3, 3, 2, 4]], 123 "axis": [ 124 0, 125 1, 126 2, 127 [0, 1], 128 [0, 2], 129 [1, 2], 130 [0, 1, 2], 131 [1, 0], 132 [2, 0], 133 [2, 1], 134 [2, 1, 0], 135 [2, 0, 1], 136 -1, 137 -2, 138 -3, 139 [1, -1], 140 [0, -1], 141 [-1, 0], 142 [-1, -2, -3], 143 ], 144 "const_axis": [True], 145 "keepdims": [True, False], 146 "fully_quantize": [True], 147 }, 148 { 149 "input_dtype": [tf.float32], 150 "input_shape": [[1, 8, 8, 4], [1, 8, 8, 3]], 151 "axis": [ 152 0, 1, 2, 3, [0], [1], [2], [3], [-1], [-2], [-3], [1, 2], 153 [0, 3], [1, 2, 3], [1, 3], [2, 3] 154 ], 155 "const_axis": [True], 156 "keepdims": [True, False], 157 "fully_quantize": [True], 158 }, 159 { 160 "input_dtype": [tf.float32, tf.int32], 161 "input_shape": [[2, 0, 2], [0]], 162 "axis": [0], 163 "const_axis": [True], 164 "keepdims": [True, False], 165 "fully_quantize": [False], 166 }, 167 ] 168 # test_parameters include fully_quantize option only when 169 # allow_fully_quantize is True. 170 if not allow_fully_quantize: 171 test_parameters = [ 172 test_parameter for test_parameter in test_parameters 173 if True not in test_parameter["fully_quantize"] 174 ] 175 176 def build_graph(parameters): 177 """Build the mean op testing graph.""" 178 dtype = parameters["input_dtype"] 179 if boolean_tensor_only: 180 dtype = tf.bool 181 input_tensor = tf.compat.v1.placeholder( 182 dtype=dtype, name="input", shape=parameters["input_shape"]) 183 184 # Get axis as either a placeholder or constants. 185 if parameters["const_axis"]: 186 axis = parameters["axis"] 187 input_tensors = [input_tensor] 188 else: 189 if isinstance(parameters["axis"], list): 190 shape = [len(parameters["axis"])] 191 else: 192 shape = [] # shape for None or integers. 193 axis = tf.compat.v1.placeholder( 194 dtype=tf.int32, name="axis", shape=shape) 195 input_tensors = [input_tensor, axis] 196 197 out = reduce_op(input_tensor, axis=axis, keepdims=parameters["keepdims"]) 198 return input_tensors, [out] 199 200 def build_inputs(parameters, sess, inputs, outputs): 201 """Build the inputs for reduced operators.""" 202 203 dtype = parameters["input_dtype"] 204 if boolean_tensor_only: 205 dtype = tf.bool 206 values = [ 207 create_tensor_data( 208 dtype, 209 parameters["input_shape"], 210 min_value=min_value, 211 max_value=max_value) 212 ] 213 if not parameters["const_axis"]: 214 values.append(np.array(parameters["axis"])) 215 return values, sess.run(outputs, feed_dict=dict(zip(inputs, values))) 216 217 make_zip_of_tests(options, test_parameters, build_graph, build_inputs) 218 219 return f 220 221 222@register_make_test_function() 223def make_mean_tests(options): 224 """Make a set of tests to do mean.""" 225 return make_reduce_tests( 226 tf.reduce_mean, 227 min_value=-1, 228 max_value=1, 229 boolean_tensor_only=False, 230 allow_fully_quantize=True)( 231 options) 232 233 234@register_make_test_function() 235def make_sum_tests(options): 236 """Make a set of tests to do sum.""" 237 return make_reduce_tests( 238 tf.reduce_sum, 239 min_value=-1, 240 max_value=1, 241 boolean_tensor_only=False, 242 allow_fully_quantize=True)( 243 options) 244 245 246@register_make_test_function() 247def make_reduce_prod_tests(options): 248 """Make a set of tests to do prod.""" 249 # set min max value to be -2, 2 to avoid overflow. 250 return make_reduce_tests(tf.reduce_prod, -2, 2)(options) 251 252 253@register_make_test_function() 254def make_reduce_max_tests(options): 255 """Make a set of tests to do max.""" 256 return make_reduce_tests( 257 tf.reduce_max, allow_fully_quantize=True, min_value=-1, max_value=1)( 258 options) 259 260 261@register_make_test_function() 262def make_reduce_min_tests(options): 263 """Make a set of tests to do min.""" 264 return make_reduce_tests( 265 tf.reduce_min, allow_fully_quantize=True, min_value=-1, max_value=1)( 266 options) 267 268 269@register_make_test_function() 270def make_reduce_any_tests(options): 271 """Make a set of tests to do any.""" 272 return make_reduce_tests(tf.reduce_any, boolean_tensor_only=True)(options) 273 274 275@register_make_test_function() 276def make_reduce_all_tests(options): 277 """Make a set of tests to do all.""" 278 return make_reduce_tests(tf.reduce_all, boolean_tensor_only=True)(options) 279