Completed
Push — master ( 7751f9...ca34ad )
by Dafne van
07:15
created

generate_CNN_hyperparameter_set()   A

Complexity

Conditions 1

Size

Total Lines 47

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 5
Bugs 1 Features 0
Metric Value
cc 1
dl 0
loc 47
ccs 6
cts 6
cp 1
crap 1
rs 9.0303
c 5
b 1
f 0
1 1
from keras.models import Sequential
2 1
from keras.layers import Dense, Activation, Convolution1D, Lambda, \
3
    Convolution2D, Flatten, \
4
    Reshape, LSTM, Dropout, TimeDistributed, BatchNormalization
5 1
from keras.regularizers import l2
6 1
from keras.optimizers import Adam
7 1
import numpy as np
8
9
10 1
def generate_models(
11
        x_shape, number_of_classes, number_of_models=5, model_type=None,
12
        cnn_min_layers=1, cnn_max_layers=10,
13
        cnn_min_filters=10, cnn_max_filters=100,
14
        cnn_min_fc_nodes=10, cnn_max_fc_nodes=2000,
15
        deepconvlstm_min_conv_layers=1, deepconvlstm_max_conv_layers=10,
16
        deepconvlstm_min_conv_filters=10, deepconvlstm_max_conv_filters=100,
17
        deepconvlstm_min_lstm_layers=1, deepconvlstm_max_lstm_layers=5,
18
        deepconvlstm_min_lstm_dims=10, deepconvlstm_max_lstm_dims=100,
19
        low_lr=1, high_lr=4, low_reg=1, high_reg=4
20
):
21
    """
22
    Generate one or multiple Keras models with random hyperparameters.
23
24
    Parameters
25
    ----------
26
    x_shape
27
        Shape of the input dataset: (num_samples, num_timesteps, num_channels)
28
    number_of_classes
29
        Number of classes for classification task
30
    number_of_models
31
        Number of models to generate
32
    model_type : str (optional)
33
        Type of model to build: 'CNN' or 'DeepConvLSTM'.
34
        Default option None generates both models.
35
    cnn_min_layers : int
36
        minimum of Conv layers in CNN model
37
    cnn_max_layers : int
38
        maximum of Conv layers in CNN model
39
    cnn_min_filters : int
40
        minimum number of filters per Conv layer in CNN model
41
    cnn_max_filters : int
42
        maximum number of filters per Conv layer in CNN model
43
    cnn_min_fc_nodes : int
44
        minimum number of hidden nodes per Dense layer in CNN model
45
    cnn_max_fc_nodes : int
46
        maximum number of hidden nodes per Dense layer in CNN model
47
    deepconvlstm_min_conv_layers : int
48
        minimum number of Conv layers in DeepConvLSTM model
49
    deepconvlstm_max_conv_layers : int
50
        maximum number of Conv layers in DeepConvLSTM model
51
    deepconvlstm_min_conv_filters : int
52
        minimum number of filters per Conv layer in DeepConvLSTM model
53
    deepconvlstm_max_conv_filters : int
54
        maximum number of filters per Conv layer in DeepConvLSTM model
55
    deepconvlstm_min_lstm_layers : int
56
        minimum number of Conv layers in DeepConvLSTM model
57
    deepconvlstm_max_lstm_layers : int
58
        maximum number of Conv layers in DeepConvLSTM model
59
    deepconvlstm_min_lstm_dims : int
60
        minimum number of hidden nodes per LSTM layer in DeepConvLSTM model
61
    deepconvlstm_max_lstm_dims : int
62
        maximum number of hidden nodes per LSTM layer in DeepConvLSTM model
63
    low_lr : float
64
        minimum of log range for learning rate: learning rate is sampled
65
        between `10**(-low_reg)` and `10**(-high_reg)`
66
    high_lr : float
67
        maximum  of log range for learning rate: learning rate is sampled
68
        between `10**(-low_reg)` and `10**(-high_reg)`
69
    low_reg : float
70
        minimum  of log range for regularization rate: regularization rate is
71
        sampled between `10**(-low_reg)` and `10**(-high_reg)`
72
    high_reg : float
73
        maximum  of log range for regularization rate: regularization rate is
74
        sampled between `10**(-low_reg)` and `10**(-high_reg)`
75
76
    Returns
77
    -------
78
    List of compiled models
79
    """
80 1
    models = []
81 1
    for _ in range(0, number_of_models):
82 1
        if model_type is None:  # random model choice:
83 1
            current_model_type = 'CNN' if np.random.random(
84
            ) < 0.5 else 'DeepConvLSTM'
85
        else:  # user-defined model choice:
86
            current_model_type = model_type
87 1
        generate_model = None
88 1
        if current_model_type == 'CNN':
89 1
            generate_model = generate_CNN_model  # generate_model is a function
90 1
            hyperparameters = generate_CNN_hyperparameter_set(
91
                min_layers=cnn_min_layers, max_layers=cnn_max_layers,
92
                min_filters=cnn_min_filters, max_filters=cnn_max_filters,
93
                min_fc_nodes=cnn_min_fc_nodes, max_fc_nodes=cnn_max_fc_nodes,
94
                low_lr=low_lr, high_lr=high_lr, low_reg=low_reg,
95
                high_reg=high_reg)
96 1
        if current_model_type == 'DeepConvLSTM':
97
            generate_model = generate_DeepConvLSTM_model
98
            hyperparameters = generate_DeepConvLSTM_hyperparameter_set(
99
                min_conv_layers=deepconvlstm_min_conv_layers,
100
                max_conv_layers=deepconvlstm_max_conv_layers,
101
                min_conv_filters=deepconvlstm_min_conv_filters,
102
                max_conv_filters=deepconvlstm_max_conv_filters,
103
                min_lstm_layers=deepconvlstm_min_lstm_layers,
104
                max_lstm_layers=deepconvlstm_max_lstm_layers,
105
                min_lstm_dims=deepconvlstm_min_lstm_dims,
106
                max_lstm_dims=deepconvlstm_max_lstm_dims,
107
                low_lr=low_lr, high_lr=high_lr, low_reg=low_reg,
108
                high_reg=high_reg)
109 1
        models.append(
110
            (generate_model(x_shape, number_of_classes, **hyperparameters),
111
             hyperparameters, current_model_type))
112 1
    return models
113
114
115 1
def generate_DeepConvLSTM_model(
0 ignored issues
show
Coding Style Naming introduced by
The name generate_DeepConvLSTM_model does not conform to the function naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
116
        x_shape, class_number, filters, lstm_dims, learning_rate=0.01,
117
        regularization_rate=0.01):
118
    """
119
    Generate a model with convolution and LSTM layers.
120
    See Ordonez et al., 2016, http://dx.doi.org/10.3390/s16010115
121
122
    Parameters
123
    ----------
124
    x_shape : tuple
125
        Shape of the input dataset: (num_samples, num_timesteps, num_channels)
126
    class_number : int
127
        Number of classes for classification task
128
    filters : list of ints
129
        number of filters for each convolutional layer
130
    lstm_dims : list of ints
131
        number of hidden nodes for each LSTM layer
132
    learning_rate : float
133
    regularization_rate : float
134
135
    Returns
136
    -------
137
    The compiled Keras model
138
    """
139 1
    dim_length = x_shape[1]  # number of samples in a time series
140 1
    dim_channels = x_shape[2]  # number of channels
141 1
    output_dim = class_number  # number of classes
142 1
    weightinit = 'lecun_uniform'  # weight initialization
143 1
    model = Sequential()  # initialize model
144 1
    model.add(BatchNormalization(input_shape=(dim_length, dim_channels)))
145
    # reshape a 2 dimensional array per file/person/object into a
146
    # 3 dimensional array
147 1
    model.add(
148
        Reshape(target_shape=(1, dim_length, dim_channels)))
149 1
    for filt in filters:
150
        # filt: number of filters used in a layer
151
        # filters: vector of filt values
152 1
        model.add(
153
            Convolution2D(filt, nb_row=3, nb_col=1, border_mode='same',
154
                          W_regularizer=l2(regularization_rate),
155
                          init=weightinit))
156 1
        model.add(BatchNormalization())
157 1
        model.add(Activation('relu'))
158
    # reshape 3 dimensional array back into a 2 dimensional array,
159
    # but now with more dept as we have the the filters for each channel
160 1
    model.add(Reshape(target_shape=(dim_length, filters[-1] * dim_channels)))
161
162 1
    for lstm_dim in lstm_dims:
163 1
        model.add(LSTM(output_dim=lstm_dim, return_sequences=True,
164
                       activation='tanh'))
165
166 1
    model.add(Dropout(0.5))  # dropout before the dense layer
167
    # set up final dense layer such that every timestamp is given one
168
    # classification
169 1
    model.add(
170
        TimeDistributed(
171
            Dense(output_dim, W_regularizer=l2(regularization_rate))))
172 1
    model.add(Activation("softmax"))
173
    # Final classification layer - per timestep
174 1
    model.add(Lambda(lambda x: x[:, -1, :], output_shape=[output_dim]))
175
176 1
    model.compile(loss='categorical_crossentropy',
177
                  optimizer=Adam(lr=learning_rate),
178
                  metrics=['accuracy'])
179
180 1
    return model
181
182
183 1
def generate_CNN_model(x_shape, class_number, filters, fc_hidden_nodes,
0 ignored issues
show
Coding Style Naming introduced by
The name generate_CNN_model does not conform to the function naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
184
                       learning_rate=0.01, regularization_rate=0.01):
185
    """
186
    Generate a convolutional neural network (CNN) model.
187
188
    The compiled Keras model is returned.
189
190
    Parameters
191
    ----------
192
    x_shape : tuple
193
        Shape of the input dataset: (num_samples, num_timesteps, num_channels)
194
    class_number : int
195
        Number of classes for classification task
196
    filters : list of ints
197
        number of filters for each convolutional layer
198
    fc_hidden_nodes : int
199
        number of hidden nodes for the hidden dense layer
200
    learning_rate : float
201
    regularization_rate : float
202
203
    Returns
204
    -------
205
    The compiled Keras model
206
    """
207 1
    dim_length = x_shape[1]  # number of samples in a time series
208 1
    dim_channels = x_shape[2]  # number of channels
209 1
    outputdim = class_number  # number of classes
210 1
    weightinit = 'lecun_uniform'  # weight initialization
211 1
    model = Sequential()
212 1
    model.add(
213
        BatchNormalization(
214
            input_shape=(
215
                dim_length,
216
                dim_channels),
217
            mode=0,
218
            axis=2))
219 1
    for filter_number in filters:
220 1
        model.add(Convolution1D(filter_number, 3, border_mode='same',
221
                                W_regularizer=l2(regularization_rate),
222
                                init=weightinit))
223 1
        model.add(BatchNormalization())
224 1
        model.add(Activation('relu'))
225 1
    model.add(Flatten())
226 1
    model.add(Dense(output_dim=fc_hidden_nodes,
227
                    W_regularizer=l2(regularization_rate),
228
                    init=weightinit))  # Fully connected layer
229 1
    model.add(Activation('relu'))  # Relu activation
230 1
    model.add(Dense(output_dim=outputdim, init=weightinit))
231 1
    model.add(BatchNormalization())
232 1
    model.add(Activation("softmax"))  # Final classification layer
233
234 1
    model.compile(loss='categorical_crossentropy',
235
                  optimizer=Adam(lr=learning_rate),
236
                  metrics=['accuracy'])
237
238 1
    return model
239
240
241 1
def generate_CNN_hyperparameter_set(min_layers=1, max_layers=10,
0 ignored issues
show
Coding Style Naming introduced by
The name generate_CNN_hyperparameter_set does not conform to the function naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
242
                                    min_filters=10, max_filters=100,
243
                                    min_fc_nodes=10, max_fc_nodes=2000,
244
                                    low_lr=1, high_lr=4, low_reg=1,
245
                                    high_reg=4):
246
    """ Generate a hyperparameter set that define a CNN model.
247
248
    Parameters
249
    ----------
250
    min_layers : int
251
        minimum of Conv layers
252
    max_layers : int
253
        maximum of Conv layers
254
    min_filters : int
255
        minimum number of filters per Conv layer
256
    max_filters : int
257
        maximum number of filters per Conv layer
258
    min_fc_nodes : int
259
        minimum number of hidden nodes per Dense layer
260
    max_fc_nodes : int
261
        maximum number of hidden nodes per Dense layer
262
    low_lr : float
263
        minimum of log range for learning rate: learning rate is sampled
264
        between `10**(-low_reg)` and `10**(-high_reg)`
265
    high_lr : float
266
        maximum  of log range for learning rate: learning rate is sampled
267
        between `10**(-low_reg)` and `10**(-high_reg)`
268
    low_reg : float
269
        minimum  of log range for regularization rate: regularization rate is
270
        sampled between `10**(-low_reg)` and `10**(-high_reg)`
271
    high_reg : float
272
        maximum  of log range for regularization rate: regularization rate is
273
        sampled between `10**(-low_reg)` and `10**(-high_reg)`
274
275
    Returns
276
    ----------
277
    hyperparameters : dict
278
        parameters for a CNN model
279
    """
280 1
    hyperparameters = generate_base_hyper_parameter_set(
281
        low_lr, high_lr, low_reg, high_reg)
282 1
    number_of_layers = np.random.randint(min_layers, max_layers + 1)
283 1
    hyperparameters['filters'] = np.random.randint(
284
        min_filters, max_filters + 1, number_of_layers)
285 1
    hyperparameters['fc_hidden_nodes'] = np.random.randint(
286
        min_fc_nodes, max_fc_nodes + 1)
287 1
    return hyperparameters
288
289
290 1
def generate_DeepConvLSTM_hyperparameter_set(
0 ignored issues
show
Coding Style Naming introduced by
The name generate_DeepConvLSTM_hyperparameter_set does not conform to the function naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
291
        min_conv_layers=1, max_conv_layers=10,
292
        min_conv_filters=10, max_conv_filters=100,
293
        min_lstm_layers=1, max_lstm_layers=5,
294
        min_lstm_dims=10, max_lstm_dims=100,
295
        low_lr=1, high_lr=4, low_reg=1, high_reg=4):
296
    """ Generate a hyperparameter set that defines a DeepConvLSTM model.
297
298
    Parameters
299
    ----------
300
    min_conv_layers : int
301
        minimum number of Conv layers in DeepConvLSTM model
302
    max_conv_layers : int
303
        maximum number of Conv layers in DeepConvLSTM model
304
    min_conv_filters : int
305
        minimum number of filters per Conv layer in DeepConvLSTM model
306
    max_conv_filters : int
307
        maximum number of filters per Conv layer in DeepConvLSTM model
308
    min_lstm_layers : int
309
        minimum number of Conv layers in DeepConvLSTM model
310
    max_lstm_layers : int
311
        maximum number of Conv layers in DeepConvLSTM model
312
    min_lstm_dims : int
313
        minimum number of hidden nodes per LSTM layer in DeepConvLSTM model
314
    max_lstm_dims : int
315
        maximum number of hidden nodes per LSTM layer in DeepConvLSTM model
316
    low_lr : float
317
        minimum of log range for learning rate: learning rate is sampled
318
        between `10**(-low_reg)` and `10**(-high_reg)`
319
    high_lr : float
320
        maximum  of log range for learning rate: learning rate is sampled
321
        between `10**(-low_reg)` and `10**(-high_reg)`
322
    low_reg : float
323
        minimum  of log range for regularization rate: regularization rate is
324
        sampled between `10**(-low_reg)` and `10**(-high_reg)`
325
    high_reg : float
326
        maximum  of log range for regularization rate: regularization rate is
327
        sampled between `10**(-low_reg)` and `10**(-high_reg)`
328
329
    Returns
330
    ----------
331
    hyperparameters: dict
332
        hyperparameters for a DeepConvLSTM model
333
    """
334 1
    hyperparameters = generate_base_hyper_parameter_set(
335
        low_lr, high_lr, low_reg, high_reg)
336 1
    number_of_conv_layers = np.random.randint(
337
        min_conv_layers, max_conv_layers + 1)
338 1
    hyperparameters['filters'] = np.random.randint(
339
        min_conv_filters, max_conv_filters + 1, number_of_conv_layers)
340 1
    number_of_lstm_layers = np.random.randint(
341
        min_lstm_layers, max_lstm_layers + 1)
342 1
    hyperparameters['lstm_dims'] = np.random.randint(
343
        min_lstm_dims, max_lstm_dims + 1, number_of_lstm_layers)
344 1
    return hyperparameters
345
346
347 1
def generate_base_hyper_parameter_set(
0 ignored issues
show
Coding Style Naming introduced by
The name generate_base_hyper_parameter_set does not conform to the function naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
348
        low_lr=1,
349
        high_lr=4,
350
        low_reg=1,
351
        high_reg=4):
352
    """ Generate a base set of hyperparameters that are necessary for any
353
    model, but sufficient for none.
354
355
    Parameters
356
    ----------
357
    low_lr : float
358
        minimum of log range for learning rate: learning rate is sampled
359
        between `10**(-low_reg)` and `10**(-high_reg)`
360
    high_lr : float
361
        maximum  of log range for learning rate: learning rate is sampled
362
        between `10**(-low_reg)` and `10**(-high_reg)`
363
    low_reg : float
364
        minimum  of log range for regularization rate: regularization rate is
365
        sampled between `10**(-low_reg)` and `10**(-high_reg)`
366
    high_reg : float
367
        maximum  of log range for regularization rate: regularization rate is
368
        sampled between `10**(-low_reg)` and `10**(-high_reg)`
369
370
    Returns
371
    -------
372
    hyperparameters : dict
373
        basis hyperpameters
374
    """
375 1
    hyperparameters = {}
376 1
    hyperparameters['learning_rate'] = get_learning_rate(low_lr, high_lr)
377 1
    hyperparameters['regularization_rate'] = get_regularization(
378
        low_reg, high_reg)
379 1
    return hyperparameters
380
381
382 1
def get_learning_rate(low=1, high=4):
383
    """ Return random learning rate 10^-n where n is sampled uniformly between
384
    low and high bounds.
385
386
    Parameters
387
    ----------
388
    low : float
389
        low bound
390
    high : float
391
        high bound
392
    """
393 1
    result = 10 ** (-np.random.uniform(low, high))
394 1
    return result
395
396
397 1
def get_regularization(low=1, high=4):
398
    """ Return random regularization rate 10^-n where n is sampled uniformly
399
    between low and high bounds.
400
401
    Parameters
402
    ----------
403
    low : float
404
        low bound
405
    high : float
406
        high bound
407
    """
408
    return 10 ** (-np.random.uniform(low, high))
409