-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathKeras Classification.py
260 lines (210 loc) · 9.09 KB
/
Keras Classification.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
250
251
252
253
254
255
256
257
258
259
260
import matplotlib.pyplot as plt
from keras.preprocessing.image import ImageDataGenerator
from keras import models, layers, optimizers
from sklearn.metrics import confusion_matrix
from pandas import DataFrame
# Parameters of the generators
imgX, imgY = (150, 150)
batch_size = 20
num_train_rows = 2593 # the number of training instances
num_val_rows = 865 # the number of validation instances
num_test_rows = 865 # the number of test instances
# Parameters of the models
epochs_num = 100
steps_per_epoch = int(num_train_rows/batch_size)
validation_steps = int(num_val_rows/batch_size)
# Generators
# Data folders needed: "train", "validation", "test"
datagen = ImageDataGenerator(rescale=1./255)
train_generator = datagen.flow_from_directory("train",
target_size=(imgX, imgY),
batch_size=batch_size,
class_mode='categorical')
validation_generator = datagen.flow_from_directory("validation",
target_size=(imgX, imgY),
batch_size=batch_size,
class_mode='categorical')
test_generator = datagen.flow_from_directory("test",
target_size=(imgX, imgY),
batch_size=1,
shuffle=False,
class_mode='categorical')
y_true = test_generator.classes
# Functions
# Plots the Validation and Training Losses and Accuracies
def plot_results(history):
acc= history.history['acc']
val_acc= history.history['val_acc']
loss = history.history['loss']
val_loss= history.history['val_loss']
epochs = range(1, len(acc)+1)
plt.figure()
plt.plot(epochs, acc, 'r', label='Training Accuracy')
plt.plot(epochs, val_acc, 'b', label='Validation Accuracy')
plt.title("Training & Validation Accuracy")
plt.xlabel("epoch")
plt.ylabel("model accuracy")
plt.legend()
plt.show()
plt.figure()
plt.plot(epochs, loss, 'r', label='Training Loss')
plt.plot(epochs, val_loss, 'b', label='Validation Loss')
plt.title("Training & Validation Loss")
plt.xlabel("epoch")
plt.ylabel("model loss")
plt.legend()
plt.show()
return True
# Build Model 1, return a compiled Keras model
def build_model_1():
model = models.Sequential()
# Layer 1
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(imgX, imgY, 3)))
model.add(layers.MaxPooling2D((2, 2)))
# Layer 2
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
# Layer 3
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
# Layer 4
model.add(layers.Flatten())
# Layer 5
model.add(layers.Dense(128, activation='relu'))
# Layer 6
model.add(layers.Dense(5, activation='softmax'))
# Compile
model.compile(loss='categorical_crossentropy', optimizer=optimizers.RMSprop(lr=1e-4), metrics=['acc'])
return model
# Build Model 2, return a compiled Keras model
def build_model_2():
model = models.Sequential()
# Layer 1
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(imgX, imgY, 3)))
model.add(layers.MaxPooling2D((2, 2)))
# Layer 2
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
# Layer 3
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
# Layer 4
model.add(layers.Conv2D(255, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
# Layer 5
model.add(layers.Flatten())
# Layer 6
model.add(layers.Dropout(0.5))
# Layer 7
model.add(layers.Dense(512, activation='relu'))
# Layer 8
model.add(layers.Dense(5, activation='softmax'))
# Compile
model.compile(loss='categorical_crossentropy', optimizer=optimizers.RMSprop(lr=1e-4), metrics=['acc'])
return model
# Prints and Returns the Loss and the Accuracy of the test set of a Keras model
def evaluate_generator(model):
print("Evaluating Accuracy and Loss...")
loss, acc = model.evaluate_generator(test_generator, num_test_rows)
print("Validation Loss: ", loss)
print("Accuracy: ", acc)
return {'loss':loss, 'acc':acc}
# Returns the predicted probabilities of the test_generator
def get_y_score(model, steps=865):
print("Evaluating Predicted Probabilities...")
return model.predict_generator(test_generator, steps=steps)
# Predicts the scores and the classes and returns the classification report
# Assumes an appropriate 'test_generator'
def get_confusion_matrix(model, y_score=None, names = "daisy dandelion rose sunflower tulip".split()):
if not y_score:
y_score = get_y_score(model)
y_pred = y_score.argmax(1)
report = confusion_matrix(y_true=y_true, y_pred=y_pred)
print()
print(DataFrame(report, columns=names, index=names))
return report
# Assignment Questions
# Question 1: Build the Network
network1 = build_model_1()
# Question 2: Train the Network
print()
print("NETWORK 1")
history1 = network1.fit_generator(train_generator,
steps_per_epoch=steps_per_epoch,
epochs=epochs_num,
validation_data=validation_generator,
validation_steps=validation_steps)
# Account for overfitting
print("""After the chart has been printed estimate where overfitting begins.
Pass the value in the input question""")
plot_results(history1)
overfit_epoch1 = int(input("\n\nOverfit Epoch? "))
# Adjust Model
# Lead the model to the end of epoch before overfitting starts occuring
history1.on_epoch_end(overfit_epoch1)
model_1 = history1.model
model_1.save("model_1.hf")
# Question 3: Apply the network to the test dataset
evaluate_generator(model_1)
# Print_confusion_matrix
cm_1 = get_confusion_matrix(model_1)
# Question 4: Improve your model
network2 = build_model_2()
print()
print("NETWORK 2")
history2 = network2.fit_generator(train_generator,
steps_per_epoch=steps_per_epoch,
epochs=epochs_num,
validation_data=validation_generator,
validation_steps=validation_steps)
# Estimate Overfitting of Improved Model
print("""After the chart has been printed estimate where overfitting begins.
Pass the value in the input question""")
plot_results(history2)
overfit_epoch2 = int(input("\n\nOverfit Epoch? "))
# Adjust Improved Model
# Lead the model on the end of epoch before overfitting starts occuring
history2.on_epoch_end(overfit_epoch2)
model_2 = history2.model
model_2.save("model_2.hf")
# Evaluate Improved Model
evaluate_generator(model_2)
# Print_confusion_matrix
cm_2 = get_confusion_matrix(model_2)
# Question 5: Use data augmentation
# Data Adjustments
datagen_aug = ImageDataGenerator(rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
rescale=1./255,
fill_mode='nearest')
train_generator_aug = datagen_aug.flow_from_directory("train",
target_size=(imgX, imgY),
batch_size=batch_size,
class_mode='categorical')
# Train Model
# Use the augmented data and fit model as it flows from the directory and use model with best results
print()
print("NETWORK 3")
history3 = build_model_2().fit_generator(train_generator_aug,
steps_per_epoch=steps_per_epoch,
epochs=epochs_num,
validation_data=validation_generator,
validation_steps=validation_steps)
# Estimate Overfitting
print("""After the chart has been printed estimate where overfitting begins.
Pass the value in the input question""")
plot_results(history3)
overfit_epoch3 = int(input("\n\nOverfit Epoch? "))
# Adjust Model
# Get the model on the end of epoch before overfitting starts
history3.on_epoch_end(overfit_epoch3)
model_3 = history3.model
model_3.save("model_3.hf")
# Apply the network to the test dataset
evaluate_generator(model_3)
# Print_confusion_matrix
cm_3 = get_confusion_matrix(model_3)