Completed
Push — master ( bdf180...a29c6d )
by
unknown
16:21
created

storetrainhist2json()   B

Complexity

Conditions 4

Size

Total Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 4.0218

Importance

Changes 0
Metric Value
cc 4
dl 0
loc 31
ccs 16
cts 18
cp 0.8889
crap 4.0218
rs 8.5806
c 0
b 0
f 0
1
'''
2
 Summary:
3
 Function generate_models from modelgen.py generates and compiles models
4
 Function train_models_on_samples trains those models
5
 Function plotTrainingProcess plots the training process
6
 Function find_best_architecture is wrapper function that combines
7
 these steps
8
 Example function calls in 'EvaluateDifferentModels.ipynb'
9
'''
10 1
import numpy as np
11 1
from matplotlib import pyplot as plt
12 1
from . import modelgen
13 1
from sklearn import neighbors, metrics
14 1
import warnings
15 1
import json
16 1
import os
17
18 1
def train_models_on_samples(X_train, y_train, X_val, y_val, models,
0 ignored issues
show
Coding Style Naming introduced by
The name X_train does not conform to the argument naming conventions ([a-z_][a-z0-9_]{1,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...
Coding Style Naming introduced by
The name X_val does not conform to the argument naming conventions ([a-z_][a-z0-9_]{1,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...
19
                            nr_epochs=5, subset_size=100, verbose=True,
20
                            outputpath=None):
21
    """
22
    Given a list of compiled models, this function trains
23
    them all on a subset of the train data. If the given size of the subset is
24
    smaller then the size of the data, the complete data set is used.
25
    Parameters
26
    ----------
27
    X_train : numpy array of shape (num_samples, num_timesteps, num_channels)
28
        The input dataset for training
29
    y_train : numpy array of shape (num_samples, num_classes)
30
        The output classes for the train data, in binary format
31
    X_val : numpy array of shape (num_samples_val, num_timesteps, num_channels)
32
        The input dataset for validation
33
    y_val : numpy array of shape (num_samples_val, num_classes)
34
        The output classes for the validation data, in binary format
35
    models : list of model, params, modeltypes
36
        List of keras models to train
37
    nr_epochs : int, optional
38
        nr of epochs to use for training one model
39
    subset_size :
40
        The number of samples used from the complete train set
41
    subsize_set : int, optional
42
        number of samples to use from the training set for training these models
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...
43
    verbose : bool, optional
44
        flag for displaying verbose output
45
46
    Returns
47
    ----------
48
    histories : list of Keras History objects
49
        train histories for all models
50
    val_accuracies : list of floats
51
        validation accuraracies of the models
52
    val_losses : list of floats
53
        validation losses of the models
54
    """
55
    # if subset_size is smaller then X_train, this will work fine
56 1
    X_train_sub = X_train[:subset_size, :, :]
0 ignored issues
show
Coding Style Naming introduced by
The name X_train_sub does not conform to the variable naming conventions ([a-z_][a-z0-9_]{1,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...
57 1
    y_train_sub = y_train[:subset_size, :]
58
59 1
    histories = []
60 1
    val_accuracies = []
61 1
    val_losses = []
62 1
    for model, params, model_types in models:
63 1
        history = model.fit(X_train_sub, y_train_sub,
64
                            nb_epoch=nr_epochs, batch_size=20,
65
                            # see comment on subsize_set
66
                            validation_data=(X_val, y_val),
67
                            verbose=verbose)
68 1
        histories.append(history)
69 1
        val_accuracies.append(history.history['val_acc'][-1])
70 1
        val_losses.append(history.history['val_loss'][-1])
71 1
        if outputpath is not None:
72
            storetrainhist2json(params, model_types, history.history, outputpath)
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (81/79).

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

Loading history...
73 1
    return histories, val_accuracies, val_losses
74
75
76 1
def storetrainhist2json(params, model_type, history, outputpath):
77
    """
78
    This function stores the model parameters, the loss and accuracy history
79
    of one model.
80
81
    Parameters
82
    ----------
83
    params : dictionary with parameters for one model
84
    model_type : Keras model object for one model
85
    history : dictionary with training history from one model
86
    outputpath : str of path where the json file needs to be stored
87
88
    """
89 1
    jsondata = params.copy()
90 1
    jsondata['filters'] = jsondata['filters'].tolist()
91 1
    jsondata['train_acc'] = history['acc'] #history.
92 1
    jsondata['train_loss'] = history['loss'] #history.
93 1
    jsondata['val_acc'] = history['val_acc'] #history.
94 1
    jsondata['val_loss'] = history['val_loss'] #history.
95 1
    jsondata['modeltype'] = model_type
96 1
    jsondata['modeltype'] = model_type
97 1
    filename = outputpath + '/modelshistory.json'
98 1
    if os.path.isfile(filename):
99
        with open(filename, 'r') as outfile:
100
            previousdata = json.load(outfile)
101
    else:
102 1
        previousdata = []
103 1
    previousdata.append(jsondata)
104 1
    print(jsondata)
105 1
    with open(filename, 'w') as outfile:
106 1
            json.dump(previousdata, outfile, sort_keys = True, indent = 4,ensure_ascii=False)
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (93/79).

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

Loading history...
Coding Style introduced by
The indentation here looks off. 8 spaces were expected, but 12 were found.
Loading history...
Coding Style introduced by
No space allowed around keyword argument assignment
json.dump(previousdata, outfile, sort_keys = True, indent = 4,ensure_ascii=False)
^
Loading history...
Coding Style introduced by
No space allowed around keyword argument assignment
json.dump(previousdata, outfile, sort_keys = True, indent = 4,ensure_ascii=False)
^
Loading history...
Coding Style introduced by
Exactly one space required after comma
json.dump(previousdata, outfile, sort_keys = True, indent = 4,ensure_ascii=False)
^
Loading history...
107
108
109 1
def plotTrainingProcess(history, name='Model', ax=None):
0 ignored issues
show
Coding Style Naming introduced by
The name plotTrainingProcess 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...
110
    """
111
    This function plots the loss and accuracy on the train and validation set,
112
    for each epoch in the history of one model.
113
114
    Parameters
115
    ----------
116
    history : keras History object for one model
117
        The history object of the training process corresponding to one model
118
119
    """
120
    if ax is None:
121
        fig, ax = plt.subplots()
122
    ax2 = ax.twinx()
123
    LN = len(history.history['val_loss'])
0 ignored issues
show
Coding Style Naming introduced by
The name LN does not conform to the variable naming conventions ([a-z_][a-z0-9_]{1,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...
124
    val_loss, = ax.plot(range(LN), history.history['val_loss'], 'g--',
125
                        label='validation loss')
126
    train_loss, = ax.plot(range(LN), history.history['loss'], 'g-',
127
                          label='train loss')
128
    val_acc, = ax2.plot(range(LN), history.history['val_acc'], 'b--',
129
                        label='validation accuracy')
130
    train_acc, = ax2.plot(range(LN), history.history['acc'], 'b-',
131
                          label='train accuracy')
132
    ax.set_xlabel('epoch')
133
    ax.set_ylabel('loss', color='g')
134
    ax2.set_ylabel('accuracy', color='b')
135
    plt.legend(handles=[val_loss, train_loss, val_acc, train_acc],
136
               loc=2, bbox_to_anchor=(1.1, 1))
137
    plt.title(name)
138
139
140 1
def find_best_architecture(X_train, y_train, X_val, y_val, verbose=True,
0 ignored issues
show
Coding Style Naming introduced by
The name X_train does not conform to the argument naming conventions ([a-z_][a-z0-9_]{1,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...
Coding Style Naming introduced by
The name X_val does not conform to the argument naming conventions ([a-z_][a-z0-9_]{1,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...
141
                           number_of_models=5, nr_epochs=5, subset_size=100,
142
                           outputpath=None, **kwargs
143
                           ):
144
    """
145
    Tries out a number of models on a subsample of the data,
146
    and outputs the best found architecture and hyperparameters.
147
148
    Parameters
149
    ----------
150
    X_train : numpy array of shape (num_samples, num_timesteps, num_channels)
151
        The input dataset for training
152
    y_train : numpy array of shape (num_samples, num_classes)
153
        The output classes for the train data, in binary format
154
    X_val : numpy array of shape (num_samples_val, num_timesteps, num_channels)
155
        The input dataset for validation
156
    y_val : numpy array of shape (num_samples_val, num_classes)
157
        The output classes for the validation data, in binary format
158
    verbose : bool, optional
159
        flag for displaying verbose output
160
    number_of_models : int
161
        The number of models to generate and test
162
    nr_epochs : int
163
        The number of epochs that each model is trained
164
    subset_size : int
165
        The size of the subset of the data that is used for finding the optimal architecture
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (92/79).

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

Loading history...
166
    **kwargs: key-value parameters
167
        parameters for generating the models (see docstring for modelgen.generate_models)
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (89/79).

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

Loading history...
168
169
    Returns
170
    ----------
171
    best_model : Keras model
172
        Best performing model, already trained on a small sample data set.
173
    best_params : dict
174
        Dictionary containing the hyperparameters for the best model
175
    best_model_type : str
176
        Type of the best model
177
    knn_acc : float
178
        accuaracy for kNN prediction on validation set
179
    """
180 1
    models = modelgen.generate_models(X_train.shape, y_train.shape[1],
181
                                      number_of_models=number_of_models,
182
                                      **kwargs)
183 1
    histories, val_accuracies, val_losses = train_models_on_samples(X_train,
184
                                                                    y_train,
185
                                                                    X_val,
186
                                                                    y_val,
187
                                                                    models,
188
                                                                    nr_epochs,
189
                                                                    subset_size=subset_size,
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (92/79).

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

Loading history...
190
                                                                    verbose=verbose,
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...
191
                                                                    outputpath=outputpath)
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (90/79).

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

Loading history...
192 1
    best_model_index = np.argmax(val_accuracies)
193 1
    best_model, best_params, best_model_type = models[best_model_index]
194 1
    knn_acc = kNN_accuracy(
195
        X_train[:subset_size, :, :], y_train[:subset_size, :], X_val, y_val)
196 1
    if verbose:
197
        for i in range(len(models)):  # <= now one plot per model, ultimately we
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...
198
            # may want all models in one plot to allow for direct comparison
199
            name = str(models[i][1])
200
            plotTrainingProcess(histories[i], name)
201
        print('Best model: model ', best_model_index)
202
        print('Model type: ', best_model_type)
203
        print('Hyperparameters: ', best_params)
204
        print('Accuracy on validation set: ', val_accuracies[best_model_index])
205
        print('Accuracy of kNN on validation set', knn_acc)
206
207 1
    if val_accuracies[best_model_index] < knn_acc:
208
        warnings.warn('Best model not better than kNN: ' +
209
                      str(val_accuracies[best_model_index]) + ' vs  ' +
210
                      str(knn_acc)
211
                      )
212 1
    return best_model, best_params, best_model_type, knn_acc
213
214
215 1
def kNN_accuracy(X_train, y_train, X_val, y_val, k=1):
0 ignored issues
show
Coding Style Naming introduced by
The name kNN_accuracy 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...
Coding Style Naming introduced by
The name X_train does not conform to the argument naming conventions ([a-z_][a-z0-9_]{1,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...
Coding Style Naming introduced by
The name X_val does not conform to the argument naming conventions ([a-z_][a-z0-9_]{1,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...
216
    """
217
    Performs k-Neigherst Neighbors and returns the accuracy score.
218
219
    Parameters
220
    ----------
221
    X_train : numpy array
222
        Train set of shape (num_samples, num_timesteps, num_channels)
223
    y_train : numpy array
224
        Class labels for train set
225
    X_val : numpy array
226
        Validation set of shape (num_samples, num_timesteps, num_channels)
227
    y_val : numpy array
228
        Class labels for validation set
229
    k : int
230
        number of neighbors to use for classifying
231
232
    Returns
233
    -------
234
    accuracy: float
235
        accuracy score on the validation set
236
    """
237 1
    num_samples, num_timesteps, num_channels = X_train.shape
238 1
    clf = neighbors.KNeighborsClassifier(k)
239 1
    clf.fit(
240
        X_train.reshape(
241
            num_samples,
242
            num_timesteps *
243
            num_channels),
244
        y_train)
245 1
    num_samples, num_timesteps, num_channels = X_val.shape
246 1
    val_predict = clf.predict(
247
        X_val.reshape(num_samples,
248
                      num_timesteps * num_channels))
249
    return metrics.accuracy_score(val_predict, y_val)
250