Completed
Push — master ( a63bb3...d33a20 )
by Christiaan
08:14
created

generate_DeepConvLSTM_model()   B

Complexity

Conditions 4

Size

Total Lines 45

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 4

Importance

Changes 6
Bugs 1 Features 3
Metric Value
cc 4
c 6
b 1
f 3
dl 0
loc 45
ccs 20
cts 20
cp 1
crap 4
rs 8.5806
1 1
from keras.models import Sequential
2 1
from keras.layers import Dense, Activation, Convolution1D, Flatten, MaxPooling1D, Lambda, Convolution2D, Flatten, Reshape, LSTM, Dropout, TimeDistributed, Permute, BatchNormalization
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (182/79).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
3 1
from keras.regularizers import l2
4 1
from keras.optimizers import Adam
5 1
import numpy as np
6
7
8 1
def generate_models(x_shape, number_of_classes, number_of_models=5, model_type=None, **kwargs):
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (95/79).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
9
    """ Generate one or multiple Keras models with random (default), or predefined, hyperparameters."""
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (103/79).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
10 1
    models = []
11 1
    for _ in range(0, number_of_models):
12 1
        if model_type is None:  # random model choice:
13 1
            current_model_type = 'CNN' if np.random.random(
14
            ) < 0.5 else 'DeepConvLSTM'
15
        else:  # user-defined model choice:
16
            current_model_type = model_type
17
18 1
        if current_model_type == 'CNN':
19 1
            generate_model = generate_CNN_model  # object is a function
20 1
            generate_hyperparameter_set = generate_CNN_hyperparameter_set
21 1
        if current_model_type == 'DeepConvLSTM':
22
            generate_model = generate_DeepConvLSTM_model  # object is a function
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (80/79).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
23
            generate_hyperparameter_set = generate_DeepConvLSTM_hyperparameter_set
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (82/79).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
24 1
        hyperparameters = generate_hyperparameter_set(**kwargs)
25 1
        models.append(
26
            (generate_model(x_shape, number_of_classes, **hyperparameters), hyperparameters, current_model_type))
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (113/79).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
27 1
    return models
28
29
30 1
def generate_DeepConvLSTM_model(x_shape, class_number, filters, lstm_dims, learning_rate=0.01,
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (94/79).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
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...
31
                                regularization_rate=0.01):
32
    """
33
    Generate a model with convolution and LSTM layers.
34
    See Ordonez et al., 2016, http://dx.doi.org/10.3390/s16010115
35
36
    The compiled Keras model is returned.
37
    """
38 1
    dim_length = x_shape[1]  # number of samples in a time series
39 1
    dim_channels = x_shape[2]  # number of channels
40 1
    output_dim = class_number  # number of classes
41 1
    weightinit = 'lecun_uniform'  # weight initialization
42 1
    model = Sequential()  # initialize model
43 1
    model.add(BatchNormalization(input_shape=(dim_length, dim_channels)))
44
    # reshape a 2 dimensional array per file/person/object into a
45
    # 3 dimensional array
46 1
    model.add(
47
        Reshape(target_shape=(1, dim_length, dim_channels)))
48 1
    for filt in filters:
49
        # filt: number of filters used in a layer
50
        # filters: vector of filt values
51 1
        model.add(
52
            Convolution2D(filt, nb_row=3, nb_col=1, border_mode='same',
53
                          W_regularizer=l2(regularization_rate), init=weightinit))
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (82/79).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
54 1
        model.add(Activation('relu'))
55
    # reshape 3 dimensional array back into a 2 dimensional array,
56
    # but now with more dept as we have the the filters for each channel
57 1
    model.add(Reshape(target_shape=(dim_length, filters[-1] * dim_channels)))
58
59 1
    for lstm_dim in lstm_dims:
60 1
        model.add(LSTM(output_dim=lstm_dim, return_sequences=True,
61
                       activation='tanh'))
62
63 1
    model.add(Dropout(0.5))  # dropout before the dense layer
64
    # set up final dense layer such that every timestamp is given one classification
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (84/79).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
65 1
    model.add(TimeDistributed(Dense(output_dim, W_regularizer=l2(regularization_rate))))
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (88/79).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
66 1
    model.add(Activation("softmax"))
67
    # Final classification layer - per timestep
68 1
    model.add(Lambda(lambda x: x[:, -1, :], output_shape=[output_dim]))
69
70 1
    model.compile(loss='categorical_crossentropy',
71
                  optimizer=Adam(lr=learning_rate),
72
                  metrics=['accuracy'])
73
74 1
    return model
75
76
77 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...
78
                       learning_rate=0.01, regularization_rate=0.01):
79
    """
80
    Generate a convolutional neural network (CNN) model.
81
82
    The compiled Keras model is returned.
83
    """
84 1
    dim_length = x_shape[1]  # number of samples in a time series
85 1
    dim_channels = x_shape[2]  # number of channels
86 1
    outputdim = class_number  # number of classes
87 1
    weightinit = 'lecun_uniform'  # weight initialization
88 1
    model = Sequential()
89 1
    model.add(BatchNormalization(input_shape=(dim_length, dim_channels)))
90 1
    for filter_number in filters:
91 1
        model.add(Convolution1D(filter_number, 3, border_mode='same',
92
                                W_regularizer=l2(regularization_rate), init=weightinit))
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (88/79).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
93 1
        model.add(Activation('relu'))
94 1
    model.add(Flatten())
95 1
    model.add(Dense(output_dim=fc_hidden_nodes,
96
                    W_regularizer=l2(regularization_rate), init=weightinit))  # Fully connected layer
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (101/79).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
97 1
    model.add(Activation('relu'))  # Relu activation
98 1
    model.add(Dense(output_dim=outputdim, init=weightinit))
99 1
    model.add(Activation("softmax"))  # Final classification layer
100
101 1
    model.compile(loss='categorical_crossentropy',
102
                  optimizer=Adam(lr=learning_rate),
103
                  metrics=['accuracy'])
104
105 1
    return model
106
107
108 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...
109
                                    min_filters=10, max_filters=100,
110
                                    min_fc_nodes=10, max_fc_nodes=100):
111
    """ Generate a hyperparameter set that define a CNN model."""
112 1
    hyperparameters = generate_base_hyper_parameter_set()
113 1
    number_of_layers = np.random.randint(min_layers, max_layers)
114 1
    hyperparameters['filters'] = np.random.randint(
115
        min_filters, max_filters, number_of_layers)
116 1
    hyperparameters['fc_hidden_nodes'] = np.random.randint(
117
        min_fc_nodes, max_fc_nodes)
118 1
    return hyperparameters
119
120
121 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...
122
    min_conv_layers=1, max_conv_layers=10,
123
    min_conv_filters=10, max_conv_filters=100,
124
    min_lstm_layers=1, max_lstm_layers=5,
125
        min_lstm_dims=10, max_lstm_dims=100):
126
    """ Generate a hyperparameter set that defines a DeepConvLSTM model."""
127
    hyperparameters = generate_base_hyper_parameter_set()
128
    number_of_conv_layers = np.random.randint(min_conv_layers, max_conv_layers)
129
    hyperparameters['filters'] = np.random.randint(
130
        min_conv_filters, max_conv_filters, number_of_conv_layers)
131
    number_of_lstm_layers = np.random.randint(min_lstm_layers, max_lstm_layers)
132
    hyperparameters['lstm_dims'] = np.random.randint(
133
        min_lstm_dims, max_lstm_dims, number_of_lstm_layers)
134
    return hyperparameters
135
136
137 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...
138
    """ Generate a base set of hyperparameters that are necessary for any model, but sufficient for none."""
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (108/79).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
139 1
    hyperparameters = {}
140 1
    hyperparameters['learning_rate'] = get_learning_rate()
141 1
    hyperparameters['regularization_rate'] = get_regularization()
142 1
    return hyperparameters
143
144
145 1
def get_learning_rate(low=1, high=4):
146
    """ Return random learning rate 10^-n where n is sampled uniformly between low and high bounds."""
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (102/79).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
147 1
    result = 10 ** (-np.random.uniform(low, high))
148 1
    return result
149
150
151 1
def get_regularization(low=1, high=4):
152
    """ Return random regularization rate 10^-n where n is sampled uniformly between low and high bounds."""
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (108/79).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
153
    return 10**(-np.random.uniform(low, high))
154