• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 transpose_conv."""
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
27# Since compute output_shape is fairly complicated for
28# tf.nn.conv2d_transpose input_sizes argument, so we here first perform a
29# "conv2d" operation to get the output, then we use the output to feed in
30# tf.nn.conv2d_backprop_input.
31# This test will depend on the "conv2d" operation's correctness.
32@register_make_test_function()
33def make_transpose_conv_tests(options):
34  """Make a set of tests to do transpose_conv."""
35
36  # Tensorflow only supports equal strides
37  test_parameters = [
38      {
39          "input_shape": [[1, 3, 4, 1], [1, 10, 10, 3], [3, 20, 20, 1]],
40          "filter_size": [[1, 1], [1, 2], [3, 3]],
41          "has_bias": [False],
42          "strides": [[1, 1, 1, 1], [1, 3, 3, 1]],
43          "padding": ["SAME", "VALID"],
44          "data_format": ["NHWC"],
45          "channel_multiplier": [1, 2],
46          "output_shape": [[]],
47          "fully_quantize": [False],
48          "const_weight_bias": [False]
49      },
50      # TODO(yunluli): Adding simple tests for now to unblock edgetpu debugging.
51      # Need to add more test cases.
52      {
53          "input_shape": [[1, 3, 3, 1]],
54          "filter_size": [[3, 3, 2, 1]],
55          "has_bias": [False],
56          "strides": [[1, 1, 1, 1]],
57          "padding": ["SAME"],
58          "data_format": ["NHWC"],
59          "channel_multiplier": [1],
60          "output_shape": [[1, 3, 3, 2]],
61          "fully_quantize": [True],
62          "const_weight_bias": [True]
63      },
64      {
65          "input_shape": [[1, 3, 3, 1]],
66          "filter_size": [[3, 3, 2, 1]],
67          "has_bias": [False],
68          "strides": [[1, 1, 1, 1]],
69          "padding": ["SAME"],
70          "data_format": ["NHWC"],
71          "channel_multiplier": [1],
72          "output_shape": [[1, 3, 3, 2]],
73          "fully_quantize": [False],
74          "const_weight_bias": [True]
75      },
76      {
77          "input_shape": [[1, 3, 3, 1]],
78          "filter_size": [[3, 3, 2, 1]],
79          "has_bias": [False],
80          "strides": [[1, 2, 2, 1]],
81          "padding": ["SAME"],
82          "data_format": ["NHWC"],
83          "channel_multiplier": [1],
84          "output_shape": [[1, 6, 6, 2]],
85          "fully_quantize": [True],
86          "const_weight_bias": [True]
87      },
88      {
89          "input_shape": [[1, 4, 3, 1]],
90          "filter_size": [[3, 3, 2, 1]],
91          "has_bias": [False],
92          "strides": [[1, 2, 2, 1]],
93          "padding": ["SAME"],
94          "data_format": ["NHWC"],
95          "channel_multiplier": [1],
96          "output_shape": [[1, 8, 6, 2]],
97          "fully_quantize": [True],
98          "const_weight_bias": [True]
99      },
100      {
101          "input_shape": [[1, 3, 3, 1]],
102          "filter_size": [[3, 3, 2, 1]],
103          "has_bias": [True],
104          "strides": [[1, 1, 1, 1]],
105          "padding": ["SAME"],
106          "data_format": ["NHWC"],
107          "channel_multiplier": [1],
108          "output_shape": [[1, 3, 3, 2]],
109          "fully_quantize": [True],
110          "const_weight_bias": [True]
111      },
112  ]
113
114  def get_tensor_shapes(parameters):
115    input_shape = parameters["input_shape"]
116    filter_size = parameters["filter_size"]
117    if not parameters["const_weight_bias"]:
118      filter_shape = filter_size + [
119          input_shape[3], parameters["channel_multiplier"]
120      ]
121      return [input_shape, filter_shape]
122    return [input_shape, filter_size]
123
124  def build_graph(parameters):
125    """Build a transpose_conv graph given `parameters`."""
126    input_shape, filter_shape = get_tensor_shapes(parameters)
127    input_tensor = tf.compat.v1.placeholder(
128        dtype=tf.float32, name="input", shape=input_shape)
129
130    filter_input = tf.compat.v1.placeholder(
131        dtype=tf.float32, name="filter", shape=filter_shape)
132
133    if not parameters["const_weight_bias"]:
134      input_tensors = [input_tensor, filter_input]
135      conv_outputs = tf.nn.conv2d(
136          input_tensor,
137          filter_input,
138          strides=parameters["strides"],
139          padding=parameters["padding"],
140          data_format=parameters["data_format"])
141      out = tf.compat.v1.nn.conv2d_backprop_input(
142          input_shape,
143          filter_input,
144          conv_outputs,
145          strides=parameters["strides"],
146          padding=parameters["padding"],
147          data_format=parameters["data_format"])
148    else:
149      input_tensors = [input_tensor]
150      if parameters["fully_quantize"]:
151        filter_input = create_tensor_data(
152            np.float32, filter_shape, min_value=-1, max_value=1)
153      else:
154        filter_input = create_tensor_data(np.float32, filter_shape)
155      out = tf.nn.conv2d_transpose(
156          input_tensor,
157          filter_input,
158          parameters["output_shape"],
159          strides=parameters["strides"],
160          padding=parameters["padding"],
161          data_format=parameters["data_format"])
162      if parameters["has_bias"]:
163        if parameters["fully_quantize"]:
164          bias_input = create_tensor_data(
165              np.float32, (parameters["output_shape"][-1],),
166              min_value=-1,
167              max_value=1)
168        else:
169          bias_input = create_tensor_data(np.float32,
170                                          (parameters["output_shape"][-1],))
171        out = tf.nn.bias_add(
172            out, bias_input, data_format=parameters["data_format"])
173
174        mul_data = create_tensor_data(np.float32,
175                                      (parameters["output_shape"][-1],))
176        out = tf.math.multiply(out, mul_data)
177
178    return input_tensors, [out]
179
180  def build_inputs(parameters, sess, inputs, outputs):
181    input_shape, filter_shape = get_tensor_shapes(parameters)
182    if not parameters["const_weight_bias"]:
183      values = [
184          create_tensor_data(np.float32, input_shape),
185          create_tensor_data(np.float32, filter_shape)
186      ]
187    else:
188      if parameters["fully_quantize"]:
189        values = [
190            create_tensor_data(
191                np.float32, input_shape, min_value=-1, max_value=1),
192        ]
193      else:
194        values = [create_tensor_data(np.float32, input_shape),]
195
196    return values, sess.run(outputs, feed_dict=dict(zip(inputs, values)))
197
198  make_zip_of_tests(options, test_parameters, build_graph, build_inputs)
199