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 shape_ops.""" 16 17 from __future__ import absolute_import 18 from __future__ import division 19 from __future__ import print_function 20 21 import numpy as np 22 23 from tensorflow.contrib.signal.python.kernel_tests import test_util 24 from tensorflow.contrib.signal.python.ops import shape_ops 25 from tensorflow.python.framework import constant_op 26 from tensorflow.python.framework import dtypes 27 from tensorflow.python.framework import ops 28 from tensorflow.python.ops import array_ops 29 from tensorflow.python.ops import math_ops 30 from tensorflow.python.platform import test 31 32 33 class FrameTest(test.TestCase): 34 35 def test_mapping_of_indices_without_padding(self): 36 with self.test_session(use_gpu=True): 37 tensor = constant_op.constant(np.arange(9152), dtypes.int32) 38 tensor = array_ops.expand_dims(tensor, 0) 39 40 result = shape_ops.frame(tensor, 512, 180, pad_end=False).eval() 41 42 expected = np.tile(np.arange(512), (49, 1)) 43 expected += np.tile(np.arange(49) * 180, (512, 1)).T 44 45 expected = np.expand_dims(expected, axis=0) 46 expected = np.array(expected, dtype=np.int32) 47 48 self.assertAllEqual(expected, result) 49 50 def test_mapping_of_indices_with_padding(self): 51 with self.test_session(use_gpu=True): 52 tensor = constant_op.constant(np.arange(10000), dtypes.int32) 53 tensor = array_ops.expand_dims(tensor, 0) 54 55 result = shape_ops.frame(tensor, 512, 192, pad_end=True).eval() 56 57 expected = np.tile(np.arange(512), (53, 1)) 58 expected += np.tile(np.arange(53) * 192, (512, 1)).T 59 60 expected[expected >= 10000] = 0 61 62 expected = np.expand_dims(expected, axis=0) 63 expected = np.array(expected, dtype=np.int32) 64 65 self.assertAllEqual(expected, result) 66 67 def test_invalid_inputs(self): 68 # Rank 0 input signal. 69 with self.assertRaises(ValueError): 70 shape_ops.frame(1, 1, 1) 71 72 # If the rank is unknown, do not raise an exception. 73 shape_ops.frame(array_ops.placeholder(dtypes.float32), 1, 1) 74 75 # Non-scalar frame_length. 76 with self.assertRaises(ValueError): 77 shape_ops.frame([1], [1], 1) 78 79 # Non-scalar frame_step. 80 with self.assertRaises(ValueError): 81 shape_ops.frame([1], 1, [1]) 82 83 # Non-scalar pad_value. 84 with self.assertRaises(ValueError): 85 shape_ops.frame([1], 1, 1, pad_end=True, pad_value=[1]) 86 87 def test_length_zero(self): 88 signal = constant_op.constant([], dtype=dtypes.float32) 89 frame_length = 2 90 frame_step = 1 91 92 with self.test_session(use_gpu=True): 93 result = shape_ops.frame(signal, frame_length, frame_step, 94 pad_end=True, pad_value=99).eval() 95 self.assertEqual((0, 2), result.shape) 96 97 result = shape_ops.frame(signal, frame_length, frame_step, 98 pad_end=False).eval() 99 self.assertEqual((0, 2), result.shape) 100 101 def test_shape_inference(self): 102 signal = array_ops.placeholder(dtypes.int32, shape=[1, 1]) 103 frame_length = 2 104 frame_step = 1 105 # Shape inference is able to detect the rank and inner-most dimension 106 # if frame_length is known at graph definition time. 107 result = shape_ops.frame(signal, frame_length, frame_step, 108 pad_end=True, pad_value=99) 109 self.assertEqual([1, 1, 2], result.shape.as_list()) 110 111 result = shape_ops.frame(signal, frame_length, frame_step, 112 pad_end=False) 113 self.assertEqual([1, 0, 2], result.shape.as_list()) 114 115 # If frame_length is not known, rank and (known) outer and inner dimensions 116 # are inferred. 117 signal = array_ops.placeholder(dtypes.int32, shape=[1, 2, 3, 4]) 118 frame_length = array_ops.placeholder(dtypes.int32, shape=[]) 119 frame_step = 1 120 result = shape_ops.frame(signal, frame_length, frame_step, 121 pad_end=True, pad_value=99, axis=1) 122 self.assertEqual([1, None, None, 3, 4], result.shape.as_list()) 123 124 result = shape_ops.frame(signal, frame_length, frame_step, 125 pad_end=False, axis=1) 126 self.assertEqual([1, None, None, 3, 4], result.shape.as_list()) 127 128 # If frame_length and inner-most dimension is known, rank, inner dimensions, 129 # and known outer dimensions are inferred. 130 signal = array_ops.placeholder(dtypes.int32, 131 shape=[None, 5, None, 20, 5, 3]) 132 frame_length = 4 133 frame_step = 3 134 result = shape_ops.frame(signal, frame_length, frame_step, 135 pad_end=True, pad_value=99, axis=3) 136 self.assertEqual([None, 5, None, 7, 4, 5, 3], result.shape.as_list()) 137 138 result = shape_ops.frame(signal, frame_length, frame_step, 139 pad_end=False, axis=3) 140 self.assertEqual([None, 5, None, 6, 4, 5, 3], result.shape.as_list()) 141 142 # Test that shape inference is consistent with actual returned shapes for 143 # small values of signal_length, frame_length, frame_step, and pad_end in 144 # [True, False]. 145 frame_step = 1 146 for signal_length in range(2): 147 signal = [0] * signal_length 148 for frame_length in range(2): 149 for pad_end in [False, True]: 150 op = shape_ops.frame(signal, frame_length, frame_step, 151 pad_end=pad_end, pad_value=99) 152 with self.test_session(use_gpu=True): 153 result = op.eval() 154 self.assertEqual(op.shape.as_list(), list(result.shape)) 155 156 def test_basic_mono(self): 157 signal = np.arange(6) 158 frame_length = 3 159 frame_step = 2 160 161 with self.test_session(use_gpu=True): 162 for rank in range(5): 163 nd_signal = np.reshape(signal, (1,) * rank + signal.shape) 164 165 # With padding, we pad the last frame with pad_value. 166 result = shape_ops.frame(nd_signal, frame_length, frame_step, 167 pad_end=True, pad_value=99).eval() 168 expected_inner_frames = np.array([[0, 1, 2], [2, 3, 4], [4, 5, 99]]) 169 expected = np.reshape( 170 expected_inner_frames, (1,) * rank + expected_inner_frames.shape) 171 self.assertAllEqual(expected, result) 172 173 # Without padding, we drop the last frame. 174 expected_inner_frames = np.array([[0, 1, 2], [2, 3, 4]]) 175 expected = np.reshape( 176 expected_inner_frames, (1,) * rank + expected_inner_frames.shape) 177 result = shape_ops.frame(nd_signal, frame_length, frame_step, 178 pad_end=False).eval() 179 self.assertAllEqual(expected, result) 180 181 def test_basic_stereo(self): 182 signal = np.vstack([np.arange(6), 183 np.arange(6) + 10]) 184 frame_length = 3 185 frame_step = 2 186 187 with self.test_session(use_gpu=True): 188 for rank in range(5): 189 nd_signal = np.reshape(signal, (1,) * rank + signal.shape) 190 191 # With padding, we pad the last frame with pad_value. 192 result = shape_ops.frame(nd_signal, frame_length, frame_step, 193 pad_end=True, pad_value=99).eval() 194 expected_inner_frames = np.array([ 195 [[0, 1, 2], [2, 3, 4], [4, 5, 99]], 196 [[10, 11, 12], [12, 13, 14], [14, 15, 99]]]) 197 expected = np.reshape( 198 expected_inner_frames, (1,) * rank + expected_inner_frames.shape) 199 self.assertAllEqual(expected, result) 200 201 # Without padding, we drop the last frame. 202 expected_inner_frames = np.array([[[0, 1, 2], [2, 3, 4]], 203 [[10, 11, 12], [12, 13, 14]]]) 204 expected = np.reshape( 205 expected_inner_frames, (1,) * rank + expected_inner_frames.shape) 206 result = shape_ops.frame(nd_signal, frame_length, frame_step, 207 pad_end=False).eval() 208 self.assertAllEqual(expected, result) 209 210 def test_complex_shape(self): 211 signal = np.vstack([np.arange(6), 212 np.arange(6) + 10, 213 np.arange(6) + 20, 214 np.arange(6) + 30, 215 np.arange(6) + 40, 216 np.arange(6) + 50]) 217 signal = np.reshape(signal, (2, 1, 3, 1, 6)) 218 frame_length = 3 219 frame_step = 2 220 221 with self.test_session(use_gpu=True): 222 # With padding, we pad the last frame with pad_value. 223 result = shape_ops.frame(signal, frame_length, frame_step, 224 pad_end=True, pad_value=99).eval() 225 # Resulting shape is (2, 1, 3, 1, 3, 3). 226 expected = [[[[[[0, 1, 2], [2, 3, 4], [4, 5, 99]]], 227 [[[10, 11, 12], [12, 13, 14], [14, 15, 99]]], 228 [[[20, 21, 22], [22, 23, 24], [24, 25, 99]]]]], 229 [[[[[30, 31, 32], [32, 33, 34], [34, 35, 99]]], 230 [[[40, 41, 42], [42, 43, 44], [44, 45, 99]]], 231 [[[50, 51, 52], [52, 53, 54], [54, 55, 99]]]]]] 232 self.assertAllEqual(expected, result) 233 234 result = shape_ops.frame(signal, frame_length, frame_step, 235 pad_end=False).eval() 236 # Resulting shape is (2, 1, 3, 1, 3, 2). 237 expected = [[[[[[0, 1, 2], [2, 3, 4]]], 238 [[[10, 11, 12], [12, 13, 14]]], 239 [[[20, 21, 22], [22, 23, 24]]]]], 240 [[[[[30, 31, 32], [32, 33, 34]]], 241 [[[40, 41, 42], [42, 43, 44]]], 242 [[[50, 51, 52], [52, 53, 54]]]]]] 243 self.assertAllEqual(expected, result) 244 245 def test_axis(self): 246 signal = np.reshape(np.arange(16), (2, 4, 2)) 247 with self.test_session(use_gpu=True): 248 result = shape_ops.frame(signal, frame_length=2, frame_step=2, 249 pad_end=True, axis=1) 250 expected = np.reshape(np.arange(16), (2, 2, 2, 2)) 251 self.assertAllEqual(expected, result.eval()) 252 253 result = shape_ops.frame(signal, frame_length=2, frame_step=1, 254 pad_end=True, axis=1) 255 expected = [[[[0, 1], [2, 3]], 256 [[2, 3], [4, 5]], 257 [[4, 5], [6, 7]], 258 [[6, 7], [0, 0]]], 259 [[[8, 9], [10, 11]], 260 [[10, 11], [12, 13]], 261 [[12, 13], [14, 15]], 262 [[14, 15], [0, 0]]]] 263 self.assertAllEqual(expected, result.eval()) 264 265 result = shape_ops.frame(signal, frame_length=3, frame_step=1, 266 pad_end=True, axis=1) 267 expected = [[[[0, 1], [2, 3], [4, 5]], 268 [[2, 3], [4, 5], [6, 7]], 269 [[4, 5], [6, 7], [0, 0]], 270 [[6, 7], [0, 0], [0, 0]]], 271 [[[8, 9], [10, 11], [12, 13]], 272 [[10, 11], [12, 13], [14, 15]], 273 [[12, 13], [14, 15], [0, 0]], 274 [[14, 15], [0, 0], [0, 0]]]] 275 self.assertAllEqual(expected, result.eval()) 276 277 def test_window_larger_than_signal(self): 278 signal = constant_op.constant([[1, 2], [11, 12]], dtype=dtypes.float32) 279 frame_length = 4 280 frame_step = 1 281 282 with self.test_session(use_gpu=True): 283 result = shape_ops.frame(signal, frame_length, frame_step, 284 pad_end=True, pad_value=99).eval() 285 self.assertAllClose([[[1, 2, 99, 99], [2, 99, 99, 99]], 286 [[11, 12, 99, 99], [12, 99, 99, 99]]], result) 287 288 result = shape_ops.frame(signal, frame_length, frame_step, 289 pad_end=False).eval() 290 self.assertEqual((2, 0, 4), result.shape) 291 292 frame_step = 2 293 result = shape_ops.frame(signal, frame_length, frame_step, 294 pad_end=True, pad_value=99).eval() 295 self.assertAllClose([[[1, 2, 99, 99]], [[11, 12, 99, 99]]], result) 296 297 result = shape_ops.frame(signal, frame_length, frame_step, 298 pad_end=False).eval() 299 self.assertEqual((2, 0, 4), result.shape) 300 301 def test_preserves_type(self): 302 signal = math_ops.range(10, dtype=dtypes.float64) 303 frame_length = 2 304 frame_step = 3 305 306 with self.test_session(use_gpu=True): 307 result = shape_ops.frame(signal, frame_length, frame_step) 308 self.assertEqual(result.dtype, signal.dtype) 309 310 def test_dynamic_tensor(self): 311 # Show that frame works even when the dimensions of its input are 312 # not known at graph creation time. 313 input_signal = np.vstack([np.arange(4), np.arange(4) + 10, 314 np.arange(4) + 20]) 315 frame_length = 2 316 frame_step = 2 317 318 with self.test_session(use_gpu=True) as sess: 319 signal_placeholder = array_ops.placeholder(shape=(None, None), 320 dtype=dtypes.float32) 321 result = sess.run(shape_ops.frame( 322 signal_placeholder, frame_length, frame_step), 323 feed_dict={signal_placeholder: input_signal}) 324 self.assertAllEqual([[[0, 1], [2, 3]], 325 [[10, 11], [12, 13]], 326 [[20, 21], [22, 23]]], result) 327 328 def test_gradient_numerical(self): 329 with self.test_session(use_gpu=True): 330 signal_shape = (2, 128) 331 signal = array_ops.ones(signal_shape) 332 frame_length = 33 333 frame_step = 9 334 frames = shape_ops.frame(signal, frame_length, frame_step) 335 error = test.compute_gradient_error( 336 signal, signal_shape, frames, frames.shape.as_list()) 337 self.assertLess(error, 2e-5) 338 339 def test_constant_folding(self): 340 """frame should be constant foldable for constant inputs.""" 341 for pad_end in [False, True]: 342 g = ops.Graph() 343 with g.as_default(): 344 frame_length, frame_step = 32, 16 345 signal_shape = (2, 128) 346 signal = array_ops.ones(signal_shape) 347 frames = shape_ops.frame(signal, frame_length, frame_step, 348 pad_end=pad_end) 349 rewritten_graph = test_util.grappler_optimize(g, [frames]) 350 self.assertEqual(1, len(rewritten_graph.node)) 351 352 353 if __name__ == "__main__": 354 test.main() 355