def test_convolution_2d(self): num_samples = 2 filters = 2 stack_size = 3 kernel_size = (3, 2) num_row = 7 num_col = 6 for padding in ['valid', 'same']: for strides in [(1, 1), (2, 2)]: if padding == 'same' and strides != (1, 1): continue with self.test_session(use_gpu=True): # Only runs on GPU with CUDA, channels_first is not supported on CPU. # TODO(b/62340061): Support channels_first on CPU. if test.is_gpu_available(cuda_only=True): testing_utils.layer_test( keras.layers.Conv2D, kwargs={ 'filters': filters, 'kernel_size': kernel_size, 'padding': padding, 'strides': strides, 'data_format': 'channels_first' }, input_shape=(num_samples, stack_size, num_row, num_col))
def test_conv_lstm(self): num_row = 3 num_col = 3 filters = 2 num_samples = 1 input_channel = 2 input_num_row = 5 input_num_col = 5 sequence_len = 2 for data_format in ['channels_first', 'channels_last']: if data_format == 'channels_first': inputs = np.random.rand(num_samples, sequence_len, input_channel, input_num_row, input_num_col) else: inputs = np.random.rand(num_samples, sequence_len, input_num_row, input_num_col, input_channel) for return_sequences in [True, False]: # test for output shape: with self.test_session(): testing_utils.layer_test( keras.layers.ConvLSTM2D, kwargs={'data_format': data_format, 'return_sequences': return_sequences, 'filters': filters, 'kernel_size': (num_row, num_col), 'padding': 'valid'}, input_shape=inputs.shape)
def test_convolution_3d(self): num_samples = 2 filters = 2 stack_size = 3 input_len_dim1 = 9 input_len_dim2 = 8 input_len_dim3 = 8 for padding in ['valid', 'same']: for strides in [(1, 1, 1), (2, 2, 2)]: if padding == 'same' and strides != (1, 1, 1): continue with self.test_session(use_gpu=True): testing_utils.layer_test( keras.layers.Convolution3D, kwargs={ 'filters': filters, 'kernel_size': 3, 'padding': padding, 'strides': strides }, input_shape=(num_samples, input_len_dim1, input_len_dim2, input_len_dim3, stack_size))
def test_zero_padding_3d(self): num_samples = 2 stack_size = 2 input_len_dim1 = 4 input_len_dim2 = 5 input_len_dim3 = 3 inputs = np.ones((num_samples, input_len_dim1, input_len_dim2, input_len_dim3, stack_size)) # basic test with self.test_session(use_gpu=True): testing_utils.layer_test( keras.layers.ZeroPadding3D, kwargs={'padding': (2, 2, 2)}, input_shape=inputs.shape) # correctness test with self.test_session(use_gpu=True): layer = keras.layers.ZeroPadding3D(padding=(2, 2, 2)) layer.build(inputs.shape) output = layer(keras.backend.variable(inputs)) np_output = keras.backend.eval(output) for offset in [0, 1, -1, -2]: np.testing.assert_allclose(np_output[:, offset, :, :, :], 0.) np.testing.assert_allclose(np_output[:, :, offset, :, :], 0.) np.testing.assert_allclose(np_output[:, :, :, offset, :], 0.) np.testing.assert_allclose(np_output[:, 2:-2, 2:-2, 2:-2, :], 1.)
def test_averagepooling_1d(self): with self.test_session(use_gpu=True): for padding in ['valid', 'same']: for stride in [1, 2]: testing_utils.layer_test( keras.layers.AveragePooling1D, kwargs={'strides': stride, 'padding': padding}, input_shape=(3, 5, 4))
def test_return_sequences_SimpleRNN(self): num_samples = 2 timesteps = 3 embedding_dim = 4 units = 2 with self.test_session(): testing_utils.layer_test( keras.layers.SimpleRNN, kwargs={'units': units, 'return_sequences': True}, input_shape=(num_samples, timesteps, embedding_dim))
def test_cropping_1d(self): num_samples = 2 time_length = 4 input_len_dim1 = 2 inputs = np.random.rand(num_samples, time_length, input_len_dim1) with self.test_session(use_gpu=True): testing_utils.layer_test( keras.layers.Cropping1D, kwargs={'cropping': (2, 2)}, input_shape=inputs.shape)
def test_cropping_2d(self): num_samples = 2 stack_size = 2 input_len_dim1 = 9 input_len_dim2 = 9 cropping = ((2, 2), (3, 3)) for data_format in ['channels_first', 'channels_last']: if data_format == 'channels_first': inputs = np.random.rand(num_samples, stack_size, input_len_dim1, input_len_dim2) else: inputs = np.random.rand(num_samples, input_len_dim1, input_len_dim2, stack_size) # basic test with self.test_session(use_gpu=True): testing_utils.layer_test( keras.layers.Cropping2D, kwargs={'cropping': cropping, 'data_format': data_format}, input_shape=inputs.shape) # correctness test with self.test_session(use_gpu=True): layer = keras.layers.Cropping2D( cropping=cropping, data_format=data_format) layer.build(inputs.shape) output = layer(keras.backend.variable(inputs)) np_output = keras.backend.eval(output) # compare with numpy if data_format == 'channels_first': expected_out = inputs[:, :, cropping[0][0]:-cropping[0][1], cropping[ 1][0]:-cropping[1][1]] else: expected_out = inputs[:, cropping[0][0]:-cropping[0][1], cropping[1][ 0]:-cropping[1][1], :] np.testing.assert_allclose(np_output, expected_out) for data_format in ['channels_first', 'channels_last']: if data_format == 'channels_first': inputs = np.random.rand(num_samples, stack_size, input_len_dim1, input_len_dim2) else: inputs = np.random.rand(num_samples, input_len_dim1, input_len_dim2, stack_size) # another correctness test (no cropping) with self.test_session(use_gpu=True): cropping = ((0, 0), (0, 0)) layer = keras.layers.Cropping2D( cropping=cropping, data_format=data_format) layer.build(inputs.shape) output = layer(keras.backend.variable(inputs)) np_output = keras.backend.eval(output) # compare with input np.testing.assert_allclose(np_output, inputs)
def test_implementation_mode_SimpleRNN(self): num_samples = 2 timesteps = 3 embedding_dim = 4 units = 2 with self.test_session(): for mode in [0, 1, 2]: testing_utils.layer_test( keras.layers.SimpleRNN, kwargs={'units': units, 'implementation': mode}, input_shape=(num_samples, timesteps, embedding_dim))
def test_maxpooling_2d(self): pool_size = (3, 3) with self.test_session(use_gpu=True): for strides in [(1, 1), (2, 2)]: testing_utils.layer_test( keras.layers.MaxPooling2D, kwargs={ 'strides': strides, 'padding': 'valid', 'pool_size': pool_size }, input_shape=(3, 5, 6, 4))
def test_dropout_SimpleRNN(self): num_samples = 2 timesteps = 3 embedding_dim = 4 units = 2 with self.test_session(): testing_utils.layer_test( keras.layers.SimpleRNN, kwargs={'units': units, 'dropout': 0.1, 'recurrent_dropout': 0.1}, input_shape=(num_samples, timesteps, embedding_dim))
def test_upsampling_3d(self): num_samples = 2 stack_size = 2 input_len_dim1 = 10 input_len_dim2 = 11 input_len_dim3 = 12 for data_format in ['channels_first', 'channels_last']: if data_format == 'channels_first': inputs = np.random.rand(num_samples, stack_size, input_len_dim1, input_len_dim2, input_len_dim3) else: inputs = np.random.rand(num_samples, input_len_dim1, input_len_dim2, input_len_dim3, stack_size) # basic test with self.test_session(use_gpu=True): testing_utils.layer_test( keras.layers.UpSampling3D, kwargs={'size': (2, 2, 2), 'data_format': data_format}, input_shape=inputs.shape) for length_dim1 in [2, 3]: for length_dim2 in [2]: for length_dim3 in [3]: layer = keras.layers.UpSampling3D( size=(length_dim1, length_dim2, length_dim3), data_format=data_format) layer.build(inputs.shape) output = layer(keras.backend.variable(inputs)) np_output = keras.backend.eval(output) if data_format == 'channels_first': assert np_output.shape[2] == length_dim1 * input_len_dim1 assert np_output.shape[3] == length_dim2 * input_len_dim2 assert np_output.shape[4] == length_dim3 * input_len_dim3 else: # tf assert np_output.shape[1] == length_dim1 * input_len_dim1 assert np_output.shape[2] == length_dim2 * input_len_dim2 assert np_output.shape[3] == length_dim3 * input_len_dim3 # compare with numpy if data_format == 'channels_first': expected_out = np.repeat(inputs, length_dim1, axis=2) expected_out = np.repeat(expected_out, length_dim2, axis=3) expected_out = np.repeat(expected_out, length_dim3, axis=4) else: # tf expected_out = np.repeat(inputs, length_dim1, axis=1) expected_out = np.repeat(expected_out, length_dim2, axis=2) expected_out = np.repeat(expected_out, length_dim3, axis=3) np.testing.assert_allclose(np_output, expected_out)
def test_conv_lstm_dropout(self): # check dropout with self.test_session(): testing_utils.layer_test( keras.layers.ConvLSTM2D, kwargs={'data_format': 'channels_last', 'return_sequences': False, 'filters': 2, 'kernel_size': (3, 3), 'padding': 'same', 'dropout': 0.1, 'recurrent_dropout': 0.1}, input_shape=(1, 2, 5, 5, 2))
def test_dilated_conv1d(self): with self.test_session(use_gpu=True): testing_utils.layer_test( keras.layers.Conv1D, input_data=np.reshape(np.arange(4, dtype='float32'), (1, 4, 1)), kwargs={ 'filters': 1, 'kernel_size': 2, 'dilation_rate': 1, 'padding': 'valid', 'kernel_initializer': 'ones', 'use_bias': False, }, expected_output=[[[1], [3], [5]]])
def test_dense(self): with self.test_session(): testing_utils.layer_test( keras.layers.Dense, kwargs={'units': 3}, input_shape=(3, 2)) with self.test_session(): testing_utils.layer_test( keras.layers.Dense, kwargs={'units': 3}, input_shape=(3, 4, 2)) with self.test_session(): testing_utils.layer_test( keras.layers.Dense, kwargs={'units': 3}, input_shape=(None, None, 2)) with self.test_session(): testing_utils.layer_test( keras.layers.Dense, kwargs={'units': 3}, input_shape=(3, 4, 5, 2)) # Test regularization with self.test_session(): layer = keras.layers.Dense( 3, kernel_regularizer=keras.regularizers.l1(0.01), bias_regularizer='l1', activity_regularizer='l2', name='dense_reg') layer(keras.backend.variable(np.ones((2, 4)))) self.assertEqual(3, len(layer.losses)) # Test constraints with self.test_session(): layer = keras.layers.Dense( 3, kernel_constraint='max_norm', bias_constraint='max_norm') layer(keras.backend.variable(np.ones((2, 4)))) self.assertEqual(2, len(layer.constraints))
def test_activation(self): # with string argument with self.test_session(): testing_utils.layer_test( keras.layers.Activation, kwargs={'activation': 'relu'}, input_shape=(3, 2)) # with function argument with self.test_session(): testing_utils.layer_test( keras.layers.Activation, kwargs={'activation': keras.backend.relu}, input_shape=(3, 2))
def test_conv_lstm(self): num_row = 3 num_col = 3 filters = 2 num_samples = 1 input_channel = 2 input_num_row = 5 input_num_col = 5 sequence_len = 2 for data_format in ['channels_first', 'channels_last']: if data_format == 'channels_first': inputs = np.random.rand(num_samples, sequence_len, input_channel, input_num_row, input_num_col) else: inputs = np.random.rand(num_samples, sequence_len, input_num_row, input_num_col, input_channel) for return_sequences in [True, False]: with self.test_session(): # test for return state: x = keras.Input(batch_shape=inputs.shape) kwargs = {'data_format': data_format, 'return_sequences': return_sequences, 'return_state': True, 'stateful': True, 'filters': filters, 'kernel_size': (num_row, num_col), 'padding': 'valid'} layer = keras.layers.ConvLSTM2D(**kwargs) layer.build(inputs.shape) outputs = layer(x) _, states = outputs[0], outputs[1:] self.assertEqual(len(states), 2) model = keras.models.Model(x, states[0]) state = model.predict(inputs) self.assertAllClose( keras.backend.eval(layer.states[0]), state, atol=1e-4) # test for output shape: testing_utils.layer_test( keras.layers.ConvLSTM2D, kwargs={'data_format': data_format, 'return_sequences': return_sequences, 'filters': filters, 'kernel_size': (num_row, num_col), 'padding': 'valid'}, input_shape=inputs.shape)
def test_upsampling_2d(self): num_samples = 2 stack_size = 2 input_num_row = 11 input_num_col = 12 for data_format in ['channels_first', 'channels_last']: if data_format == 'channels_first': inputs = np.random.rand(num_samples, stack_size, input_num_row, input_num_col) else: inputs = np.random.rand(num_samples, input_num_row, input_num_col, stack_size) # basic test with self.test_session(use_gpu=True): testing_utils.layer_test( keras.layers.UpSampling2D, kwargs={'size': (2, 2), 'data_format': data_format}, input_shape=inputs.shape) for length_row in [2]: for length_col in [2, 3]: layer = keras.layers.UpSampling2D( size=(length_row, length_col), data_format=data_format) layer.build(inputs.shape) output = layer(keras.backend.variable(inputs)) np_output = keras.backend.eval(output) if data_format == 'channels_first': assert np_output.shape[2] == length_row * input_num_row assert np_output.shape[3] == length_col * input_num_col else: # tf assert np_output.shape[1] == length_row * input_num_row assert np_output.shape[2] == length_col * input_num_col # compare with numpy if data_format == 'channels_first': expected_out = np.repeat(inputs, length_row, axis=2) expected_out = np.repeat(expected_out, length_col, axis=3) else: # tf expected_out = np.repeat(inputs, length_row, axis=1) expected_out = np.repeat(expected_out, length_col, axis=2) np.testing.assert_allclose(np_output, expected_out)
def test_averagepooling_3d(self): pool_size = (3, 3, 3) with self.test_session(use_gpu=True): testing_utils.layer_test( keras.layers.AveragePooling3D, kwargs={'strides': 2, 'padding': 'valid', 'pool_size': pool_size}, input_shape=(3, 11, 12, 10, 4)) testing_utils.layer_test( keras.layers.AveragePooling3D, kwargs={ 'strides': 3, 'padding': 'valid', 'data_format': 'channels_first', 'pool_size': pool_size }, input_shape=(3, 4, 11, 12, 10))
def test_dilated_conv_2d(self): num_samples = 2 filters = 2 stack_size = 3 kernel_size = (3, 2) num_row = 7 num_col = 6 # Test dilation with self.test_session(use_gpu=True): testing_utils.layer_test( keras.layers.Conv2D, kwargs={ 'filters': filters, 'kernel_size': kernel_size, 'dilation_rate': (2, 2) }, input_shape=(num_samples, num_row, num_col, stack_size))
def test_cropping_3d(self): num_samples = 2 stack_size = 2 input_len_dim1 = 8 input_len_dim2 = 8 input_len_dim3 = 8 cropping = ((2, 2), (1, 1), (2, 3)) for data_format in ['channels_last', 'channels_first']: if data_format == 'channels_first': inputs = np.random.rand(num_samples, stack_size, input_len_dim1, input_len_dim2, input_len_dim3) else: inputs = np.random.rand(num_samples, input_len_dim1, input_len_dim2, input_len_dim3, stack_size) # basic test with self.test_session(): testing_utils.layer_test( keras.layers.Cropping3D, kwargs={'cropping': cropping, 'data_format': data_format}, input_shape=inputs.shape) # correctness test with self.test_session(): layer = keras.layers.Cropping3D( cropping=cropping, data_format=data_format) layer.build(inputs.shape) output = layer(keras.backend.variable(inputs)) np_output = keras.backend.eval(output) # compare with numpy if data_format == 'channels_first': expected_out = inputs[:, :, cropping[0][0]:-cropping[0][1], cropping[1][0]:-cropping[1][1], cropping[2][0]:-cropping[2][1]] else: expected_out = inputs[:, cropping[0][0]:-cropping[0][1], cropping[1][0]:-cropping[1][1], cropping[2][0]:-cropping[2][1], :] print(expected_out.shape) np.testing.assert_allclose(np_output, expected_out)
def test_embedding(self): with self.test_session(): testing_utils.layer_test( keras.layers.Embedding, kwargs={'output_dim': 4, 'input_dim': 10, 'input_length': 2}, input_shape=(3, 2), input_dtype='int32', expected_output_dtype='float32') with self.test_session(): testing_utils.layer_test( keras.layers.Embedding, kwargs={'output_dim': 4, 'input_dim': 10, 'mask_zero': True}, input_shape=(3, 2), input_dtype='int32', expected_output_dtype='float32')
def test_averagepooling_2d(self): with self.test_session(use_gpu=True): testing_utils.layer_test( keras.layers.AveragePooling2D, kwargs={'strides': (2, 2), 'padding': 'same', 'pool_size': (2, 2)}, input_shape=(3, 5, 6, 4)) testing_utils.layer_test( keras.layers.AveragePooling2D, kwargs={'strides': (2, 2), 'padding': 'valid', 'pool_size': (3, 3)}, input_shape=(3, 5, 6, 4)) # Only runs on GPU with CUDA, channels_first is not supported on CPU. # TODO(b/62340061): Support channels_first on CPU. if test.is_gpu_available(cuda_only=True): testing_utils.layer_test( keras.layers.AveragePooling2D, kwargs={ 'strides': (1, 1), 'padding': 'valid', 'pool_size': (2, 2), 'data_format': 'channels_first' }, input_shape=(3, 4, 5, 6))
def basic_batchnorm_test(self): with self.test_session(): testing_utils.layer_test( keras.layers.BatchNormalization, kwargs={ 'momentum': 0.9, 'epsilon': 0.1, 'gamma_regularizer': keras.regularizers.l2(0.01), 'beta_regularizer': keras.regularizers.l2(0.01) }, input_shape=(3, 4, 2)) testing_utils.layer_test( keras.layers.BatchNormalization, kwargs={ 'gamma_initializer': 'ones', 'beta_initializer': 'ones', 'moving_mean_initializer': 'zeros', 'moving_variance_initializer': 'ones' }, input_shape=(3, 4, 2)) testing_utils.layer_test( keras.layers.BatchNormalization, kwargs={'scale': False, 'center': False}, input_shape=(3, 3))
def test_conv_1d(self): batch_size = 2 steps = 8 input_dim = 2 kernel_size = 3 filters = 3 for padding in ['valid', 'same']: for strides in [1, 2]: if padding == 'same' and strides != 1: continue with self.test_session(use_gpu=True): testing_utils.layer_test( keras.layers.Conv1D, kwargs={ 'filters': filters, 'kernel_size': kernel_size, 'padding': padding, 'strides': strides }, input_shape=(batch_size, steps, input_dim))
def test_zero_padding_1d(self): num_samples = 2 input_dim = 2 num_steps = 5 shape = (num_samples, num_steps, input_dim) inputs = np.ones(shape) # basic test with self.test_session(use_gpu=True): testing_utils.layer_test( keras.layers.ZeroPadding1D, kwargs={'padding': 2}, input_shape=inputs.shape) testing_utils.layer_test( keras.layers.ZeroPadding1D, kwargs={'padding': (1, 2)}, input_shape=inputs.shape) # correctness test with self.test_session(use_gpu=True): layer = keras.layers.ZeroPadding1D(padding=2) layer.build(shape) output = layer(keras.backend.variable(inputs)) np_output = keras.backend.eval(output) for offset in [0, 1, -1, -2]: np.testing.assert_allclose(np_output[:, offset, :], 0.) np.testing.assert_allclose(np_output[:, 2:-2, :], 1.) layer = keras.layers.ZeroPadding1D(padding=(1, 2)) layer.build(shape) output = layer(keras.backend.variable(inputs)) np_output = keras.backend.eval(output) for left_offset in [0]: np.testing.assert_allclose(np_output[:, left_offset, :], 0.) for right_offset in [-1, -2]: np.testing.assert_allclose(np_output[:, right_offset, :], 0.) np.testing.assert_allclose(np_output[:, 1:-2, :], 1.) layer.get_config()
def test_conv2d_transpose(self): num_samples = 2 filters = 2 stack_size = 3 num_row = 5 num_col = 6 for padding in ['valid', 'same']: for strides in [(1, 1), (2, 2)]: if padding == 'same' and strides != (1, 1): continue with self.test_session(use_gpu=True): testing_utils.layer_test( keras.layers.Conv2DTranspose, kwargs={ 'filters': filters, 'kernel_size': 3, 'padding': padding, 'strides': strides, 'data_format': 'channels_last' }, input_shape=(num_samples, num_row, num_col, stack_size))
def test_lambda(self): with self.test_session(): testing_utils.layer_test( keras.layers.Lambda, kwargs={'function': lambda x: x + 1}, input_shape=(3, 2)) with self.test_session(): testing_utils.layer_test( keras.layers.Lambda, kwargs={ 'function': lambda x, a, b: x * a + b, 'arguments': { 'a': 0.6, 'b': 0.4 } }, input_shape=(3, 2)) with self.test_session(): # test serialization with function def f(x): return x + 1 ld = keras.layers.Lambda(f) config = ld.get_config() ld = keras.layers.deserialize({ 'class_name': 'Lambda', 'config': config }) # test with lambda ld = keras.layers.Lambda( lambda x: keras.backend.concatenate([keras.backend.square(x), x])) config = ld.get_config() ld = keras.layers.Lambda.from_config(config)
def test_convolution_2d(self): num_samples = 2 filters = 2 stack_size = 3 kernel_size = (3, 2) num_row = 7 num_col = 6 for padding in ['valid', 'same']: for strides in [(1, 1), (2, 2)]: if padding == 'same' and strides != (1, 1): continue with self.test_session(use_gpu=True): testing_utils.layer_test( keras.layers.Conv2D, kwargs={ 'filters': filters, 'kernel_size': kernel_size, 'padding': padding, 'strides': strides, 'data_format': 'channels_first' }, input_shape=(num_samples, stack_size, num_row, num_col))
def test_separable_conv_2d(self): num_samples = 2 filters = 6 stack_size = 3 num_row = 7 num_col = 6 for padding in ['valid', 'same']: for strides in [(1, 1), (2, 2)]: for multiplier in [1, 2]: if padding == 'same' and strides != (1, 1): continue with self.test_session(use_gpu=True): testing_utils.layer_test( keras.layers.SeparableConv2D, kwargs={ 'filters': filters, 'kernel_size': (3, 3), 'padding': padding, 'strides': strides, 'depth_multiplier': multiplier }, input_shape=(num_samples, num_row, num_col, stack_size))
def test_cropping_2d(self): num_samples = 2 stack_size = 2 input_len_dim1 = 9 input_len_dim2 = 9 cropping = ((2, 2), (3, 3)) for data_format in ['channels_first', 'channels_last']: if data_format == 'channels_first': inputs = np.random.rand(num_samples, stack_size, input_len_dim1, input_len_dim2) else: inputs = np.random.rand(num_samples, input_len_dim1, input_len_dim2, stack_size) # basic test with self.test_session(use_gpu=True): testing_utils.layer_test(keras.layers.Cropping2D, kwargs={ 'cropping': cropping, 'data_format': data_format }, input_shape=inputs.shape) # correctness test with self.test_session(use_gpu=True): layer = keras.layers.Cropping2D(cropping=cropping, data_format=data_format) layer.build(inputs.shape) output = layer(keras.backend.variable(inputs)) np_output = keras.backend.eval(output) # compare with numpy if data_format == 'channels_first': expected_out = inputs[:, :, cropping[0][0]:-cropping[0][1], cropping[1][0]:-cropping[1][1]] else: expected_out = inputs[:, cropping[0][0]:-cropping[0][1], cropping[1][0]:-cropping[1][1], :] np.testing.assert_allclose(np_output, expected_out) for data_format in ['channels_first', 'channels_last']: if data_format == 'channels_first': inputs = np.random.rand(num_samples, stack_size, input_len_dim1, input_len_dim2) else: inputs = np.random.rand(num_samples, input_len_dim1, input_len_dim2, stack_size) # another correctness test (no cropping) with self.test_session(use_gpu=True): cropping = ((0, 0), (0, 0)) layer = keras.layers.Cropping2D(cropping=cropping, data_format=data_format) layer.build(inputs.shape) output = layer(keras.backend.variable(inputs)) np_output = keras.backend.eval(output) # compare with input np.testing.assert_allclose(np_output, inputs) # test incorrect use with self.assertRaises(ValueError): keras.layers.Cropping2D(cropping=(1, 1, 1)) with self.assertRaises(ValueError): keras.layers.Cropping2D(cropping=None)
def test_prelu_share(self): with self.test_session(): testing_utils.layer_test(keras.layers.PReLU, kwargs={'shared_axes': 1}, input_shape=(2, 3, 4))