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

Commit 6eb632b

Browse files
committed
added conv1d & conv2d functionality
1 parent 1bc09d7 commit 6eb632b

File tree

2 files changed

+32
-31
lines changed

2 files changed

+32
-31
lines changed

keras_contrib/wrappers/cdropout.py

+21-12
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ class ConcreteDropout(Wrapper):
1313
"""A wrapper automating the dropout rate choice
1414
through the 'Concrete Dropout' technique.
1515
16+
Note that currently only Dense layers with weights
17+
and Conv layers (Conv1D, Conv2D, Conv3D) are supported.
18+
In the case of Dense Layers, dropout is applied to its complete input,
19+
whereas in the Conv case just the input-channels are dropped.
20+
1621
# Example
1722
1823
```python
@@ -24,7 +29,7 @@ class ConcreteDropout(Wrapper):
2429
model.add(ConcreteDropout(Dense(32), n_data=500))
2530
# now model.output_shape == (None, 32)
2631
27-
# Note that the current implementation supports Conv2D Layer as well.
32+
# Note that the current implementation supports Conv layers as well.
2833
```
2934
3035
# Arguments
@@ -83,19 +88,21 @@ def _concrete_dropout(self, inputs, layer_type):
8388
8489
# Arguments
8590
inputs: Input.
86-
layer_type: str. Either 'dense' or 'conv2d'.
91+
layer_type: str. Either 'dense' or 'conv'.
8792
# Returns
8893
A tensor with the same shape as inputs and dropout applied.
8994
"""
90-
assert layer_type in {'dense', 'conv2d'}
95+
assert layer_type in {'dense', 'conv'}
9196
eps = K.cast_to_floatx(K.epsilon())
9297

9398
noise_shape = K.shape(inputs)
94-
if layer_type == 'conv2d':
99+
if layer_type == 'conv':
100+
nodrops = np.ones(len(K.int_shape(inputs)) - 2, int)
101+
_ = lambda *x: x # don't ask... py2 can't unpack directly into a tuple
95102
if K.image_data_format() == 'channels_first':
96-
noise_shape = (noise_shape[0], noise_shape[1], 1, 1)
103+
noise_shape = _(noise_shape[0], noise_shape[1], *nodrops)
97104
else:
98-
noise_shape = (noise_shape[0], 1, 1, noise_shape[3])
105+
noise_shape = _(noise_shape[0], *(_(*nodrops) + (noise_shape[-1],)))
99106
unif_noise = K.random_uniform(shape=noise_shape,
100107
seed=self._seed,
101108
dtype=inputs.dtype)
@@ -119,13 +126,15 @@ def build(self, input_shape=None):
119126
input_shape = to_tuple(input_shape)
120127
if len(input_shape) == 2: # Dense_layer
121128
input_dim = np.prod(input_shape[-1]) # we drop only last dim
122-
elif len(input_shape) == 4: # Conv2D_layer
123-
input_dim = (input_shape[1]
124-
if K.image_data_format() == 'channels_first'
125-
else input_shape[3]) # we drop only channels
129+
elif 3 <= len(input_shape) <= 5: # Conv_layers
130+
input_dim = (
131+
input_shape[1]
132+
if K.image_data_format() == 'channels_first'
133+
else input_shape[-1] # we drop only channels
134+
)
126135
else:
127136
raise ValueError(
128-
'concrete_dropout currenty supports only Dense/Conv2D layers')
137+
'concrete_dropout currenty supports only Dense/Conv layers')
129138

130139
self.input_spec = InputSpec(shape=input_shape)
131140
if not self.layer.built:
@@ -161,7 +170,7 @@ def build(self, input_shape=None):
161170
def call(self, inputs, training=None):
162171
def relaxed_dropped_inputs():
163172
return self.layer.call(self._concrete_dropout(inputs, (
164-
'dense' if len(K.int_shape(inputs)) == 2 else 'conv2d'
173+
'dense' if len(K.int_shape(inputs)) == 2 else 'conv'
165174
)))
166175

167176
return K.in_train_phase(relaxed_dropped_inputs,

tests/keras_contrib/wrappers/test_cdropout.py

+11-19
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from numpy.testing import assert_approx_equal
77
from numpy.testing import assert_equal
88
from keras import backend as K
9-
from keras.layers import Input, Dense, Conv1D, Conv2D, Conv3D
9+
from keras.layers import Conv1D, Conv2D, Conv3D, Dense, Input
1010
from keras.models import Model
1111
from keras_contrib.utils.test_utils import layer_test
1212
from keras_contrib.wrappers import ConcreteDropout
@@ -204,29 +204,21 @@ def sigmoid(x):
204204

205205

206206
@pytest.mark.parametrize('n_data', [1, 60])
207-
@pytest.mark.parametrize('layer, shape', [(Conv1D(8, 3), (None, 20, 1)),
208-
(Conv3D(16, 7), (1, 20, 20, 20, 1))])
209-
def test_cdropout_invalid_layer(layer, shape, n_data):
210-
"""To be replaced with a real function test, if implemented.
211-
"""
212-
with pytest.raises(ValueError):
213-
layer_test(ConcreteDropout,
214-
kwargs={'layer': layer,
215-
'n_data': n_data},
216-
input_shape=shape)
217-
218-
219-
@pytest.mark.parametrize('n_data', [1, 60])
220-
@pytest.mark.parametrize('layer, shape', [(Conv2D(8, 3), (None, 12, 12, 3)),
221-
(Conv2D(16, 7), (1, 12, 12, 3))])
222-
def test_cdropout_valid_layer(layer, shape, n_data):
223-
"""Original layer test with valid parameters.
207+
@pytest.mark.parametrize('layer, args, shape', [(Dense, (2,), (None, 6)),
208+
(Conv1D, (4, 3), (None, 6, 1)),
209+
(Conv2D, (8, 7), (None, 12, 12, 3)),
210+
(Conv3D, (16, 3), (1, 6, 6, 6, 1))])
211+
def test_cdropout_valid_layer(layer, args, shape, n_data):
212+
"""Original layer test with a variety of different valid parameters.
224213
"""
225214
layer_test(ConcreteDropout,
226-
kwargs={'layer': layer,
215+
kwargs={'layer': layer(*args),
227216
'n_data': n_data},
228217
input_shape=shape)
229218

219+
if K.backend() == 'tensorflow' or K.backend() == 'cntk':
220+
K.clear_session()
221+
230222

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

0 commit comments

Comments
 (0)