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 depthwiseconv.""" 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 23@register_make_test_function() 24def make_depthwiseconv_tests(options): 25 """Make a set of tests to do convolution.""" 26 27 # Tensorflow only supports equal strides 28 test_parameters = [ 29 { 30 "input_shape": [[1, 3, 4, 3], [1, 10, 10, 3]], 31 "filter_size": [[1, 1], [1, 2], [3, 3]], 32 "strides": [[1, 1, 1, 1], [1, 3, 3, 1]], 33 "dilations": [[1, 1, 1, 1], [1, 3, 2, 1], [1, 2, 2, 1]], 34 "channel_multiplier": [1, 2], 35 "rate": [[1, 1]], 36 "padding": ["SAME", "VALID"], 37 "data_format": ["NHWC"], 38 "constant_filter": [True, False], 39 "fully_quantize": [False], 40 "quant_16x8": [False] 41 }, 42 { 43 "input_shape": [[1, 3, 4, 3]], 44 "filter_size": [[1, 1]], 45 "strides": [[1, 1, 2, 1]], # TF needs [1, x, x, 1] 46 "dilations": [[1, 1, 1, 1], [1, 2, 2, 1]], 47 "channel_multiplier": [2], 48 "rate": [[2, 2]], # Only [1, 1] is supported 49 "padding": ["SAME"], 50 "data_format": ["NHWC"], 51 "constant_filter": [True, False], 52 "fully_quantize": [False], 53 "quant_16x8": [False] 54 }, 55 { 56 "input_shape": [[1, 3, 4, 3], [1, 10, 10, 3]], 57 "filter_size": [[1, 1], [1, 2], [3, 3]], 58 "strides": [[1, 1, 1, 1], [1, 3, 3, 1]], 59 "dilations": [[1, 1, 1, 1], [1, 3, 2, 1], [1, 2, 2, 1]], 60 "channel_multiplier": [1, 2], 61 "rate": [[1, 1]], 62 "padding": ["SAME", "VALID"], 63 "data_format": ["NHWC"], 64 "constant_filter": [True], 65 "fully_quantize": [True], 66 "quant_16x8": [False] 67 }, 68 { 69 "input_shape": [[1, 3, 3, 3000]], 70 "filter_size": [[3, 3]], 71 "strides": [[1, 1, 1, 1]], 72 "dilations": [[1, 1, 1, 1]], 73 "channel_multiplier": [1], 74 "rate": [[1, 1]], 75 "padding": ["VALID"], 76 "data_format": ["NHWC"], 77 "constant_filter": [True], 78 "fully_quantize": [True], 79 "quant_16x8": [False] 80 }, 81 { 82 "input_shape": [[1, 3, 4, 3]], 83 "filter_size": [[1, 2]], 84 "strides": [[1, 3, 3, 1]], 85 "dilations": [[1, 3, 2, 1]], 86 "channel_multiplier": [1], 87 "rate": [[1, 1]], 88 "padding": ["SAME", "VALID"], 89 "data_format": ["NHWC"], 90 "constant_filter": [True], 91 "fully_quantize": [True], 92 "quant_16x8": [True] 93 }, 94 ] 95 96 def get_tensor_shapes(parameters): 97 input_shape = parameters["input_shape"] 98 filter_size = parameters["filter_size"] 99 filter_shape = filter_size + [ 100 input_shape[3], parameters["channel_multiplier"] 101 ] 102 return [input_shape, filter_shape] 103 104 def build_graph(parameters): 105 """Build a depthwise conv graph given `parameters`.""" 106 input_shape, filter_shape = get_tensor_shapes(parameters) 107 input_tensor = tf.compat.v1.placeholder( 108 dtype=tf.float32, name="input", shape=input_shape) 109 110 # Get filter input either as a placeholder or constants. Also get a list of 111 # the input tensors that are represented as placeholders. 112 if parameters["constant_filter"]: 113 filter_input = create_tensor_data(np.float32, filter_shape) 114 input_tensors = [input_tensor] 115 else: 116 filter_input = tf.compat.v1.placeholder( 117 dtype=tf.float32, name="filter", shape=filter_shape) 118 input_tensors = [input_tensor, filter_input] 119 120 out = tf.nn.depthwise_conv2d( 121 input_tensor, 122 filter_input, 123 strides=parameters["strides"], 124 rate=parameters["rate"], 125 padding=parameters["padding"], 126 data_format=parameters["data_format"]) 127 return input_tensors, [out] 128 129 def build_inputs(parameters, sess, inputs, outputs): 130 # pylint: disable=g-doc-return-or-yield, g-doc-args 131 """Build list of input values. 132 133 It either contains 1 tensor (input) or 2 tensors (input, filter) based on 134 whether filter is constant or variable input. 135 """ 136 137 input_shape, filter_shape = get_tensor_shapes(parameters) 138 values = [ 139 create_tensor_data(np.float32, input_shape, min_value=-1, max_value=1) 140 ] 141 if not parameters["constant_filter"]: 142 values.append( 143 create_tensor_data( 144 np.float32, filter_shape, min_value=-1, max_value=1)) 145 return values, sess.run(outputs, feed_dict=dict(zip(inputs, values))) 146 147 make_zip_of_tests( 148 options, 149 test_parameters, 150 build_graph, 151 build_inputs, 152 expected_tf_failures=4) 153