Skip to content
This repository has been archived by the owner on Nov 3, 2022. It is now read-only.

Commit

Permalink
added conv1d & conv2d functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
kirschte committed Feb 21, 2019
1 parent 1bc09d7 commit ba3eb0b
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 31 deletions.
33 changes: 21 additions & 12 deletions keras_contrib/wrappers/cdropout.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ class ConcreteDropout(Wrapper):
"""A wrapper automating the dropout rate choice
through the 'Concrete Dropout' technique.
Note that currently only Dense layers with weights
and Conv layers (Conv1D, Conv2D, Conv3D) are supported.
In the case of Dense Layers, dropout is applied to its complete input,
whereas in the Conv case just the input-channels are dropped.
# Example
```python
Expand All @@ -24,7 +29,7 @@ class ConcreteDropout(Wrapper):
model.add(ConcreteDropout(Dense(32), n_data=500))
# now model.output_shape == (None, 32)
# Note that the current implementation supports Conv2D Layer as well.
# Note that the current implementation supports Conv layers as well.
```
# Arguments
Expand Down Expand Up @@ -83,19 +88,21 @@ def _concrete_dropout(self, inputs, layer_type):
# Arguments
inputs: Input.
layer_type: str. Either 'dense' or 'conv2d'.
layer_type: str. Either 'dense' or 'conv'.
# Returns
A tensor with the same shape as inputs and dropout applied.
"""
assert layer_type in {'dense', 'conv2d'}
assert layer_type in {'dense', 'conv'}
eps = K.cast_to_floatx(K.epsilon())

noise_shape = K.shape(inputs)
if layer_type == 'conv2d':
if layer_type == 'conv':
nodrops = np.ones(len(K.int_shape(inputs)) - 2, int)
_ = lambda *x: x # don't ask... py2 can't unpack directly into a tuple
if K.image_data_format() == 'channels_first':
noise_shape = (noise_shape[0], noise_shape[1], 1, 1)
noise_shape = _(noise_shape[0], noise_shape[1], *nodrops)
else:
noise_shape = (noise_shape[0], 1, 1, noise_shape[3])
noise_shape = _(noise_shape[0], *(_(*nodrops) + (noise_shape[-1],)))
unif_noise = K.random_uniform(shape=noise_shape,
seed=self._seed,
dtype=inputs.dtype)
Expand All @@ -119,13 +126,15 @@ def build(self, input_shape=None):
input_shape = to_tuple(input_shape)
if len(input_shape) == 2: # Dense_layer
input_dim = np.prod(input_shape[-1]) # we drop only last dim
elif len(input_shape) == 4: # Conv2D_layer
input_dim = (input_shape[1]
if K.image_data_format() == 'channels_first'
else input_shape[3]) # we drop only channels
elif 3 <= len(input_shape) <= 5: # Conv_layers
input_dim = (
input_shape[1]
if K.image_data_format() == 'channels_first'
else input_shape[-1] # we drop only channels
)
else:
raise ValueError(
'concrete_dropout currenty supports only Dense/Conv2D layers')
'concrete_dropout currenty supports only Dense/Conv layers')

self.input_spec = InputSpec(shape=input_shape)
if not self.layer.built:
Expand Down Expand Up @@ -161,7 +170,7 @@ def build(self, input_shape=None):
def call(self, inputs, training=None):
def relaxed_dropped_inputs():
return self.layer.call(self._concrete_dropout(inputs, (
'dense' if len(K.int_shape(inputs)) == 2 else 'conv2d'
'dense' if len(K.int_shape(inputs)) == 2 else 'conv'
)))

return K.in_train_phase(relaxed_dropped_inputs,
Expand Down
30 changes: 11 additions & 19 deletions tests/keras_contrib/wrappers/test_cdropout.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from numpy.testing import assert_approx_equal
from numpy.testing import assert_equal
from keras import backend as K
from keras.layers import Input, Dense, Conv1D, Conv2D, Conv3D
from keras.layers import Conv1D, Conv2D, Conv3D, Dense, Input
from keras.models import Model
from keras_contrib.utils.test_utils import layer_test
from keras_contrib.wrappers import ConcreteDropout
Expand Down Expand Up @@ -204,29 +204,21 @@ def sigmoid(x):


@pytest.mark.parametrize('n_data', [1, 60])
@pytest.mark.parametrize('layer, shape', [(Conv1D(8, 3), (None, 20, 1)),
(Conv3D(16, 7), (1, 20, 20, 20, 1))])
def test_cdropout_invalid_layer(layer, shape, n_data):
"""To be replaced with a real function test, if implemented.
"""
with pytest.raises(ValueError):
layer_test(ConcreteDropout,
kwargs={'layer': layer,
'n_data': n_data},
input_shape=shape)


@pytest.mark.parametrize('n_data', [1, 60])
@pytest.mark.parametrize('layer, shape', [(Conv2D(8, 3), (None, 12, 12, 3)),
(Conv2D(16, 7), (1, 12, 12, 3))])
def test_cdropout_valid_layer(layer, shape, n_data):
"""Original layer test with valid parameters.
@pytest.mark.parametrize('layer, args, shape', [(Dense, (2), (None, 6)),
(Conv1D, (4, 3), (None, 6, 1)),
(Conv2D, (8, 7), (None, 12, 12, 3)),
(Conv3D, (16, 3), (1, 6, 6, 6, 1))])
def test_cdropout_valid_layer(layer, args, shape, n_data):
"""Original layer test with a variety of different valid parameters.
"""
layer_test(ConcreteDropout,
kwargs={'layer': layer,
kwargs={'layer': layer(*args),
'n_data': n_data},
input_shape=shape)

if K.backend() == 'tensorflow' or K.backend() == 'cntk':
K.clear_session()


if __name__ == '__main__':
pytest.main([__file__])

0 comments on commit ba3eb0b

Please sign in to comment.