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