-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathautoencoder.py
249 lines (208 loc) · 10.1 KB
/
autoencoder.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
import argparse
import sys
sys.path.append('..')
import numpy as np
import pandas as pd
from keras import layers, optimizers, losses, metrics
from keras.models import Sequential
from keras import Model
from keras.optimizers import RMSprop
from keras.models import load_model
from sklearn.model_selection import train_test_split
from keras.layers.convolutional import Conv2D
from keras.layers.normalization import BatchNormalization
from keras.layers import MaxPooling2D
from keras.layers import UpSampling2D
from keras import Input
from keras.models import load_model
from matplotlib import pyplot as plt
import tensorflow as tf
from common.mnist_parser import *
from common.utils import *
from Autoencoder.encoder import *
from Autoencoder.decoder import *
# try:
# import hiplot as hip
# except:
# install('hiplot')
try:
import hiplot as hip
except:
print("Hiplot can not be installed, please install it using pip install hiplot")
import webbrowser
# Main function of the autoencoder
"""
FUNCTION USAGE: The main function is given a path of a file containing the
MNINT dataset, and tries to apply autoencoding for those images in the dataset.
This is an expiramental approach with respect to the hyperparameters of the
problem, thus the program will run many loops, train many models, and plot
the loss function results, until the user is satisfied by the output, and selects
to save that model for later usage.
"""
def main():
# create a parser in order to obtain the arguments
parser = argparse.ArgumentParser(description='Create a NN for autoencoding a set of images')
# the oonly argument that we want is -d
parser.add_argument('-d', '--dataset', action='store', default=None, metavar='', help='Relative path to the dataset')
# parse the arguments
args = parser.parse_args()
print("------PARSING THE DATA.....------")
# parse the MNIST dataset and obtain its rows and columns
dataset, rows, columns = parse_X(args.dataset)
# define the shape of the images that we are going to use
input_img = Input(shape=(rows, columns, 1))
# # split the dataset in order to check the model's behaviour
train_X, valid_X, train_ground, valid_ground = train_test_split(dataset, dataset, test_size=0.2, random_state=13)
# normalize all values between 0 and 1
train_X = train_X.astype('float32') / 255.
valid_X = valid_X.astype('float32') / 255.
# reshape the train and validation matrices into 28x28x1, due to an idiomorphy of the keras convolution.
train_X = np.reshape(train_X, (len(train_X), rows, columns, 1))
valid_X = np.reshape(valid_X, (len(valid_X), rows, columns, 1))
# list to keep all of our models
models_list = []
plots = 0
#boolean variable to exit the program
offside = False
# run until the user decides to break
while (offside == False):
# get the hyperparameters from the user
conv_layers = int(input("Give the number of convolution layers\n"))
conv_filter_size = int(input("Give the size of each convolution filter\n"))
n_conv_filters_per_layer = int(input("Give the number of convolution filters per layer\n"))
epochs = int(input("Give the number of epochs\n"))
batch_size = int(input("Give the batch size\n"))
print ("---TRYING TO RUN THE AUTOENCODER WITH THE FOLLOWING PARAMETERS: \nconv_layers ", conv_layers, \
" conv_filter_size: ", conv_filter_size, " n_conv_filters_per_layer: ", n_conv_filters_per_layer, \
" epochs: ", epochs, " batch_size: ", batch_size)
try:
# the autoencoder is a keras model class, consisted of an encoder and a decoder
autoencoder = Model(input_img, decoder(encoder(input_img, conv_layers, conv_filter_size, n_conv_filters_per_layer)))
# compile the model
# theory has shown that the best optimizer for the mnist dataset is the following
autoencoder.compile(loss='mean_squared_error', optimizer = RMSprop(lr=0.001, rho=0.9, epsilon=1e-08, decay=0.0), metrics=['accuracy'])
# fit the problem in order to check its behaviour
auto_train = autoencoder.fit(train_X, train_X, batch_size=batch_size, epochs=epochs, verbose=1, validation_data=(valid_X, valid_X))
# create a dictionary of the model plus some info in order to save it to the models' list
model_plus_info = {'full_model': autoencoder, 'epochs': epochs, 'batch_size': batch_size,\
'convolution layers': conv_layers, 'convolution filter size ': conv_filter_size,\
'number of conv. filters per layer': n_conv_filters_per_layer}
models_list.append(model_plus_info)
except:
# an error has occured, but we dont want to exit the program
print("Chosen hyperparameters caused an error. Please select others")
# ask the user for new input
while 1:
choice = int(input("Experiment completed! Choose one of the following options to procced: \n \
1 - Repeat the expirement with different hyperparameters\n \
2 - Print the plots gathered from the expirement\n \
3 - Save the model and exit\n \
4 - Load a pre-trained model\n"))
if (choice == 1):
break
elif (choice == 2):
if (len(models_list) > 0):
# Get the last model from the list
last_model = models_list[-1]
model = last_model["full_model"]
batch_size = last_model["batch_size"]
conv_layers = last_model["convolution layers"]
conv_filter_size = last_model["convolution filter size "]
n_conv_filters_per_layer = last_model["number of conv. filters per layer"]
accuracy = model.history.history['accuracy']
if len(accuracy) > 1:
print("\n------------------TRAINED MODEL METRICS----------------------")
# Loss plot
plt.figure()
plt.xlabel('Epochs')
plt.ylabel('MSE loss')
title = print(" Training/validation loss iconv_layers: " + str(conv_layers) + \
" conv_filter_size: " + str(conv_filter_size) + \
" n_conv_filters_per_layer: " + str(n_conv_filters_per_layer) + \
" epochs: " + str(epochs) + " batch_size: " + str(batch_size))
plt.title(title)
plt.plot(model.history.history['loss'], label = 'Training loss')
plt.plot(model.history.history['val_loss'], label = 'Validation loss')
plt.legend(loc="upper right")
plt.legend()
# path to save the plot image
plot_path = "loss_plot_" + str(conv_layers) + "_" + str(conv_filter_size) + "_" + str(n_conv_filters_per_layer) + ".png"
# save the image
plt.savefig(plot_path)
plt.show()
# Accuracy plot
plt.figure()
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
title = print(" Training/validation accuracy iconv_layers: " + str(conv_layers) + \
" conv_filter_size: " + str(conv_filter_size) + \
" n_conv_filters_per_layer: " + str(n_conv_filters_per_layer) + \
" epochs: " + str(epochs) + " batch_size: " + str(batch_size))
plt.title(title)
plt.plot(model.history.history['accuracy'], label = 'Training accuracy')
plt.plot(model.history.history['val_accuracy'], label = 'Validation accuracy')
plt.legend(loc="lower right")
plt.legend()
# path to save the plot image
plot_path = "accuracy_plot_" + str(conv_layers) + "_" + str(conv_filter_size) + "_" + str(n_conv_filters_per_layer) + ".png"
# save the image
plt.savefig(plot_path)
plt.show()
if (len(models_list) > 1):
print("\n--------------- ALL TRAINED MODElS METRICS-----------------\n")
"""
Using hiPlot to create a high dimensional plot of our models' hyperparameters
"""
plotting_dict_list = []
for m in models_list:
m["loss"] = round(m['full_model'].history.history['loss'][-1], 4)
m["accuracy"] = round(m['full_model'].history.history['accuracy'][-1], 4)
plotting_dict_list.append(dict(list(m.items())[1:]))
try:
html_str = hip.Experiment.from_iterable(plotting_dict_list).to_html(force_full_width=True)
# open a file to save the html containing the plot
f_name = "hiplot_result_" + str(plots) + '.html'
# increase the plot variable
plots += 1
f = open(f_name, "w")
f.write(html_str)
f.close()
# pop-up in google chrome
webbrowser.get('/usr/bin/google-chrome %s').open(f_name)
except:
print("HiPlot not installed, hi-dimensional plot can not be created")
else :
print("There is only one model, train an other one too to compare...\n")
continue
elif (choice == 3):
# demand a datapath to save the model
path = input("Give the path and the name of the file to save the model\n")
autoencoder.save(path + ".h5", save_format='h5')
# break the loop: model training is finished
offside = True
break
elif (choice == 4):
# Get the model info
path = input("Give the path and the name of the model you want to load\n")
conv_layers = int(input("Give the number of convolutional layers that were used to train the model\n"))
conv_filter_size = int(input("Give the conv_filter_size that was used to train the model\n"))
n_conv_filters_per_layer = int(input("Give the number of convolution filters per layer that were used to train the model\n"))
epochs = int(input("Give the number of epochs that were used to train the model\n"))
batch_size = int(input("Give the batch size that was used to train the model\n"))
# load the pre-trained model
autoencoder = load_model(path)
autoencoder.compile(loss='mean_squared_error', optimizer = RMSprop(lr=0.001, rho=0.9, epsilon=1e-08, decay=0.0), metrics=['accuracy'])
# fit the problem one time in order to get its accuracy and errors
auto_train = autoencoder.fit(train_X, train_X, batch_size=batch_size, epochs=1, verbose=1, validation_data=(valid_X, valid_X))
# create a dictionary of the model plus some info in order to save it to the models' list
model_plus_info = {'full_model': autoencoder, 'epochs': epochs, 'batch_size': batch_size,\
'convolution layers': conv_layers, 'convolution filter size ': conv_filter_size,\
'number of conv. filters per layer': n_conv_filters_per_layer}
# append the model in the models' list
models_list.append(model_plus_info)
else:
print("Choose one of the default values")
continue
# Main function of the autoencoder
if __name__ == "__main__":
main()