• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2015 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"""Tests for convolution related functionality in tensorflow.ops.nn."""
16
17import numpy as np
18
19from tensorflow.python.framework import constant_op
20from tensorflow.python.framework import dtypes
21from tensorflow.python.framework import test_util
22from tensorflow.python.ops import gradient_checker
23from tensorflow.python.ops import nn_ops
24import tensorflow.python.ops.nn_grad  # pylint: disable=unused-import
25from tensorflow.python.platform import test
26
27
28class Conv1DTransposeTest(test.TestCase):
29
30  def testConv1DTransposeSingleStride(self):
31    with self.cached_session():
32      strides = [1, 1, 1]
33
34      # Input, output: [batch, width, depth]
35      x_shape = [2, 6, 3]
36      y_shape = [2, 6, 2]
37
38      # Filter: [kernel_width, output_depth, input_depth]
39      f_shape = [3, 2, 3]
40
41      x = constant_op.constant(
42          1.0, shape=x_shape, name="x", dtype=dtypes.float32)
43      f = constant_op.constant(
44          1.0, shape=f_shape, name="filter", dtype=dtypes.float32)
45      output = nn_ops.conv1d_transpose(
46          x, f, y_shape, strides=strides, padding="SAME")
47      value = self.evaluate(output)
48
49      for n in range(y_shape[0]):
50        for w in range(y_shape[1]):
51          for c in range(y_shape[2]):
52            target = 2 * 3.0
53            w_in = w > 0 and w < y_shape[1] - 1
54            if w_in:
55              target += 3.0
56            self.assertAllClose(target, value[n, w, c])
57
58  def testConv1DTransposeSame(self):
59    with self.cached_session():
60      strides = [1, 2, 1]
61
62      # Input, output: [batch, width, depth]
63      x_shape = [2, 4, 3]
64      y_shape = [2, 8, 2]
65
66      # Filter: [kernel_width, output_depth, input_depth]
67      f_shape = [3, 2, 3]
68
69      x = constant_op.constant(
70          1.0, shape=x_shape, name="x", dtype=dtypes.float32)
71      f = constant_op.constant(
72          1.0, shape=f_shape, name="filter", dtype=dtypes.float32)
73      output = nn_ops.conv1d_transpose(
74          x, f, y_shape, strides=strides, padding="SAME")
75      value = self.evaluate(output)
76
77      for n in range(x_shape[0]):
78        for k in range(f_shape[1]):
79          for w in range(y_shape[1]):
80            target = 3.0
81            # We add a case for locations divisible by the stride.
82            w_in = w % strides[1] == 0 and w > 0 and w < y_shape[1] - 1
83            if w_in:
84              target += 3.0
85            self.assertAllClose(target, value[n, w, k])
86
87  def testConv1DTransposeValid(self):
88    with self.cached_session():
89      strides = [1, 2, 1]
90
91      # Input, output: [batch, width, depth]
92      x_shape = [2, 4, 3]
93      y_shape = [2, 9, 2]
94
95      # Filter: [kernel_width, output_depth, input_depth]
96      f_shape = [3, 2, 3]
97
98      x = constant_op.constant(
99          1.0, shape=x_shape, name="x", dtype=dtypes.float32)
100      f = constant_op.constant(
101          1.0, shape=f_shape, name="filter", dtype=dtypes.float32)
102      output = nn_ops.conv1d_transpose(
103          x, f, y_shape, strides=strides, padding="VALID")
104      value = self.evaluate(output)
105
106      cache_values = np.zeros(y_shape, dtype=np.float32)
107
108      # The amount of padding added
109      pad = 1
110
111      for n in range(x_shape[0]):
112        for k in range(f_shape[1]):
113          for w in range(pad, y_shape[1] - pad):
114            target = 3.0
115            # We add a case for locations divisible by the stride.
116            w_in = w % strides[1] == 0 and w > pad and w < y_shape[1] - 1 - pad
117            if w_in:
118              target += 3.0
119            cache_values[n, w, k] = target
120
121          # copy values in the border
122          cache_values[n, 0, k] = cache_values[n, 1, k]
123          cache_values[n, -1, k] = cache_values[n, -2, k]
124          cache_values[n, :, k] = cache_values[n, :, k]
125
126    self.assertAllClose(cache_values, value)
127
128  @test_util.run_deprecated_v1
129  def testGradient(self):
130    x_shape = [2, 4, 3]
131    f_shape = [3, 2, 3]
132    y_shape = [2, 8, 2]
133    strides = [1, 2, 1]
134    np.random.seed(1)  # Make it reproducible.
135    x_val = np.random.random_sample(x_shape).astype(np.float64)
136    f_val = np.random.random_sample(f_shape).astype(np.float64)
137    with self.cached_session():
138      x = constant_op.constant(x_val, name="x", dtype=dtypes.float32)
139      f = constant_op.constant(f_val, name="f", dtype=dtypes.float32)
140      output = nn_ops.conv1d_transpose(
141          x, f, y_shape, strides=strides, padding="SAME")
142      err = gradient_checker.compute_gradient_error([x, f], [x_shape, f_shape],
143                                                    output, y_shape)
144    print("conv1d_transpose gradient err = %g " % err)
145    err_tolerance = 0.0005
146    self.assertLess(err, err_tolerance)
147
148  def testConv1DTransposeSingleStrideNCW(self):
149    # `NCW` data format is only supported for CUDA device.
150    if test.is_gpu_available(cuda_only=True):
151      with self.session():
152        strides = [1, 1, 1]
153
154        # Input, output: [batch, depth, width]
155        x_shape = [2, 3, 4]
156        y_shape = [2, 2, 4]
157
158        # Filter: [kernel_width, output_depth, input_depth]
159        f_shape = [3, 2, 3]
160
161        x = constant_op.constant(
162            1.0, shape=x_shape, name="x", dtype=dtypes.float32)
163        f = constant_op.constant(
164            1.0, shape=f_shape, name="filter", dtype=dtypes.float32)
165
166        output = nn_ops.conv1d_transpose(
167            x, f, y_shape, strides=strides, padding="SAME", data_format="NCW")
168
169        value = self.evaluate(output)
170        for n in range(x_shape[0]):
171          for k in range(f_shape[1]):
172            for w in range(y_shape[2]):
173              target = 2 * 3.0
174              w_in = w > 0 and w < y_shape[2] - 1
175              if w_in:
176                target += 3.0
177              self.assertAllClose(target, value[n, k, w])
178
179  def testConv1DTransposeSameNCW(self):
180    # `NCW` data format is only supported for CUDA device.
181    if test.is_gpu_available(cuda_only=True):
182      with self.session():
183        strides = [1, 1, 2]
184
185        # Input, output: [batch, depth, width]
186        x_shape = [2, 3, 4]
187        y_shape = [2, 2, 8]
188
189        # Filter: [kernel_width, output_depth, input_depth]
190        f_shape = [3, 2, 3]
191
192        x = constant_op.constant(
193            1.0, shape=x_shape, name="x", dtype=dtypes.float32)
194        f = constant_op.constant(
195            1.0, shape=f_shape, name="filter", dtype=dtypes.float32)
196
197        output = nn_ops.conv1d_transpose(
198            x, f, y_shape, strides=strides, padding="SAME", data_format="NCW")
199
200        value = self.evaluate(output)
201        for n in range(x_shape[0]):
202          for k in range(f_shape[1]):
203            for w in range(y_shape[2]):
204              target = 3.0
205              # We add a case for locations divisible by the stride.
206              w_in = w % strides[2] == 0 and w > 0 and w < y_shape[2] - 1
207              if w_in:
208                target += 3.0
209              self.assertAllClose(target, value[n, k, w])
210
211  def testConv1DTransposeValidNCW(self):
212    # `NCW` data format is only supported for CUDA device.
213    if test.is_gpu_available(cuda_only=True):
214      with self.session():
215        strides = [1, 1, 2]
216
217        # Input, output: [batch, depth, width]
218        x_shape = [2, 3, 4]
219        y_shape = [2, 2, 9]
220
221        # Filter: [kernel_width, output_depth, input_depth]
222        f_shape = [3, 2, 3]
223
224        x = constant_op.constant(
225            1.0, shape=x_shape, name="x", dtype=dtypes.float32)
226        f = constant_op.constant(
227            1.0, shape=f_shape, name="filter", dtype=dtypes.float32)
228        output = nn_ops.conv1d_transpose(
229            x, f, y_shape, strides=strides, padding="VALID", data_format="NCW")
230
231        value = self.evaluate(output)
232        cache_values = np.zeros(y_shape, dtype=np.float32)
233        # The amount of padding added
234        pad = 1
235        for n in range(x_shape[0]):
236          for k in range(f_shape[1]):
237            for w in range(pad, y_shape[2] - pad):
238              target = 3.0
239              # We add a case for locations divisible by the stride.
240              w_in = w % strides[2] == 0 and w > pad and \
241                     w < y_shape[2] - 1 - pad
242              if w_in:
243                target += 3.0
244              cache_values[n, k, w] = target
245
246            # copy values in the border
247            cache_values[n, k, 0] = cache_values[n, k, 1]
248            cache_values[n, k, -1] = cache_values[n, k, -2]
249            cache_values[n, k, :] = cache_values[n, k, :]
250
251        self.assertAllClose(cache_values, value)
252
253
254if __name__ == "__main__":
255  test.main()
256