-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.py
170 lines (137 loc) · 6.46 KB
/
main.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
# TensorFlow and tf.keras
import tensorflow as tf
import tensorflow_datasets as tfds
import os
# Helper libraries
import numpy as np
import matplotlib.pyplot as plt
def create_model(input_shape, output_units, hidden_units, filter_shape,
convolution_layers, dense_layers,
max_pooling=(2,2), batch_normalisation=False, dropout=False,
activation_type='relu',)->tf.keras.Sequential:
"""
Create and return a new sequential model with the specified architecture
This model will be suited for the task of image classification, or anything using a Convolutional network
This model will have the form of
convolution_layers number of Convd2D layers with hidden_units number of units(the first having input_shape)
optional maxPool2D layers and batchNormalisation layers
A flatten layer
dense_layers number of Dense layers
optional Dropout layers with dropout rate
A final Dense layer with output_units number of units (non-optional)
A Softmax layer to normalise the outputs
Params:
input_shape : tuple of integers
tuple of integers, does not include the sample axis, the data shape given to the model
output_units : integer
The shape of the output ie how many classes we are classifying
hidden_units : integer
How many units each hidden layer will have
filter_shape : tuple of integers
shape of filters to use in Conv2D layers
convolution_layers : integer
How many Conv2D layers to have (not including first input layer)
dense_layers : integer
How many Dense layers to include (not including final output Dense layer)
max_pooling : tuple of integers, optional
Dimension of pooling to use, default is (2,2)
batch_normalisation : Boolean, optional
Whether to have a batch_normalisation layer after each Conv2d layer
dropout : float, optional
False if no dropout layer, or a float between 0.0 and 1.0 for dropout rate after each Dense layer
activation_type : string, optional
The type of activation to use for each layer, default ReLu
"""
#Create the model
model = tf.keras.Sequential()
model._name = f'MODEL_{convolution_layers}CONVD-{filter_shape[0]}.{filter_shape[1]}_MAXPOOL-{max_pooling[0]}.{max_pooling[1]}_{"BATCHNORM_" if batch_normalisation else ""}{dense_layers}DENSE{"_DROPOUT-"+str(dropout) if dropout else ""}_UNITS-{hidden_units}'
#add the first convd layer
model.add(tf.keras.layers.Conv2D(hidden_units, filter_shape, activation=activation_type, input_shape=input_shape))
model.add(tf.keras.layers.MaxPool2D(max_pooling))
if batch_normalisation:
model.add(tf.keras.layers.BatchNormalization())
#add a convolutional layer for each required
for i in range(convolution_layers):
if batch_normalisation:
model.add(tf.keras.layers.BatchNormalization())
try:
model.add(tf.keras.layers.Conv2D(hidden_units, filter_shape, activation=activation_type))
model.add(tf.keras.layers.MaxPool2D(max_pooling))
except ValueError:
#if MaxPool breaks the model, just don't add it
pass
#Add the flatten layer
model.add(tf.keras.layers.Flatten())
#Add the dense layers
for i in range(dense_layers):
model.add(tf.keras.layers.Dense(hidden_units, activation=activation_type))
if dropout:
model.add(tf.keras.layers.Dropout(dropout))
#add the final dense layer and softmax
model.add(tf.keras.layers.Dense(output_units, activation=activation_type))
model.add(tf.keras.layers.Softmax())
model.compile(
optimizer="adam",
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=[tf.keras.metrics.SparseCategoricalAccuracy()],
)
return model
#import our data
(ds_train, ds_test), ds_info = tfds.load(
'mnist',
split=['train', 'test'],
shuffle_files=True,
as_supervised=True,
with_info=True,
)
#normalise the data to [0,1]
ds_train = ds_train.map(lambda image,label: (tf.cast(image, tf.float16) / 255., label), num_parallel_calls=tf.data.experimental.AUTOTUNE)
# cache dataset for better performance
ds_train = ds_train.cache()
#Shuffle the training data for true randomness at each epoch
ds_train = ds_train.shuffle(512)
#Batches after shuffling
ds_train = ds_train.batch(256)
#Finally, prefetch for performance
ds_train = ds_train.prefetch(tf.data.experimental.AUTOTUNE)
ds_test = ds_test.map(lambda image,label: (tf.cast(image, tf.float16) / 255., label), num_parallel_calls=tf.data.experimental.AUTOTUNE)
ds_test = ds_test.batch(512)
ds_test = ds_test.cache()
ds_test = ds_test.prefetch(tf.data.experimental.AUTOTUNE)
#Define what we are going to be training
log_path = "logs/"
model_path = "models/unit_number/"
histories = list()
csv_logger = tf.keras.callbacks.CSVLogger(log_path+'unit_number.csv', append=True, separator=';')
number_variants = 10
for current_variant in range(number_variants):
print("-"*80)
model = create_model(input_shape=ds_info.features["image"].shape,
output_units=10, hidden_units=2**current_variant, filter_shape=(2,2), convolution_layers=2,
dense_layers=2, batch_normalisation=False, dropout=0.2)
print(f'{current_variant+1}/{number_variants}: {model.name}')
model.summary()
history = model.fit(
ds_train,
epochs=10,
validation_data=ds_test,
callbacks=[csv_logger]
)
model.save(f'{model_path}{model.name}', save_format='h5')
histories.append(history)
for i in range(len(histories)):
plt.plot(histories[i].history["sparse_categorical_accuracy"], marker='x')
plt.legend([f'{2**i} Units' for i in range(len(histories))], title="Legend", loc="upper left", bbox_to_anchor=(1.05,0.75), fontsize="xx-small")
plt.title("Sparse Categorical Accuracy vs Epochs\nfor fixed 2 CONV2D Layers, 2 Dense layers, Dropout Rate 0.2")
plt.xlabel("Epoch number")
plt.ylabel("Sparse Categorical Accuracy")
plt.ylim(0.0, 1.0)
plt.show()
for i in range(len(histories)):
plt.plot(histories[i].history["val_sparse_categorical_accuracy"], marker='x')
plt.legend([f'{2**i} Units' for i in range(len(histories))], title="Legend", loc="upper left", bbox_to_anchor=(1.05,0.75), fontsize="xx-small")
plt.title("Validation Sparse Categorical Accuracy vs Epochs\nfor fixed 2 CONV2D Layers, 2 Dense layers, Dropout Rate 0.2")
plt.xlabel("Epoch number")
plt.ylabel("Validation Sparse Categorical Accuracy")
plt.ylim(0.0, 1.0)
plt.show()