Completed
Push — master ( 81cbcf...c2b817 )
by Christiaan
06:36
created

get_regularization()   A

Complexity

Conditions 1

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 3
Bugs 0 Features 1
Metric Value
cc 1
dl 0
loc 12
ccs 2
cts 2
cp 1
crap 1
rs 9.4285
c 3
b 0
f 1
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
        learning rate
134
    regularization_rate : float
135
        regularization rate
136
137
    Returns
138
    -------
139
    The compiled Keras model
140
    """
141 1
    dim_length = x_shape[1]  # number of samples in a time series
142 1
    dim_channels = x_shape[2]  # number of channels
143 1
    output_dim = class_number  # number of classes
144 1
    weightinit = 'lecun_uniform'  # weight initialization
145 1
    model = Sequential()  # initialize model
146 1
    model.add(BatchNormalization(input_shape=(dim_length, dim_channels)))
147
    # reshape a 2 dimensional array per file/person/object into a
148
    # 3 dimensional array
149 1
    model.add(
150
        Reshape(target_shape=(1, dim_length, dim_channels)))
151 1
    for filt in filters:
152
        # filt: number of filters used in a layer
153
        # filters: vector of filt values
154 1
        model.add(
155
            Convolution2D(filt, nb_row=3, nb_col=1, border_mode='same',
156
                          W_regularizer=l2(regularization_rate),
157
                          init=weightinit))
158 1
        model.add(BatchNormalization())
159 1
        model.add(Activation('relu'))
160
    # reshape 3 dimensional array back into a 2 dimensional array,
161
    # but now with more dept as we have the the filters for each channel
162 1
    model.add(Reshape(target_shape=(dim_length, filters[-1] * dim_channels)))
163
164 1
    for lstm_dim in lstm_dims:
165 1
        model.add(LSTM(output_dim=lstm_dim, return_sequences=True,
166
                       activation='tanh'))
167
168 1
    model.add(Dropout(0.5))  # dropout before the dense layer
169
    # set up final dense layer such that every timestamp is given one
170
    # classification
171 1
    model.add(
172
        TimeDistributed(
173
            Dense(output_dim, W_regularizer=l2(regularization_rate))))
174 1
    model.add(Activation("softmax"))
175
    # Final classification layer - per timestep
176 1
    model.add(Lambda(lambda x: x[:, -1, :], output_shape=[output_dim]))
177
178 1
    model.compile(loss='categorical_crossentropy',
179
                  optimizer=Adam(lr=learning_rate),
180
                  metrics=['accuracy'])
181
182 1
    return model
183
184
185 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...
186
                       learning_rate=0.01, regularization_rate=0.01):
187
    """
188
    Generate a convolutional neural network (CNN) model.
189
190
    The compiled Keras model is returned.
191
192
    Parameters
193
    ----------
194
    x_shape : tuple
195
        Shape of the input dataset: (num_samples, num_timesteps, num_channels)
196
    class_number : int
197
        Number of classes for classification task
198
    filters : list of ints
199
        number of filters for each convolutional layer
200
    fc_hidden_nodes : int
201
        number of hidden nodes for the hidden dense layer
202
    learning_rate : float
203
        learning rate
204
    regularization_rate : float
205
        regularization rate
206
207
    Returns
208
    -------
209
    The compiled Keras model
210
    """
211 1
    dim_length = x_shape[1]  # number of samples in a time series
212 1
    dim_channels = x_shape[2]  # number of channels
213 1
    outputdim = class_number  # number of classes
214 1
    weightinit = 'lecun_uniform'  # weight initialization
215 1
    model = Sequential()
216 1
    model.add(
217
        BatchNormalization(
218
            input_shape=(
219
                dim_length,
220
                dim_channels),
221
            mode=0,
222
            axis=2))
223 1
    for filter_number in filters:
224 1
        model.add(Convolution1D(filter_number, 3, border_mode='same',
225
                                W_regularizer=l2(regularization_rate),
226
                                init=weightinit))
227 1
        model.add(BatchNormalization())
228 1
        model.add(Activation('relu'))
229 1
    model.add(Flatten())
230 1
    model.add(Dense(output_dim=fc_hidden_nodes,
231
                    W_regularizer=l2(regularization_rate),
232
                    init=weightinit))  # Fully connected layer
233 1
    model.add(Activation('relu'))  # Relu activation
234 1
    model.add(Dense(output_dim=outputdim, init=weightinit))
235 1
    model.add(BatchNormalization())
236 1
    model.add(Activation("softmax"))  # Final classification layer
237
238 1
    model.compile(loss='categorical_crossentropy',
239
                  optimizer=Adam(lr=learning_rate),
240
                  metrics=['accuracy'])
241
242 1
    return model
243
244
245 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...
246
                                    min_filters=10, max_filters=100,
247
                                    min_fc_nodes=10, max_fc_nodes=2000,
248
                                    low_lr=1, high_lr=4, low_reg=1,
249
                                    high_reg=4):
250
    """ Generate a hyperparameter set that define a CNN model.
251
252
    Parameters
253
    ----------
254
    min_layers : int
255
        minimum of Conv layers
256
    max_layers : int
257
        maximum of Conv layers
258
    min_filters : int
259
        minimum number of filters per Conv layer
260
    max_filters : int
261
        maximum number of filters per Conv layer
262
    min_fc_nodes : int
263
        minimum number of hidden nodes per Dense layer
264
    max_fc_nodes : int
265
        maximum number of hidden nodes per Dense layer
266
    low_lr : float
267
        minimum of log range for learning rate: learning rate is sampled
268
        between `10**(-low_reg)` and `10**(-high_reg)`
269
    high_lr : float
270
        maximum  of log range for learning rate: learning rate is sampled
271
        between `10**(-low_reg)` and `10**(-high_reg)`
272
    low_reg : float
273
        minimum  of log range for regularization rate: regularization rate is
274
        sampled between `10**(-low_reg)` and `10**(-high_reg)`
275
    high_reg : float
276
        maximum  of log range for regularization rate: regularization rate is
277
        sampled between `10**(-low_reg)` and `10**(-high_reg)`
278
279
    Returns
280
    ----------
281
    hyperparameters : dict
282
        parameters for a CNN model
283
    """
284 1
    hyperparameters = generate_base_hyper_parameter_set(
285
        low_lr, high_lr, low_reg, high_reg)
286 1
    number_of_layers = np.random.randint(min_layers, max_layers + 1)
287 1
    hyperparameters['filters'] = np.random.randint(
288
        min_filters, max_filters + 1, number_of_layers)
289 1
    hyperparameters['fc_hidden_nodes'] = np.random.randint(
290
        min_fc_nodes, max_fc_nodes + 1)
291 1
    return hyperparameters
292
293
294 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...
295
        min_conv_layers=1, max_conv_layers=10,
296
        min_conv_filters=10, max_conv_filters=100,
297
        min_lstm_layers=1, max_lstm_layers=5,
298
        min_lstm_dims=10, max_lstm_dims=100,
299
        low_lr=1, high_lr=4, low_reg=1, high_reg=4):
300
    """ Generate a hyperparameter set that defines a DeepConvLSTM model.
301
302
    Parameters
303
    ----------
304
    min_conv_layers : int
305
        minimum number of Conv layers in DeepConvLSTM model
306
    max_conv_layers : int
307
        maximum number of Conv layers in DeepConvLSTM model
308
    min_conv_filters : int
309
        minimum number of filters per Conv layer in DeepConvLSTM model
310
    max_conv_filters : int
311
        maximum number of filters per Conv layer in DeepConvLSTM model
312
    min_lstm_layers : int
313
        minimum number of Conv layers in DeepConvLSTM model
314
    max_lstm_layers : int
315
        maximum number of Conv layers in DeepConvLSTM model
316
    min_lstm_dims : int
317
        minimum number of hidden nodes per LSTM layer in DeepConvLSTM model
318
    max_lstm_dims : int
319
        maximum number of hidden nodes per LSTM layer in DeepConvLSTM model
320
    low_lr : float
321
        minimum of log range for learning rate: learning rate is sampled
322
        between `10**(-low_reg)` and `10**(-high_reg)`
323
    high_lr : float
324
        maximum  of log range for learning rate: learning rate is sampled
325
        between `10**(-low_reg)` and `10**(-high_reg)`
326
    low_reg : float
327
        minimum  of log range for regularization rate: regularization rate is
328
        sampled between `10**(-low_reg)` and `10**(-high_reg)`
329
    high_reg : float
330
        maximum  of log range for regularization rate: regularization rate is
331
        sampled between `10**(-low_reg)` and `10**(-high_reg)`
332
333
    Returns
334
    ----------
335
    hyperparameters: dict
336
        hyperparameters for a DeepConvLSTM model
337
    """
338 1
    hyperparameters = generate_base_hyper_parameter_set(
339
        low_lr, high_lr, low_reg, high_reg)
340 1
    number_of_conv_layers = np.random.randint(
341
        min_conv_layers, max_conv_layers + 1)
342 1
    hyperparameters['filters'] = np.random.randint(
343
        min_conv_filters, max_conv_filters + 1, number_of_conv_layers)
344 1
    number_of_lstm_layers = np.random.randint(
345
        min_lstm_layers, max_lstm_layers + 1)
346 1
    hyperparameters['lstm_dims'] = np.random.randint(
347
        min_lstm_dims, max_lstm_dims + 1, number_of_lstm_layers)
348 1
    return hyperparameters
349
350
351 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...
352
        low_lr=1,
353
        high_lr=4,
354
        low_reg=1,
355
        high_reg=4):
356
    """ Generate a base set of hyperparameters that are necessary for any
357
    model, but sufficient for none.
358
359
    Parameters
360
    ----------
361
    low_lr : float
362
        minimum of log range for learning rate: learning rate is sampled
363
        between `10**(-low_reg)` and `10**(-high_reg)`
364
    high_lr : float
365
        maximum  of log range for learning rate: learning rate is sampled
366
        between `10**(-low_reg)` and `10**(-high_reg)`
367
    low_reg : float
368
        minimum  of log range for regularization rate: regularization rate is
369
        sampled between `10**(-low_reg)` and `10**(-high_reg)`
370
    high_reg : float
371
        maximum  of log range for regularization rate: regularization rate is
372
        sampled between `10**(-low_reg)` and `10**(-high_reg)`
373
374
    Returns
375
    -------
376
    hyperparameters : dict
377
        basis hyperpameters
378
    """
379 1
    hyperparameters = {}
380 1
    hyperparameters['learning_rate'] = get_learning_rate(low_lr, high_lr)
381 1
    hyperparameters['regularization_rate'] = get_regularization(
382
        low_reg, high_reg)
383 1
    return hyperparameters
384
385
386 1
def get_learning_rate(low=1, high=4):
387
    """ Return random learning rate 10^-n where n is sampled uniformly between
388
    low and high bounds.
389
390
    Parameters
391
    ----------
392
    low : float
393
        low bound
394
    high : float
395
        high bound
396
    """
397 1
    result = 10 ** (-np.random.uniform(low, high))
398 1
    return result
399
400
401 1
def get_regularization(low=1, high=4):
402
    """ Return random regularization rate 10^-n where n is sampled uniformly
403
    between low and high bounds.
404
405
    Parameters
406
    ----------
407
    low : float
408
        low bound
409
    high : float
410
        high bound
411
    """
412
    return 10 ** (-np.random.uniform(low, high))
413