1# Copyright 2016 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 convolutional layers.""" 16 17from absl.testing import parameterized 18import numpy as np 19 20from tensorflow.python import keras 21from tensorflow.python.eager import context 22from tensorflow.python.eager import def_function 23from tensorflow.python.framework import tensor_spec 24from tensorflow.python.framework import test_util 25from tensorflow.python.keras import keras_parameterized 26from tensorflow.python.keras import testing_utils 27from tensorflow.python.ops import array_ops 28from tensorflow.python.ops import nn 29from tensorflow.python.ops import random_ops 30from tensorflow.python.platform import test 31 32 33@keras_parameterized.run_all_keras_modes 34class Conv1DTest(keras_parameterized.TestCase): 35 36 def _run_test(self, kwargs, expected_output_shape): 37 num_samples = 2 38 stack_size = 3 39 length = 7 40 41 with self.cached_session(): 42 testing_utils.layer_test( 43 keras.layers.Conv1D, 44 kwargs=kwargs, 45 input_shape=(num_samples, length, stack_size), 46 expected_output_shape=expected_output_shape) 47 48 def _run_test_extra_batch_dim(self, kwargs, expected_output_shape): 49 batch_shape = (2, 11) 50 stack_size = 3 51 length = 7 52 53 with self.cached_session(): 54 if expected_output_shape is not None: 55 expected_output_shape = (None,) + expected_output_shape 56 57 testing_utils.layer_test( 58 keras.layers.Conv1D, 59 kwargs=kwargs, 60 input_shape=batch_shape + (length, stack_size), 61 expected_output_shape=expected_output_shape) 62 63 @parameterized.named_parameters( 64 ('padding_valid', { 65 'padding': 'valid' 66 }, (None, 5, 2)), 67 ('padding_same', { 68 'padding': 'same' 69 }, (None, 7, 2)), 70 ('padding_same_dilation_2', { 71 'padding': 'same', 72 'dilation_rate': 2 73 }, (None, 7, 2)), 74 ('padding_same_dilation_3', { 75 'padding': 'same', 76 'dilation_rate': 3 77 }, (None, 7, 2)), 78 ('padding_causal', { 79 'padding': 'causal' 80 }, (None, 7, 2)), 81 ('strides', { 82 'strides': 2 83 }, (None, 3, 2)), 84 ('dilation_rate', { 85 'dilation_rate': 2 86 }, (None, 3, 2)), 87 # Only runs on GPU with CUDA, groups are not supported on CPU. 88 # https://github.com/tensorflow/tensorflow/issues/29005 89 ('group', { 90 'groups': 3, 91 'filters': 6 92 }, (None, 5, 6), True), 93 ) 94 def test_conv1d(self, kwargs, expected_output_shape, requires_gpu=False): 95 kwargs['filters'] = kwargs.get('filters', 2) 96 kwargs['kernel_size'] = 3 97 if not requires_gpu or test.is_gpu_available(cuda_only=True): 98 self._run_test(kwargs, expected_output_shape) 99 self._run_test_extra_batch_dim(kwargs, expected_output_shape) 100 101 def test_conv1d_regularizers(self): 102 kwargs = { 103 'filters': 3, 104 'kernel_size': 3, 105 'padding': 'valid', 106 'kernel_regularizer': 'l2', 107 'bias_regularizer': 'l2', 108 'activity_regularizer': 'l2', 109 'strides': 1 110 } 111 with self.cached_session(): 112 layer = keras.layers.Conv1D(**kwargs) 113 layer.build((None, 5, 2)) 114 self.assertEqual(len(layer.losses), 2) 115 layer(keras.backend.variable(np.ones((1, 5, 2)))) 116 self.assertEqual(len(layer.losses), 3) 117 118 def test_conv1d_constraints(self): 119 k_constraint = lambda x: x 120 b_constraint = lambda x: x 121 122 kwargs = { 123 'filters': 3, 124 'kernel_size': 3, 125 'padding': 'valid', 126 'kernel_constraint': k_constraint, 127 'bias_constraint': b_constraint, 128 'strides': 1 129 } 130 with self.cached_session(): 131 layer = keras.layers.Conv1D(**kwargs) 132 layer.build((None, 5, 2)) 133 self.assertEqual(layer.kernel.constraint, k_constraint) 134 self.assertEqual(layer.bias.constraint, b_constraint) 135 136 def test_conv1d_recreate_conv(self): 137 with self.cached_session(): 138 layer = keras.layers.Conv1D(filters=1, 139 kernel_size=3, 140 strides=1, 141 dilation_rate=2, 142 padding='causal') 143 inpt1 = np.random.normal(size=[1, 2, 1]) 144 inpt2 = np.random.normal(size=[1, 1, 1]) 145 outp1_shape = layer(inpt1).shape 146 _ = layer(inpt2).shape 147 self.assertEqual(outp1_shape, layer(inpt1).shape) 148 149 def test_conv1d_recreate_conv_unknown_dims(self): 150 with self.cached_session(): 151 layer = keras.layers.Conv1D(filters=1, 152 kernel_size=3, 153 strides=1, 154 dilation_rate=2, 155 padding='causal') 156 157 inpt1 = np.random.normal(size=[1, 9, 1]).astype(np.float32) 158 inpt2 = np.random.normal(size=[1, 2, 1]).astype(np.float32) 159 outp1_shape = layer(inpt1).shape 160 161 @def_function.function(input_signature=[ 162 tensor_spec.TensorSpec([1, None, 1])]) 163 def fn(inpt): 164 return layer(inpt) 165 166 fn(inpt2) 167 self.assertEqual(outp1_shape, layer(inpt1).shape) 168 169 170@keras_parameterized.run_all_keras_modes 171class Conv2DTest(keras_parameterized.TestCase): 172 173 def _run_test(self, kwargs, expected_output_shape, spatial_shape=(7, 6)): 174 num_samples = 2 175 stack_size = 3 176 num_row, num_col = spatial_shape 177 input_data = None 178 # Generate valid input data. 179 if None in spatial_shape: 180 input_data_shape = (num_samples, num_row or 7, num_col or 6, stack_size) 181 input_data = 10 * np.random.random(input_data_shape).astype(np.float32) 182 183 with self.cached_session(): 184 testing_utils.layer_test( 185 keras.layers.Conv2D, 186 kwargs=kwargs, 187 input_shape=(num_samples, num_row, num_col, stack_size), 188 input_data=input_data, 189 expected_output_shape=expected_output_shape) 190 191 def _run_test_extra_batch_dim(self, 192 kwargs, 193 expected_output_shape, 194 spatial_shape=(7, 6)): 195 batch_shape = (2, 11) 196 stack_size = 3 197 num_row, num_col = spatial_shape 198 input_data = None 199 # Generate valid input data. 200 if None in spatial_shape: 201 input_data_shape = batch_shape + (num_row or 7, num_col or 6, stack_size) 202 input_data = 10 * np.random.random(input_data_shape).astype(np.float32) 203 204 with self.cached_session(): 205 if expected_output_shape is not None: 206 expected_output_shape = (None,) + expected_output_shape 207 testing_utils.layer_test( 208 keras.layers.Conv2D, 209 kwargs=kwargs, 210 input_shape=batch_shape + (num_row, num_col, stack_size), 211 input_data=input_data, 212 expected_output_shape=expected_output_shape) 213 214 @parameterized.named_parameters( 215 ('padding_valid', { 216 'padding': 'valid' 217 }, (None, 5, 4, 2)), 218 ('padding_same', { 219 'padding': 'same' 220 }, (None, 7, 6, 2)), 221 ('padding_same_dilation_2', { 222 'padding': 'same', 223 'dilation_rate': 2 224 }, (None, 7, 6, 2)), 225 ('strides', { 226 'strides': (2, 2) 227 }, (None, 3, 2, 2)), 228 ('dilation_rate', { 229 'dilation_rate': (2, 2) 230 }, (None, 3, 2, 2)), 231 # Only runs on GPU with CUDA, channels_first is not supported on CPU. 232 # TODO(b/62340061): Support channels_first on CPU. 233 ('data_format', { 234 'data_format': 'channels_first' 235 }, None, True), 236 # Only runs on GPU with CUDA, groups are not supported on CPU. 237 # https://github.com/tensorflow/tensorflow/issues/29005 238 ('group', { 239 'groups': 3, 240 'filters': 6 241 }, (None, 5, 4, 6), True), 242 ('dilation_2_unknown_width', { 243 'dilation_rate': (2, 2) 244 }, (None, None, 2, 2), False, (None, 6)), 245 ('dilation_2_unknown_height', { 246 'dilation_rate': (2, 2) 247 }, (None, 3, None, 2), False, (7, None)), 248 ) 249 def test_conv2d(self, 250 kwargs, 251 expected_output_shape=None, 252 requires_gpu=False, 253 spatial_shape=(7, 6)): 254 kwargs['filters'] = kwargs.get('filters', 2) 255 kwargs['kernel_size'] = (3, 3) 256 if not requires_gpu or test.is_gpu_available(cuda_only=True): 257 self._run_test(kwargs, expected_output_shape, spatial_shape) 258 self._run_test_extra_batch_dim(kwargs, expected_output_shape, 259 spatial_shape) 260 261 def test_conv2d_regularizers(self): 262 kwargs = { 263 'filters': 3, 264 'kernel_size': 3, 265 'padding': 'valid', 266 'kernel_regularizer': 'l2', 267 'bias_regularizer': 'l2', 268 'activity_regularizer': 'l2', 269 'strides': 1 270 } 271 with self.cached_session(): 272 layer = keras.layers.Conv2D(**kwargs) 273 layer.build((None, 5, 5, 2)) 274 self.assertEqual(len(layer.losses), 2) 275 layer(keras.backend.variable(np.ones((1, 5, 5, 2)))) 276 self.assertEqual(len(layer.losses), 3) 277 278 def test_conv2d_constraints(self): 279 k_constraint = lambda x: x 280 b_constraint = lambda x: x 281 282 kwargs = { 283 'filters': 3, 284 'kernel_size': 3, 285 'padding': 'valid', 286 'kernel_constraint': k_constraint, 287 'bias_constraint': b_constraint, 288 'strides': 1 289 } 290 with self.cached_session(): 291 layer = keras.layers.Conv2D(**kwargs) 292 layer.build((None, 5, 5, 2)) 293 self.assertEqual(layer.kernel.constraint, k_constraint) 294 self.assertEqual(layer.bias.constraint, b_constraint) 295 296 def test_conv2d_zero_kernel_size(self): 297 kwargs = {'filters': 2, 'kernel_size': 0} 298 with self.assertRaises(ValueError): 299 keras.layers.Conv2D(**kwargs) 300 301 302@keras_parameterized.run_all_keras_modes 303class Conv3DTest(keras_parameterized.TestCase): 304 305 def _run_test(self, kwargs, expected_output_shape, validate_training=True): 306 num_samples = 2 307 stack_size = 3 308 num_row = 7 309 num_col = 6 310 depth = 5 311 312 with self.cached_session(): 313 testing_utils.layer_test( 314 keras.layers.Conv3D, 315 kwargs=kwargs, 316 input_shape=(num_samples, depth, num_row, num_col, stack_size), 317 expected_output_shape=expected_output_shape, 318 validate_training=validate_training) 319 320 def _run_test_extra_batch_dim(self, 321 kwargs, 322 expected_output_shape, 323 validate_training=True): 324 batch_shape = (2, 11) 325 stack_size = 3 326 num_row = 7 327 num_col = 6 328 depth = 5 329 330 with self.cached_session(): 331 if expected_output_shape is not None: 332 expected_output_shape = (None,) + expected_output_shape 333 334 testing_utils.layer_test( 335 keras.layers.Conv3D, 336 kwargs=kwargs, 337 input_shape=batch_shape + (depth, num_row, num_col, stack_size), 338 expected_output_shape=expected_output_shape, 339 validate_training=validate_training) 340 341 @parameterized.named_parameters( 342 ('padding_valid', { 343 'padding': 'valid' 344 }, (None, 3, 5, 4, 2)), 345 ('padding_same', { 346 'padding': 'same' 347 }, (None, 5, 7, 6, 2)), 348 ('strides', { 349 'strides': (2, 2, 2) 350 }, (None, 2, 3, 2, 2)), 351 ('dilation_rate', { 352 'dilation_rate': (2, 2, 2) 353 }, (None, 1, 3, 2, 2)), 354 # Only runs on GPU with CUDA, channels_first is not supported on CPU. 355 # TODO(b/62340061): Support channels_first on CPU. 356 ('data_format', { 357 'data_format': 'channels_first' 358 }, None, True), 359 # Only runs on GPU with CUDA, groups are not supported on CPU. 360 # https://github.com/tensorflow/tensorflow/issues/29005 361 ('group', { 362 'groups': 3, 363 'filters': 6 364 }, (None, 3, 5, 4, 6), True), 365 ) 366 def test_conv3d(self, kwargs, expected_output_shape=None, requires_gpu=False): 367 kwargs['filters'] = kwargs.get('filters', 2) 368 kwargs['kernel_size'] = (3, 3, 3) 369 # train_on_batch currently fails with XLA enabled on GPUs 370 test_training = 'groups' not in kwargs or not test_util.is_xla_enabled() 371 if not requires_gpu or test.is_gpu_available(cuda_only=True): 372 self._run_test(kwargs, expected_output_shape, test_training) 373 self._run_test_extra_batch_dim(kwargs, expected_output_shape, 374 test_training) 375 376 def test_conv3d_regularizers(self): 377 kwargs = { 378 'filters': 3, 379 'kernel_size': 3, 380 'padding': 'valid', 381 'kernel_regularizer': 'l2', 382 'bias_regularizer': 'l2', 383 'activity_regularizer': 'l2', 384 'strides': 1 385 } 386 with self.cached_session(): 387 layer = keras.layers.Conv3D(**kwargs) 388 layer.build((None, 5, 5, 5, 2)) 389 self.assertEqual(len(layer.losses), 2) 390 self.assertEqual(len(layer.losses), 2) 391 layer(keras.backend.variable(np.ones((1, 5, 5, 5, 2)))) 392 self.assertEqual(len(layer.losses), 3) 393 394 def test_conv3d_constraints(self): 395 k_constraint = lambda x: x 396 b_constraint = lambda x: x 397 398 kwargs = { 399 'filters': 3, 400 'kernel_size': 3, 401 'padding': 'valid', 402 'kernel_constraint': k_constraint, 403 'bias_constraint': b_constraint, 404 'strides': 1 405 } 406 with self.cached_session(): 407 layer = keras.layers.Conv3D(**kwargs) 408 layer.build((None, 5, 5, 5, 2)) 409 self.assertEqual(layer.kernel.constraint, k_constraint) 410 self.assertEqual(layer.bias.constraint, b_constraint) 411 412 def test_conv3d_dynamic_shape(self): 413 input_data = np.random.random((1, 3, 3, 3, 3)).astype(np.float32) 414 with self.cached_session(): 415 # Won't raise error here. 416 testing_utils.layer_test( 417 keras.layers.Conv3D, 418 kwargs={ 419 'data_format': 'channels_last', 420 'filters': 3, 421 'kernel_size': 3 422 }, 423 input_shape=(None, None, None, None, 3), 424 input_data=input_data) 425 if test.is_gpu_available(cuda_only=True): 426 testing_utils.layer_test( 427 keras.layers.Conv3D, 428 kwargs={ 429 'data_format': 'channels_first', 430 'filters': 3, 431 'kernel_size': 3 432 }, 433 input_shape=(None, 3, None, None, None), 434 input_data=input_data) 435 436 437@keras_parameterized.run_all_keras_modes(always_skip_v1=True) 438class GroupedConvTest(keras_parameterized.TestCase): 439 440 @parameterized.named_parameters( 441 ('Conv1D', keras.layers.Conv1D), 442 ('Conv2D', keras.layers.Conv2D), 443 ('Conv3D', keras.layers.Conv3D), 444 ) 445 def test_group_conv_incorrect_use(self, layer): 446 with self.assertRaisesRegex(ValueError, 'The number of filters'): 447 layer(16, 3, groups=3) 448 with self.assertRaisesRegex(ValueError, 'The number of input channels'): 449 layer(16, 3, groups=4).build((32, 12, 12, 3)) 450 451 @parameterized.named_parameters( 452 ('Conv1D', keras.layers.Conv1D, (32, 12, 32)), 453 ('Conv2D', keras.layers.Conv2D, (32, 12, 12, 32)), 454 ('Conv3D', keras.layers.Conv3D, (32, 12, 12, 12, 32)), 455 ) 456 def test_group_conv(self, layer_cls, input_shape): 457 if test.is_gpu_available(cuda_only=True): 458 with testing_utils.use_gpu(): 459 inputs = random_ops.random_uniform(shape=input_shape) 460 461 layer = layer_cls(16, 3, groups=4, use_bias=False) 462 layer.build(input_shape) 463 464 input_slices = array_ops.split(inputs, 4, axis=-1) 465 weight_slices = array_ops.split(layer.kernel, 4, axis=-1) 466 expected_outputs = array_ops.concat([ 467 nn.convolution_v2(inputs, weights) 468 for inputs, weights in zip(input_slices, weight_slices) 469 ], 470 axis=-1) 471 self.assertAllClose( 472 layer(inputs), expected_outputs, rtol=3e-5, atol=3e-5) 473 474 def test_group_conv_depthwise(self): 475 if test.is_gpu_available(cuda_only=True): 476 with testing_utils.use_gpu(): 477 inputs = random_ops.random_uniform(shape=(3, 27, 27, 32)) 478 479 layer = keras.layers.Conv2D(32, 3, groups=32, use_bias=False) 480 layer.build((3, 27, 27, 32)) 481 482 weights_dw = array_ops.reshape(layer.kernel, [3, 3, 32, 1]) 483 expected_outputs = nn.depthwise_conv2d( 484 inputs, weights_dw, strides=[1, 1, 1, 1], padding='VALID') 485 486 self.assertAllClose(layer(inputs), expected_outputs, rtol=1e-5) 487 488 489@keras_parameterized.run_all_keras_modes 490class Conv1DTransposeTest(keras_parameterized.TestCase): 491 492 def _run_test(self, kwargs, expected_output_shape): 493 num_samples = 2 494 stack_size = 3 495 num_col = 6 496 497 with testing_utils.use_gpu(): 498 testing_utils.layer_test( 499 keras.layers.Conv1DTranspose, 500 kwargs=kwargs, 501 input_shape=(num_samples, num_col, stack_size), 502 expected_output_shape=expected_output_shape) 503 504 @parameterized.named_parameters( 505 ('padding_valid', {'padding': 'valid'}, (None, 8, 2)), 506 ('padding_same', {'padding': 'same'}, (None, 6, 2)), 507 ('strides', {'strides': 2}, (None, 13, 2)), 508 # Only runs on GPU with CUDA, dilation_rate>1 is not supported on CPU. 509 ('dilation_rate', {'dilation_rate': 2}, (None, 10, 2)), 510 # Only runs on GPU with CUDA, channels_first is not supported on CPU. 511 # TODO(b/62340061): Support channels_first on CPU. 512 ('data_format', {'data_format': 'channels_first'}), 513 ) 514 def test_conv1d_transpose(self, kwargs, expected_output_shape=None): 515 kwargs['filters'] = 2 516 kwargs['kernel_size'] = 3 517 if (('data_format' not in kwargs and 'dilation_rate' not in kwargs) or 518 test.is_gpu_available(cuda_only=True)): 519 self._run_test(kwargs, expected_output_shape) 520 521 522@keras_parameterized.run_all_keras_modes 523class Conv3DTransposeTest(keras_parameterized.TestCase): 524 525 def _run_test(self, kwargs, expected_output_shape): 526 num_samples = 2 527 stack_size = 3 528 num_row = 7 529 num_col = 6 530 depth = 5 531 532 with testing_utils.use_gpu(): 533 testing_utils.layer_test( 534 keras.layers.Conv3DTranspose, 535 kwargs=kwargs, 536 input_shape=(num_samples, depth, num_row, num_col, stack_size), 537 expected_output_shape=expected_output_shape) 538 539 @parameterized.named_parameters( 540 ('padding_valid', {'padding': 'valid'}, (None, 7, 9, 8, 2)), 541 ('padding_same', {'padding': 'same'}, (None, 5, 7, 6, 2)), 542 ('strides', {'strides': (2, 2, 2)}, (None, 11, 15, 13, 2)), 543 ('dilation_rate', {'dilation_rate': (2, 2, 2)}, (None, 7, 9, 8, 2)), 544 # Only runs on GPU with CUDA, channels_first is not supported on CPU. 545 # TODO(b/62340061): Support channels_first on CPU. 546 ('data_format', {'data_format': 'channels_first'}), 547 ) 548 def test_conv3d_transpose(self, kwargs, expected_output_shape=None): 549 kwargs['filters'] = 2 550 kwargs['kernel_size'] = (3, 3, 3) 551 if 'data_format' not in kwargs or test.is_gpu_available(cuda_only=True): 552 self._run_test(kwargs, expected_output_shape) 553 554 555@keras_parameterized.run_all_keras_modes 556class ConvSequentialTest(keras_parameterized.TestCase): 557 558 def _run_test(self, conv_layer_cls, kwargs, input_shape1, input_shape2, 559 expected_output_shape1, expected_output_shape2): 560 kwargs['filters'] = 1 561 kwargs['kernel_size'] = 3 562 kwargs['dilation_rate'] = 2 563 with self.cached_session(): 564 layer = conv_layer_cls(**kwargs) 565 output1 = layer(np.zeros(input_shape1)) 566 self.assertEqual(output1.shape, expected_output_shape1) 567 output2 = layer(np.zeros(input_shape2)) 568 self.assertEqual(output2.shape, expected_output_shape2) 569 570 @parameterized.named_parameters( 571 ('padding_valid', {'padding': 'valid'}, 572 (1, 8, 2), (1, 5, 2), (1, 4, 1), (1, 1, 1)), 573 ('padding_same', {'padding': 'same'}, 574 (1, 8, 2), (1, 5, 2), (1, 8, 1), (1, 5, 1)), 575 ('padding_causal', {'padding': 'causal'}, 576 (1, 8, 2), (1, 5, 2), (1, 8, 1), (1, 5, 1)), 577 ) 578 def test_conv1d(self, kwargs, input_shape1, input_shape2, 579 expected_output_shape1, expected_output_shape2): 580 self._run_test(keras.layers.Conv1D, kwargs, input_shape1, input_shape2, 581 expected_output_shape1, expected_output_shape2) 582 583 @parameterized.named_parameters( 584 ('padding_valid', {'padding': 'valid'}, 585 (1, 7, 6, 2), (1, 6, 5, 2), (1, 3, 2, 1), (1, 2, 1, 1)), 586 ('padding_same', {'padding': 'same'}, 587 (1, 7, 6, 2), (1, 6, 5, 2), (1, 7, 6, 1), (1, 6, 5, 1)), 588 ) 589 def test_conv2d(self, kwargs, input_shape1, input_shape2, 590 expected_output_shape1, expected_output_shape2): 591 self._run_test(keras.layers.Conv2D, kwargs, input_shape1, input_shape2, 592 expected_output_shape1, expected_output_shape2) 593 594 @parameterized.named_parameters( 595 ('padding_valid', {'padding': 'valid'}, 596 (1, 5, 7, 6, 2), (1, 8, 6, 5, 2), (1, 1, 3, 2, 1), (1, 4, 2, 1, 1)), 597 ('padding_same', {'padding': 'same'}, 598 (1, 5, 7, 6, 2), (1, 8, 6, 5, 2), (1, 5, 7, 6, 1), (1, 8, 6, 5, 1)), 599 ) 600 def test_conv3d(self, kwargs, input_shape1, input_shape2, 601 expected_output_shape1, expected_output_shape2): 602 self._run_test(keras.layers.Conv3D, kwargs, input_shape1, input_shape2, 603 expected_output_shape1, expected_output_shape2) 604 605 def test_dynamic_shape(self): 606 with self.cached_session(): 607 layer = keras.layers.Conv3D(2, 3) 608 input_shape = (5, None, None, 2) 609 inputs = keras.Input(shape=input_shape) 610 x = layer(inputs) 611 # Won't raise error here with None values in input shape (b/144282043). 612 layer(x) 613 614 615@keras_parameterized.run_all_keras_modes 616class ZeroPaddingTest(keras_parameterized.TestCase): 617 618 def test_zero_padding_1d(self): 619 num_samples = 2 620 input_dim = 2 621 num_steps = 5 622 shape = (num_samples, num_steps, input_dim) 623 inputs = np.ones(shape) 624 625 with self.cached_session(): 626 # basic test 627 testing_utils.layer_test( 628 keras.layers.ZeroPadding1D, 629 kwargs={'padding': 2}, 630 input_shape=inputs.shape) 631 testing_utils.layer_test( 632 keras.layers.ZeroPadding1D, 633 kwargs={'padding': (1, 2)}, 634 input_shape=inputs.shape) 635 636 # correctness test 637 layer = keras.layers.ZeroPadding1D(padding=2) 638 layer.build(shape) 639 output = layer(keras.backend.variable(inputs)) 640 if context.executing_eagerly(): 641 np_output = output.numpy() 642 else: 643 np_output = keras.backend.eval(output) 644 for offset in [0, 1, -1, -2]: 645 np.testing.assert_allclose(np_output[:, offset, :], 0.) 646 np.testing.assert_allclose(np_output[:, 2:-2, :], 1.) 647 648 layer = keras.layers.ZeroPadding1D(padding=(1, 2)) 649 layer.build(shape) 650 output = layer(keras.backend.variable(inputs)) 651 if context.executing_eagerly(): 652 np_output = output.numpy() 653 else: 654 np_output = keras.backend.eval(output) 655 for left_offset in [0]: 656 np.testing.assert_allclose(np_output[:, left_offset, :], 0.) 657 for right_offset in [-1, -2]: 658 np.testing.assert_allclose(np_output[:, right_offset, :], 0.) 659 np.testing.assert_allclose(np_output[:, 1:-2, :], 1.) 660 layer.get_config() 661 662 # test incorrect use 663 with self.assertRaises(ValueError): 664 keras.layers.ZeroPadding1D(padding=(1, 1, 1)) 665 with self.assertRaises(ValueError): 666 keras.layers.ZeroPadding1D(padding=None) 667 668 @parameterized.named_parameters(('channels_first', 'channels_first'), 669 ('channels_last', 'channels_last')) 670 def test_zero_padding_2d(self, data_format): 671 num_samples = 2 672 stack_size = 2 673 input_num_row = 4 674 input_num_col = 5 675 if data_format == 'channels_first': 676 inputs = np.ones((num_samples, stack_size, input_num_row, input_num_col)) 677 elif data_format == 'channels_last': 678 inputs = np.ones((num_samples, input_num_row, input_num_col, stack_size)) 679 680 # basic test 681 with self.cached_session(): 682 testing_utils.layer_test( 683 keras.layers.ZeroPadding2D, 684 kwargs={ 685 'padding': (2, 2), 686 'data_format': data_format 687 }, 688 input_shape=inputs.shape) 689 testing_utils.layer_test( 690 keras.layers.ZeroPadding2D, 691 kwargs={ 692 'padding': ((1, 2), (3, 4)), 693 'data_format': data_format 694 }, 695 input_shape=inputs.shape) 696 697 # correctness test 698 with self.cached_session(): 699 layer = keras.layers.ZeroPadding2D( 700 padding=(2, 2), data_format=data_format) 701 layer.build(inputs.shape) 702 output = layer(keras.backend.variable(inputs)) 703 if context.executing_eagerly(): 704 np_output = output.numpy() 705 else: 706 np_output = keras.backend.eval(output) 707 if data_format == 'channels_last': 708 for offset in [0, 1, -1, -2]: 709 np.testing.assert_allclose(np_output[:, offset, :, :], 0.) 710 np.testing.assert_allclose(np_output[:, :, offset, :], 0.) 711 np.testing.assert_allclose(np_output[:, 2:-2, 2:-2, :], 1.) 712 elif data_format == 'channels_first': 713 for offset in [0, 1, -1, -2]: 714 np.testing.assert_allclose(np_output[:, :, offset, :], 0.) 715 np.testing.assert_allclose(np_output[:, :, :, offset], 0.) 716 np.testing.assert_allclose(np_output[:, 2:-2, 2:-2, :], 1.) 717 718 layer = keras.layers.ZeroPadding2D( 719 padding=((1, 2), (3, 4)), data_format=data_format) 720 layer.build(inputs.shape) 721 output = layer(keras.backend.variable(inputs)) 722 if context.executing_eagerly(): 723 np_output = output.numpy() 724 else: 725 np_output = keras.backend.eval(output) 726 if data_format == 'channels_last': 727 for top_offset in [0]: 728 np.testing.assert_allclose(np_output[:, top_offset, :, :], 0.) 729 for bottom_offset in [-1, -2]: 730 np.testing.assert_allclose(np_output[:, bottom_offset, :, :], 0.) 731 for left_offset in [0, 1, 2]: 732 np.testing.assert_allclose(np_output[:, :, left_offset, :], 0.) 733 for right_offset in [-1, -2, -3, -4]: 734 np.testing.assert_allclose(np_output[:, :, right_offset, :], 0.) 735 np.testing.assert_allclose(np_output[:, 1:-2, 3:-4, :], 1.) 736 elif data_format == 'channels_first': 737 for top_offset in [0]: 738 np.testing.assert_allclose(np_output[:, :, top_offset, :], 0.) 739 for bottom_offset in [-1, -2]: 740 np.testing.assert_allclose(np_output[:, :, bottom_offset, :], 0.) 741 for left_offset in [0, 1, 2]: 742 np.testing.assert_allclose(np_output[:, :, :, left_offset], 0.) 743 for right_offset in [-1, -2, -3, -4]: 744 np.testing.assert_allclose(np_output[:, :, :, right_offset], 0.) 745 np.testing.assert_allclose(np_output[:, :, 1:-2, 3:-4], 1.) 746 747 # test incorrect use 748 with self.assertRaises(ValueError): 749 keras.layers.ZeroPadding2D(padding=(1, 1, 1)) 750 with self.assertRaises(ValueError): 751 keras.layers.ZeroPadding2D(padding=None) 752 753 @parameterized.named_parameters(('channels_first', 'channels_first'), 754 ('channels_last', 'channels_last')) 755 def test_zero_padding_3d(self, data_format): 756 num_samples = 2 757 stack_size = 2 758 input_len_dim1 = 4 759 input_len_dim2 = 5 760 input_len_dim3 = 3 761 762 if data_format == 'channels_first': 763 inputs = np.ones((num_samples, stack_size, input_len_dim1, input_len_dim2, 764 input_len_dim3)) 765 elif data_format == 'channels_last': 766 inputs = np.ones((num_samples, input_len_dim1, input_len_dim2, 767 input_len_dim3, stack_size)) 768 769 with self.cached_session(): 770 # basic test 771 testing_utils.layer_test( 772 keras.layers.ZeroPadding3D, 773 kwargs={ 774 'padding': (2, 2, 2), 775 'data_format': data_format 776 }, 777 input_shape=inputs.shape) 778 testing_utils.layer_test( 779 keras.layers.ZeroPadding3D, 780 kwargs={ 781 'padding': ((1, 2), (3, 4), (0, 2)), 782 'data_format': data_format 783 }, 784 input_shape=inputs.shape) 785 786 with self.cached_session(): 787 # correctness test 788 layer = keras.layers.ZeroPadding3D( 789 padding=(2, 2, 2), data_format=data_format) 790 layer.build(inputs.shape) 791 output = layer(keras.backend.variable(inputs)) 792 if context.executing_eagerly(): 793 np_output = output.numpy() 794 else: 795 np_output = keras.backend.eval(output) 796 if data_format == 'channels_last': 797 for offset in [0, 1, -1, -2]: 798 np.testing.assert_allclose(np_output[:, offset, :, :, :], 0.) 799 np.testing.assert_allclose(np_output[:, :, offset, :, :], 0.) 800 np.testing.assert_allclose(np_output[:, :, :, offset, :], 0.) 801 np.testing.assert_allclose(np_output[:, 2:-2, 2:-2, 2:-2, :], 1.) 802 elif data_format == 'channels_first': 803 for offset in [0, 1, -1, -2]: 804 np.testing.assert_allclose(np_output[:, :, offset, :, :], 0.) 805 np.testing.assert_allclose(np_output[:, :, :, offset, :], 0.) 806 np.testing.assert_allclose(np_output[:, :, :, :, offset], 0.) 807 np.testing.assert_allclose(np_output[:, :, 2:-2, 2:-2, 2:-2], 1.) 808 809 layer = keras.layers.ZeroPadding3D( 810 padding=((1, 2), (3, 4), (0, 2)), data_format=data_format) 811 layer.build(inputs.shape) 812 output = layer(keras.backend.variable(inputs)) 813 if context.executing_eagerly(): 814 np_output = output.numpy() 815 else: 816 np_output = keras.backend.eval(output) 817 if data_format == 'channels_last': 818 for offset in [0]: 819 np.testing.assert_allclose(np_output[:, offset, :, :, :], 0.) 820 for offset in [-1, -2]: 821 np.testing.assert_allclose(np_output[:, offset, :, :, :], 0.) 822 for offset in [0, 1, 2]: 823 np.testing.assert_allclose(np_output[:, :, offset, :, :], 0.) 824 for offset in [-1, -2, -3, -4]: 825 np.testing.assert_allclose(np_output[:, :, offset, :, :], 0.) 826 for offset in [-1, -2]: 827 np.testing.assert_allclose(np_output[:, :, :, offset, :], 0.) 828 np.testing.assert_allclose(np_output[:, 1:-2, 3:-4, 0:-2, :], 1.) 829 elif data_format == 'channels_first': 830 for offset in [0]: 831 np.testing.assert_allclose(np_output[:, :, offset, :, :], 0.) 832 for offset in [-1, -2]: 833 np.testing.assert_allclose(np_output[:, :, offset, :, :], 0.) 834 for offset in [0, 1, 2]: 835 np.testing.assert_allclose(np_output[:, :, :, offset, :], 0.) 836 for offset in [-1, -2, -3, -4]: 837 np.testing.assert_allclose(np_output[:, :, :, offset, :], 0.) 838 for offset in [-1, -2]: 839 np.testing.assert_allclose(np_output[:, :, :, :, offset], 0.) 840 np.testing.assert_allclose(np_output[:, :, 1:-2, 3:-4, 0:-2], 1.) 841 842 # test incorrect use 843 with self.assertRaises(ValueError): 844 keras.layers.ZeroPadding3D(padding=(1, 1)) 845 with self.assertRaises(ValueError): 846 keras.layers.ZeroPadding3D(padding=None) 847 848 849@test_util.for_all_test_methods(test_util.disable_xla, 850 'align_corners=False not supported by XLA') 851@keras_parameterized.run_all_keras_modes 852class UpSamplingTest(keras_parameterized.TestCase): 853 854 def test_upsampling_1d(self): 855 with self.cached_session(): 856 testing_utils.layer_test( 857 keras.layers.UpSampling1D, kwargs={'size': 2}, input_shape=(3, 5, 4)) 858 859 def test_upsampling_2d(self): 860 num_samples = 2 861 stack_size = 2 862 input_num_row = 11 863 input_num_col = 12 864 865 for data_format in ['channels_first', 'channels_last']: 866 if data_format == 'channels_first': 867 inputs = np.random.rand(num_samples, stack_size, input_num_row, 868 input_num_col) 869 else: 870 inputs = np.random.rand(num_samples, input_num_row, input_num_col, 871 stack_size) 872 873 # basic test 874 with self.cached_session(): 875 testing_utils.layer_test( 876 keras.layers.UpSampling2D, 877 kwargs={'size': (2, 2), 878 'data_format': data_format}, 879 input_shape=inputs.shape) 880 881 for length_row in [2]: 882 for length_col in [2, 3]: 883 layer = keras.layers.UpSampling2D( 884 size=(length_row, length_col), data_format=data_format) 885 layer.build(inputs.shape) 886 output = layer(keras.backend.variable(inputs)) 887 if context.executing_eagerly(): 888 np_output = output.numpy() 889 else: 890 np_output = keras.backend.eval(output) 891 if data_format == 'channels_first': 892 assert np_output.shape[2] == length_row * input_num_row 893 assert np_output.shape[3] == length_col * input_num_col 894 else: # tf 895 assert np_output.shape[1] == length_row * input_num_row 896 assert np_output.shape[2] == length_col * input_num_col 897 898 # compare with numpy 899 if data_format == 'channels_first': 900 expected_out = np.repeat(inputs, length_row, axis=2) 901 expected_out = np.repeat(expected_out, length_col, axis=3) 902 else: # tf 903 expected_out = np.repeat(inputs, length_row, axis=1) 904 expected_out = np.repeat(expected_out, length_col, axis=2) 905 906 np.testing.assert_allclose(np_output, expected_out) 907 908 def test_upsampling_2d_bilinear(self): 909 num_samples = 2 910 stack_size = 2 911 input_num_row = 11 912 input_num_col = 12 913 for data_format in ['channels_first', 'channels_last']: 914 if data_format == 'channels_first': 915 inputs = np.random.rand(num_samples, stack_size, input_num_row, 916 input_num_col) 917 else: 918 inputs = np.random.rand(num_samples, input_num_row, input_num_col, 919 stack_size) 920 921 testing_utils.layer_test(keras.layers.UpSampling2D, 922 kwargs={'size': (2, 2), 923 'data_format': data_format, 924 'interpolation': 'bilinear'}, 925 input_shape=inputs.shape) 926 927 if not context.executing_eagerly(): 928 for length_row in [2]: 929 for length_col in [2, 3]: 930 layer = keras.layers.UpSampling2D( 931 size=(length_row, length_col), 932 data_format=data_format) 933 layer.build(inputs.shape) 934 outputs = layer(keras.backend.variable(inputs)) 935 np_output = keras.backend.eval(outputs) 936 if data_format == 'channels_first': 937 self.assertEqual(np_output.shape[2], length_row * input_num_row) 938 self.assertEqual(np_output.shape[3], length_col * input_num_col) 939 else: 940 self.assertEqual(np_output.shape[1], length_row * input_num_row) 941 self.assertEqual(np_output.shape[2], length_col * input_num_col) 942 943 def test_upsampling_3d(self): 944 num_samples = 2 945 stack_size = 2 946 input_len_dim1 = 10 947 input_len_dim2 = 11 948 input_len_dim3 = 12 949 950 for data_format in ['channels_first', 'channels_last']: 951 if data_format == 'channels_first': 952 inputs = np.random.rand(num_samples, stack_size, input_len_dim1, 953 input_len_dim2, input_len_dim3) 954 else: 955 inputs = np.random.rand(num_samples, input_len_dim1, input_len_dim2, 956 input_len_dim3, stack_size) 957 958 # basic test 959 with self.cached_session(): 960 testing_utils.layer_test( 961 keras.layers.UpSampling3D, 962 kwargs={'size': (2, 2, 2), 963 'data_format': data_format}, 964 input_shape=inputs.shape) 965 966 for length_dim1 in [2, 3]: 967 for length_dim2 in [2]: 968 for length_dim3 in [3]: 969 layer = keras.layers.UpSampling3D( 970 size=(length_dim1, length_dim2, length_dim3), 971 data_format=data_format) 972 layer.build(inputs.shape) 973 output = layer(keras.backend.variable(inputs)) 974 if context.executing_eagerly(): 975 np_output = output.numpy() 976 else: 977 np_output = keras.backend.eval(output) 978 if data_format == 'channels_first': 979 assert np_output.shape[2] == length_dim1 * input_len_dim1 980 assert np_output.shape[3] == length_dim2 * input_len_dim2 981 assert np_output.shape[4] == length_dim3 * input_len_dim3 982 else: # tf 983 assert np_output.shape[1] == length_dim1 * input_len_dim1 984 assert np_output.shape[2] == length_dim2 * input_len_dim2 985 assert np_output.shape[3] == length_dim3 * input_len_dim3 986 987 # compare with numpy 988 if data_format == 'channels_first': 989 expected_out = np.repeat(inputs, length_dim1, axis=2) 990 expected_out = np.repeat(expected_out, length_dim2, axis=3) 991 expected_out = np.repeat(expected_out, length_dim3, axis=4) 992 else: # tf 993 expected_out = np.repeat(inputs, length_dim1, axis=1) 994 expected_out = np.repeat(expected_out, length_dim2, axis=2) 995 expected_out = np.repeat(expected_out, length_dim3, axis=3) 996 997 np.testing.assert_allclose(np_output, expected_out) 998 999 1000@keras_parameterized.run_all_keras_modes 1001class CroppingTest(keras_parameterized.TestCase): 1002 1003 def test_cropping_1d(self): 1004 num_samples = 2 1005 time_length = 4 1006 input_len_dim1 = 2 1007 inputs = np.random.rand(num_samples, time_length, input_len_dim1) 1008 1009 with self.cached_session(): 1010 testing_utils.layer_test( 1011 keras.layers.Cropping1D, 1012 kwargs={'cropping': (2, 2)}, 1013 input_shape=inputs.shape) 1014 1015 # test incorrect use 1016 with self.assertRaises(ValueError): 1017 keras.layers.Cropping1D(cropping=(1, 1, 1)) 1018 with self.assertRaises(ValueError): 1019 keras.layers.Cropping1D(cropping=None) 1020 1021 def test_cropping_2d(self): 1022 num_samples = 2 1023 stack_size = 2 1024 input_len_dim1 = 9 1025 input_len_dim2 = 9 1026 cropping = ((2, 2), (3, 3)) 1027 1028 for data_format in ['channels_first', 'channels_last']: 1029 if data_format == 'channels_first': 1030 inputs = np.random.rand(num_samples, stack_size, input_len_dim1, 1031 input_len_dim2) 1032 else: 1033 inputs = np.random.rand(num_samples, input_len_dim1, input_len_dim2, 1034 stack_size) 1035 with self.cached_session(): 1036 # basic test 1037 testing_utils.layer_test( 1038 keras.layers.Cropping2D, 1039 kwargs={'cropping': cropping, 1040 'data_format': data_format}, 1041 input_shape=inputs.shape) 1042 # correctness test 1043 layer = keras.layers.Cropping2D( 1044 cropping=cropping, data_format=data_format) 1045 layer.build(inputs.shape) 1046 output = layer(keras.backend.variable(inputs)) 1047 if context.executing_eagerly(): 1048 np_output = output.numpy() 1049 else: 1050 np_output = keras.backend.eval(output) 1051 # compare with numpy 1052 if data_format == 'channels_first': 1053 expected_out = inputs[:, :, cropping[0][0]:-cropping[0][1], cropping[ 1054 1][0]:-cropping[1][1]] 1055 else: 1056 expected_out = inputs[:, cropping[0][0]:-cropping[0][1], cropping[1][ 1057 0]:-cropping[1][1], :] 1058 np.testing.assert_allclose(np_output, expected_out) 1059 1060 for data_format in ['channels_first', 'channels_last']: 1061 if data_format == 'channels_first': 1062 inputs = np.random.rand(num_samples, stack_size, input_len_dim1, 1063 input_len_dim2) 1064 else: 1065 inputs = np.random.rand(num_samples, input_len_dim1, input_len_dim2, 1066 stack_size) 1067 # another correctness test (no cropping) 1068 with self.cached_session(): 1069 cropping = ((0, 0), (0, 0)) 1070 layer = keras.layers.Cropping2D( 1071 cropping=cropping, data_format=data_format) 1072 layer.build(inputs.shape) 1073 output = layer(keras.backend.variable(inputs)) 1074 if context.executing_eagerly(): 1075 np_output = output.numpy() 1076 else: 1077 np_output = keras.backend.eval(output) 1078 # compare with input 1079 np.testing.assert_allclose(np_output, inputs) 1080 1081 # test incorrect use 1082 with self.assertRaises(ValueError): 1083 keras.layers.Cropping2D(cropping=(1, 1, 1)) 1084 with self.assertRaises(ValueError): 1085 keras.layers.Cropping2D(cropping=None) 1086 1087 def test_cropping_3d(self): 1088 num_samples = 2 1089 stack_size = 2 1090 input_len_dim1 = 8 1091 input_len_dim2 = 8 1092 input_len_dim3 = 8 1093 croppings = [((2, 2), (1, 1), (2, 3)), 3, (0, 1, 1)] 1094 1095 for cropping in croppings: 1096 for data_format in ['channels_last', 'channels_first']: 1097 if data_format == 'channels_first': 1098 inputs = np.random.rand(num_samples, stack_size, input_len_dim1, 1099 input_len_dim2, input_len_dim3) 1100 else: 1101 inputs = np.random.rand(num_samples, input_len_dim1, input_len_dim2, 1102 input_len_dim3, stack_size) 1103 # basic test 1104 with self.cached_session(): 1105 testing_utils.layer_test( 1106 keras.layers.Cropping3D, 1107 kwargs={'cropping': cropping, 1108 'data_format': data_format}, 1109 input_shape=inputs.shape) 1110 1111 if len(croppings) == 3 and len(croppings[0]) == 2: 1112 # correctness test 1113 with self.cached_session(): 1114 layer = keras.layers.Cropping3D( 1115 cropping=cropping, data_format=data_format) 1116 layer.build(inputs.shape) 1117 output = layer(keras.backend.variable(inputs)) 1118 if context.executing_eagerly(): 1119 np_output = output.numpy() 1120 else: 1121 np_output = keras.backend.eval(output) 1122 # compare with numpy 1123 if data_format == 'channels_first': 1124 expected_out = inputs[:, :, 1125 cropping[0][0]:-cropping[0][1], 1126 cropping[1][0]:-cropping[1][1], 1127 cropping[2][0]:-cropping[2][1]] 1128 else: 1129 expected_out = inputs[:, 1130 cropping[0][0]:-cropping[0][1], 1131 cropping[1][0]:-cropping[1][1], 1132 cropping[2][0]:-cropping[2][1], :] 1133 np.testing.assert_allclose(np_output, expected_out) 1134 1135 # test incorrect use 1136 with self.assertRaises(ValueError): 1137 keras.layers.Cropping3D(cropping=(1, 1)) 1138 with self.assertRaises(ValueError): 1139 keras.layers.Cropping3D(cropping=None) 1140 1141 1142@keras_parameterized.run_all_keras_modes 1143class DepthwiseConv2DTest(keras_parameterized.TestCase): 1144 1145 def _run_test(self, kwargs, expected_output_shape=None): 1146 num_samples = 2 1147 stack_size = 3 1148 num_row = 7 1149 num_col = 6 1150 1151 with self.cached_session(): 1152 testing_utils.layer_test( 1153 keras.layers.DepthwiseConv2D, 1154 kwargs=kwargs, 1155 input_shape=(num_samples, num_row, num_col, stack_size), 1156 expected_output_shape=expected_output_shape) 1157 1158 @parameterized.named_parameters( 1159 ('padding_valid', {'padding': 'valid'}), 1160 ('padding_same', {'padding': 'same'}), 1161 ('strides', {'strides': (2, 2)}), 1162 # Only runs on GPU with CUDA, channels_first is not supported on CPU. 1163 # TODO(b/62340061): Support channels_first on CPU. 1164 ('data_format', {'data_format': 'channels_first'}), 1165 ('depth_multiplier_1', {'depth_multiplier': 1}), 1166 ('depth_multiplier_2', {'depth_multiplier': 2}), 1167 ('dilation_rate', {'dilation_rate': (2, 2)}, (None, 3, 2, 3)), 1168 ) 1169 def test_depthwise_conv2d(self, kwargs, expected_output_shape=None): 1170 kwargs['kernel_size'] = (3, 3) 1171 if 'data_format' not in kwargs or test.is_gpu_available(cuda_only=True): 1172 self._run_test(kwargs, expected_output_shape) 1173 1174 def test_depthwise_conv2d_full(self): 1175 kwargs = { 1176 'kernel_size': 3, 1177 'padding': 'valid', 1178 'data_format': 'channels_last', 1179 'dilation_rate': (1, 1), 1180 'activation': None, 1181 'depthwise_regularizer': 'l2', 1182 'bias_regularizer': 'l2', 1183 'activity_regularizer': 'l2', 1184 'depthwise_constraint': 'unit_norm', 1185 'use_bias': True, 1186 'strides': (2, 2), 1187 'depth_multiplier': 1, 1188 } 1189 self._run_test(kwargs) 1190 1191if __name__ == '__main__': 1192 test.main() 1193