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