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