import torch
torch.cuda.is_available()
True
# Import TensorFlow/Keras
import tensorflow as tf
from tensorflow import keras
# keras.__version__
from time import time
import numpy as np
import random as python_random
# Import other modules
from matplotlib import pyplot as plt
np.random.seed(0)
python_random.seed(0)
tf.random.set_seed(0)
import cv2
import os
from tqdm import tqdm
base_path = 'C:/Users/david/Desktop/DeepLearning/flower_photos'
categories = os.listdir(base_path)
categories
['daisy', 'dandelion', 'roses', 'sunflowers', 'Test', 'Train', 'tulips']
height = []
width = []
for category in categories:
for image in tqdm(os.listdir(base_path + category)):
im = cv2.imread(base_path + category + '/' + image)
height.append(im.shape[0])
width.append(im.shape[1])
100%|██████████| 898/898 [00:47<00:00, 18.97it/s] 100%|██████████| 799/799 [00:28<00:00, 27.56it/s] 100%|██████████| 633/633 [00:21<00:00, 29.51it/s] 100%|██████████| 699/699 [00:24<00:00, 28.17it/s] 100%|██████████| 641/641 [00:29<00:00, 21.86it/s]
# Setting up Seaborn style
sns.set(style="whitegrid")
# Creating horizontal boxplots
plt.figure(figsize=(5, 3))
g = sns.boxplot(data=[height, width], orient='h', palette='Set2')
plt.title('Horizontal Boxplot of Height and Width', fontsize=16)
plt.xticks(fontsize=12)
plt.yticks(fontsize=12)
g.set_yticklabels(['Height', 'Width'])
plt.grid(axis='x')
plt.tight_layout()
plt.show()
<ipython-input-33-60fba1ad0455>:10: UserWarning: FixedFormatter should only be used together with FixedLocator g.set_yticklabels(['Height', 'Width'])
# Average width
sum(width)/len(width)
365.0623978201635
# Average height
sum(height)/len(height)
271.79128065395093
We create two copies of the data, one named "Train" and one named "Test".
train_path = 'C:/Users/david/Desktop/DeepLearning/flower_photos/Train/'
train_dataset = keras.preprocessing.image_dataset_from_directory(train_path,
image_size=(256,256),
batch_size=32,
label_mode='categorical',
subset='training',
validation_split = 0.2,
shuffle=True,
seed=1)
Found 2936 files belonging to 5 classes. Using 2349 files for training.
val_dataset = keras.preprocessing.image_dataset_from_directory(train_path,
image_size=(256,256),
batch_size=32,
label_mode='categorical',
subset='validation',
validation_split = 0.2,
shuffle=True,
seed=1)
Found 2936 files belonging to 5 classes. Using 587 files for validation.
From the train data, we are going to remove all of the observations that have been selected in the validation dataset. In the same way, from the test data, we are going to remove all of the observations that have been selected in the train dataset.
# From train dataset, remove all of the observations selected in validation set
for el in val_dataset.file_paths:
os.remove(el)
import re
# From test dataset, remove all of the observations selected in train set
for el in train_dataset.file_paths:
# Substitute 'Train' with 'Test' in order to remove observation from train directory
el = re.sub('Train', 'Test', el)
os.remove(el)
import os
train_path = 'C:/Users/david/Desktop/DeepLearning/flower_photos/Train/'
subD = os.listdir(train_path)
dizTrain = {}
# For each class subdirectory, insert in the dictionary dizTrain the number of element in that subdirectory
for dir in subD:
dizTrain[dir] = len(os.listdir(train_path + dir))
# Number of observations of each class in train set
dizTrain
{'daisy': 508, 'dandelion': 701, 'roses': 534, 'sunflowers': 561, 'tulips': 632}
test_path = 'C:/Users/david/Desktop/DeepLearning/flower_photos/Test/'
subD = os.listdir(test_path)
dizTest = {}
# For each class subdirectory, insert in the dictionary dizTrain the number of element in that subdirectory
for dir in subD:
dizTest[dir] = len(os.listdir(test_path + dir))
# Number of observations of each class in train set
dizTest
{'daisy': 125, 'dandelion': 197, 'roses': 107, 'sunflowers': 138, 'tulips': 167}
plt.bar(dizTrain.keys(), dizTrain.values(), color='b', alpha=0.5, label='Train')
plt.bar(dizTest.keys(), dizTest.values(), color='r', alpha=0.5, label='Test')
# Adding labels and title
plt.xlabel('N. of Observations')
plt.ylabel('Classes')
plt.title('N. of Observations per class')
plt.legend()
# Show plot
plt.show()
As we can see, there is not a huge difference in the classes sizes. For now, we are going to try and develop CNNs that do not address the issues of unbalanced classes.
The train data is going to be split in 80% train set and 20% validation set. The test data is going to be loaded from the train set that we built previously.
To recap: we firstly split the entire dataset in 80% train and 20% test. Now, we split the train set in 80% train and 20% validation. In this way, we have 0.64% train + 0.16% validation + 20% test.
train_path = 'C:/Users/david/Desktop/DeepLearning/flower_photos/Train/'
test_path = 'C:/Users/david/Desktop/DeepLearning/flower_photos/Test/'
train_ds = keras.preprocessing.image_dataset_from_directory(train_path,
image_size=(224,224),
batch_size=32,
label_mode='categorical',
subset='training',
validation_split = 0.2,
shuffle=True,
seed=1)
Found 2936 files belonging to 5 classes. Using 2349 files for training.
val_ds = keras.preprocessing.image_dataset_from_directory(train_path,
image_size=(224,224),
batch_size=32,
label_mode='categorical',
subset='validation',
validation_split = 0.2,
shuffle=True,
seed=1)
Found 2936 files belonging to 5 classes. Using 587 files for validation.
test_ds = keras.preprocessing.image_dataset_from_directory(test_path,
image_size=(224,224),
batch_size=32,
label_mode='categorical',
shuffle=False,
seed=1)
Found 734 files belonging to 5 classes.
num_classes = 5
We are going to start with a very easy CNN, and see what changes benefit its performances.
The first CNN consists of two hidden layers, with 32 and 64 neurons respectively. Both layers with ReLU activation.
Max Pooling is applied to the first layer, and Global Max Pooling to the second.
# Architecture definition Naive Model
inputs = keras.Input((224,224,3))
x = inputs
x = keras.layers.Conv2D(32, 3, padding="same")(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Conv2D(64, 3, padding="same")(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.GlobalMaxPooling2D()(x)
outputs = keras.layers.Dense(num_classes, activation="softmax")(x)
net = keras.Model(inputs, outputs)
# Compile the model for training
net.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.RMSprop(learning_rate=0.001),
metrics=['accuracy'])
# Check that we are running on GPU
tf.config.list_physical_devices('GPU')
[PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]
# Model training
history = net.fit(train_ds,
epochs=40,
validation_data=val_ds)
Epoch 1/40 74/74 [==============================] - 11s 72ms/step - loss: 17.0196 - accuracy: 0.3274 - val_loss: 5.2585 - val_accuracy: 0.4242 Epoch 2/40 74/74 [==============================] - 4s 52ms/step - loss: 4.1190 - accuracy: 0.4551 - val_loss: 4.1449 - val_accuracy: 0.3986 Epoch 3/40 74/74 [==============================] - 4s 50ms/step - loss: 2.0812 - accuracy: 0.5143 - val_loss: 2.0645 - val_accuracy: 0.5026 Epoch 4/40 74/74 [==============================] - 4s 51ms/step - loss: 1.4421 - accuracy: 0.5734 - val_loss: 1.5696 - val_accuracy: 0.5298 Epoch 5/40 74/74 [==============================] - 4s 50ms/step - loss: 1.1769 - accuracy: 0.6228 - val_loss: 1.9620 - val_accuracy: 0.5094 Epoch 6/40 74/74 [==============================] - 4s 52ms/step - loss: 0.9984 - accuracy: 0.6624 - val_loss: 1.4287 - val_accuracy: 0.5554 Epoch 7/40 74/74 [==============================] - 4s 52ms/step - loss: 0.8333 - accuracy: 0.7092 - val_loss: 1.4772 - val_accuracy: 0.5622 Epoch 8/40 74/74 [==============================] - 5s 61ms/step - loss: 0.7523 - accuracy: 0.7399 - val_loss: 1.7338 - val_accuracy: 0.5332 Epoch 9/40 74/74 [==============================] - 5s 64ms/step - loss: 0.6737 - accuracy: 0.7603 - val_loss: 1.5059 - val_accuracy: 0.5963 Epoch 10/40 74/74 [==============================] - 5s 68ms/step - loss: 0.6115 - accuracy: 0.7897 - val_loss: 1.2401 - val_accuracy: 0.6440 Epoch 11/40 74/74 [==============================] - 5s 69ms/step - loss: 0.5533 - accuracy: 0.7991 - val_loss: 1.5348 - val_accuracy: 0.6116 Epoch 12/40 74/74 [==============================] - 5s 66ms/step - loss: 0.4892 - accuracy: 0.8191 - val_loss: 1.3223 - val_accuracy: 0.5843 Epoch 13/40 74/74 [==============================] - 5s 67ms/step - loss: 0.4653 - accuracy: 0.8357 - val_loss: 1.2628 - val_accuracy: 0.6031 Epoch 14/40 74/74 [==============================] - 5s 66ms/step - loss: 0.4180 - accuracy: 0.8540 - val_loss: 1.5855 - val_accuracy: 0.6048 Epoch 15/40 74/74 [==============================] - 5s 67ms/step - loss: 0.3965 - accuracy: 0.8608 - val_loss: 1.2333 - val_accuracy: 0.6525 Epoch 16/40 74/74 [==============================] - 5s 67ms/step - loss: 0.3618 - accuracy: 0.8782 - val_loss: 1.5441 - val_accuracy: 0.6031 Epoch 17/40 74/74 [==============================] - 5s 66ms/step - loss: 0.3258 - accuracy: 0.8868 - val_loss: 2.0238 - val_accuracy: 0.6014 Epoch 18/40 74/74 [==============================] - 5s 66ms/step - loss: 0.3315 - accuracy: 0.8817 - val_loss: 1.3188 - val_accuracy: 0.6337 Epoch 19/40 74/74 [==============================] - 5s 72ms/step - loss: 0.2685 - accuracy: 0.9076 - val_loss: 1.3513 - val_accuracy: 0.6167 Epoch 20/40 74/74 [==============================] - 6s 74ms/step - loss: 0.2843 - accuracy: 0.8983 - val_loss: 1.4823 - val_accuracy: 0.6422 Epoch 21/40 74/74 [==============================] - 6s 74ms/step - loss: 0.2466 - accuracy: 0.9153 - val_loss: 1.5257 - val_accuracy: 0.6644 Epoch 22/40 74/74 [==============================] - 5s 69ms/step - loss: 0.2286 - accuracy: 0.9281 - val_loss: 1.5254 - val_accuracy: 0.6508 Epoch 23/40 74/74 [==============================] - 5s 69ms/step - loss: 0.2380 - accuracy: 0.9221 - val_loss: 1.2851 - val_accuracy: 0.6729 Epoch 24/40 74/74 [==============================] - 5s 69ms/step - loss: 0.2063 - accuracy: 0.9327 - val_loss: 2.9742 - val_accuracy: 0.5094 Epoch 25/40 74/74 [==============================] - 5s 67ms/step - loss: 0.2015 - accuracy: 0.9319 - val_loss: 1.3905 - val_accuracy: 0.6695 Epoch 26/40 74/74 [==============================] - 5s 66ms/step - loss: 0.1916 - accuracy: 0.9417 - val_loss: 1.6560 - val_accuracy: 0.6201 Epoch 27/40 74/74 [==============================] - 5s 66ms/step - loss: 0.1841 - accuracy: 0.9438 - val_loss: 2.1389 - val_accuracy: 0.6031 Epoch 28/40 74/74 [==============================] - 5s 66ms/step - loss: 0.1963 - accuracy: 0.9383 - val_loss: 1.7148 - val_accuracy: 0.6405 Epoch 29/40 74/74 [==============================] - 5s 66ms/step - loss: 0.1410 - accuracy: 0.9502 - val_loss: 1.4132 - val_accuracy: 0.6712 Epoch 30/40 74/74 [==============================] - 5s 66ms/step - loss: 0.1609 - accuracy: 0.9527 - val_loss: 2.4283 - val_accuracy: 0.6150 Epoch 31/40 74/74 [==============================] - 5s 66ms/step - loss: 0.1597 - accuracy: 0.9523 - val_loss: 1.8876 - val_accuracy: 0.6286 Epoch 32/40 74/74 [==============================] - 5s 66ms/step - loss: 0.1274 - accuracy: 0.9549 - val_loss: 1.9109 - val_accuracy: 0.6576 Epoch 33/40 74/74 [==============================] - 5s 66ms/step - loss: 0.1617 - accuracy: 0.9472 - val_loss: 1.7023 - val_accuracy: 0.6491 Epoch 34/40 74/74 [==============================] - 5s 68ms/step - loss: 0.1564 - accuracy: 0.9527 - val_loss: 1.5465 - val_accuracy: 0.6559 Epoch 35/40 74/74 [==============================] - 5s 67ms/step - loss: 0.1210 - accuracy: 0.9672 - val_loss: 1.7433 - val_accuracy: 0.6695 Epoch 36/40 74/74 [==============================] - 5s 66ms/step - loss: 0.1734 - accuracy: 0.9510 - val_loss: 1.5100 - val_accuracy: 0.6848 Epoch 37/40 74/74 [==============================] - 5s 66ms/step - loss: 0.1139 - accuracy: 0.9642 - val_loss: 2.8824 - val_accuracy: 0.5945 Epoch 38/40 74/74 [==============================] - 5s 66ms/step - loss: 0.1256 - accuracy: 0.9579 - val_loss: 1.8765 - val_accuracy: 0.6627 Epoch 39/40 74/74 [==============================] - 5s 67ms/step - loss: 0.1353 - accuracy: 0.9587 - val_loss: 2.0762 - val_accuracy: 0.6320 Epoch 40/40 74/74 [==============================] - 5s 67ms/step - loss: 0.0931 - accuracy: 0.9719 - val_loss: 2.7361 - val_accuracy: 0.5554
# Visualization of the learning curves
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.ylim([0.0, 2.0])
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend(['train', 'valid'])
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.ylim([0.5, 1.0])
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(['train', 'valid'])
<matplotlib.legend.Legend at 0x2a4a520c6d0>
While this simple Convolutional Neural Network reaches +95% accuracy on the training set, it is evident that it does not generalize well on the validation set. We will have to find additional methods to close the gap between train accuracy and validation accuracy.
The process of batch normalization makes it so that the weight in the network do not become unbalanced. We are going to add Batch Normalization on both of the hidden layers of the network.
# Architecture definition
inputs = keras.Input((224,224,3))
x = inputs
x = keras.layers.Conv2D(32, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Conv2D(64, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.GlobalMaxPooling2D()(x)
outputs = keras.layers.Dense(num_classes, activation="softmax")(x)
net = keras.Model(inputs, outputs)
# Compile the model for training
net.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.RMSprop(learning_rate=0.001),
metrics=['accuracy'])
# Model training (v2)
history = net.fit(train_ds,
epochs=40,
validation_data=val_ds);
Epoch 1/40 74/74 [==============================] - 8s 83ms/step - loss: 1.2796 - accuracy: 0.5121 - val_loss: 2.8535 - val_accuracy: 0.3424 Epoch 2/40 74/74 [==============================] - 6s 74ms/step - loss: 0.9084 - accuracy: 0.6390 - val_loss: 1.2577 - val_accuracy: 0.4940 Epoch 3/40 74/74 [==============================] - 6s 80ms/step - loss: 0.7982 - accuracy: 0.6845 - val_loss: 1.0072 - val_accuracy: 0.5894 Epoch 4/40 74/74 [==============================] - 6s 87ms/step - loss: 0.7335 - accuracy: 0.7143 - val_loss: 0.7672 - val_accuracy: 0.7070 Epoch 5/40 74/74 [==============================] - 7s 88ms/step - loss: 0.6749 - accuracy: 0.7361 - val_loss: 0.8029 - val_accuracy: 0.6780 Epoch 6/40 74/74 [==============================] - 7s 87ms/step - loss: 0.6239 - accuracy: 0.7680 - val_loss: 0.7348 - val_accuracy: 0.7206 Epoch 7/40 74/74 [==============================] - 7s 88ms/step - loss: 0.5900 - accuracy: 0.7842 - val_loss: 0.8029 - val_accuracy: 0.6848 Epoch 8/40 74/74 [==============================] - 7s 87ms/step - loss: 0.5679 - accuracy: 0.7808 - val_loss: 0.8248 - val_accuracy: 0.6865 Epoch 9/40 74/74 [==============================] - 7s 88ms/step - loss: 0.5212 - accuracy: 0.8118 - val_loss: 0.8332 - val_accuracy: 0.6831 Epoch 10/40 74/74 [==============================] - 7s 88ms/step - loss: 0.5138 - accuracy: 0.8131 - val_loss: 0.7168 - val_accuracy: 0.7257 Epoch 11/40 74/74 [==============================] - 7s 88ms/step - loss: 0.4825 - accuracy: 0.8280 - val_loss: 0.7173 - val_accuracy: 0.7274 Epoch 12/40 74/74 [==============================] - 7s 88ms/step - loss: 0.4600 - accuracy: 0.8318 - val_loss: 0.7322 - val_accuracy: 0.7206 Epoch 13/40 74/74 [==============================] - 7s 88ms/step - loss: 0.4364 - accuracy: 0.8378 - val_loss: 0.8179 - val_accuracy: 0.6848 Epoch 14/40 74/74 [==============================] - 7s 88ms/step - loss: 0.4334 - accuracy: 0.8463 - val_loss: 0.7783 - val_accuracy: 0.6951 Epoch 15/40 74/74 [==============================] - 7s 88ms/step - loss: 0.4077 - accuracy: 0.8582 - val_loss: 0.6688 - val_accuracy: 0.7581 Epoch 16/40 74/74 [==============================] - 7s 87ms/step - loss: 0.3873 - accuracy: 0.8740 - val_loss: 0.8979 - val_accuracy: 0.6729 Epoch 17/40 74/74 [==============================] - 7s 96ms/step - loss: 0.3656 - accuracy: 0.8838 - val_loss: 0.7228 - val_accuracy: 0.7070 Epoch 18/40 74/74 [==============================] - 8s 105ms/step - loss: 0.3494 - accuracy: 0.8834 - val_loss: 0.7341 - val_accuracy: 0.7155 Epoch 19/40 74/74 [==============================] - 9s 122ms/step - loss: 0.3515 - accuracy: 0.8838 - val_loss: 0.6989 - val_accuracy: 0.7223 Epoch 20/40 74/74 [==============================] - 10s 133ms/step - loss: 0.3113 - accuracy: 0.9012 - val_loss: 0.8656 - val_accuracy: 0.6865 Epoch 21/40 74/74 [==============================] - 10s 138ms/step - loss: 0.3170 - accuracy: 0.9046 - val_loss: 1.2112 - val_accuracy: 0.6133 Epoch 22/40 74/74 [==============================] - 12s 156ms/step - loss: 0.3106 - accuracy: 0.8991 - val_loss: 0.6845 - val_accuracy: 0.7376 Epoch 23/40 74/74 [==============================] - 12s 158ms/step - loss: 0.2756 - accuracy: 0.9191 - val_loss: 0.8177 - val_accuracy: 0.7121 Epoch 24/40 74/74 [==============================] - 13s 175ms/step - loss: 0.2774 - accuracy: 0.9174 - val_loss: 1.0374 - val_accuracy: 0.6167 Epoch 25/40 74/74 [==============================] - 14s 194ms/step - loss: 0.2549 - accuracy: 0.9212 - val_loss: 0.7430 - val_accuracy: 0.7138 Epoch 26/40 74/74 [==============================] - 15s 202ms/step - loss: 0.2540 - accuracy: 0.9264 - val_loss: 0.8174 - val_accuracy: 0.6865 Epoch 27/40 74/74 [==============================] - 15s 205ms/step - loss: 0.2570 - accuracy: 0.9144 - val_loss: 0.7751 - val_accuracy: 0.7155 Epoch 28/40 74/74 [==============================] - 15s 205ms/step - loss: 0.2361 - accuracy: 0.9293 - val_loss: 0.9054 - val_accuracy: 0.6712 Epoch 29/40 74/74 [==============================] - 15s 206ms/step - loss: 0.2183 - accuracy: 0.9434 - val_loss: 0.8155 - val_accuracy: 0.7189 Epoch 30/40 74/74 [==============================] - 16s 208ms/step - loss: 0.2175 - accuracy: 0.9353 - val_loss: 0.7847 - val_accuracy: 0.7240 Epoch 31/40 74/74 [==============================] - 16s 208ms/step - loss: 0.2085 - accuracy: 0.9468 - val_loss: 0.7389 - val_accuracy: 0.7325 Epoch 32/40 74/74 [==============================] - 16s 209ms/step - loss: 0.1941 - accuracy: 0.9485 - val_loss: 0.9924 - val_accuracy: 0.6865 Epoch 33/40 74/74 [==============================] - 16s 216ms/step - loss: 0.1850 - accuracy: 0.9476 - val_loss: 0.8727 - val_accuracy: 0.7104 Epoch 34/40 74/74 [==============================] - 16s 215ms/step - loss: 0.1784 - accuracy: 0.9579 - val_loss: 0.9229 - val_accuracy: 0.6814 Epoch 35/40 74/74 [==============================] - 16s 216ms/step - loss: 0.1794 - accuracy: 0.9476 - val_loss: 0.8788 - val_accuracy: 0.7342 Epoch 36/40 74/74 [==============================] - 16s 216ms/step - loss: 0.1597 - accuracy: 0.9621 - val_loss: 0.7931 - val_accuracy: 0.7428 Epoch 37/40 74/74 [==============================] - 17s 226ms/step - loss: 0.1594 - accuracy: 0.9587 - val_loss: 1.1626 - val_accuracy: 0.6542 Epoch 38/40 74/74 [==============================] - 17s 225ms/step - loss: 0.1509 - accuracy: 0.9647 - val_loss: 0.8755 - val_accuracy: 0.6917 Epoch 39/40 74/74 [==============================] - 18s 230ms/step - loss: 0.1513 - accuracy: 0.9651 - val_loss: 0.7679 - val_accuracy: 0.7496 Epoch 40/40 74/74 [==============================] - 18s 240ms/step - loss: 0.1355 - accuracy: 0.9672 - val_loss: 0.8849 - val_accuracy: 0.6882
# Visualization of the learning curves
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.ylim([0.0, 2.0])
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend(['train', 'valid'])
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.ylim([0.5, 1.0])
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(['train', 'valid'])
<matplotlib.legend.Legend at 0x29101c77160>
It seems that adding batch Normalization results in an increase in performance.
Though, there is a lot of volatility, and the network is still not able to generalize as well as we would want.
In order to try and reduce this gap, we are going to add Data Augmentation.
Data Augmentation consists in artificially augmenting the training data by, in this case, applying transformations over the observations. This will not only increase the size of the training data, but will increase its complexity. This increase in complexity will likely prevent overfitting, but will come at the cost of worse performances on the training data. This is not a problem, since, in case this happen, we can resolve the issue be increasing the complexity of our Neural Network.
Since we want to apply a "crop" augmentation, we have to re-import the training that as larger images, in order to later crop them into the default 224x224 size that we used for the previous CNNs.
# Data loader with (slightly) larger images
# In this way, we can augment the images with RandomCrop
train_ds_256 = keras.preprocessing.image_dataset_from_directory(train_path,
image_size=(256,256),
batch_size=32,
label_mode='categorical',
subset='training',
validation_split = 0.2,
shuffle=True,
seed=1)
Found 2936 files belonging to 5 classes. Using 2349 files for training.
# We check if the file did not change. This should be the case since we inserted the same seed.
train_ds.file_paths == train_ds_256.file_paths
True
For augmenting our data, we apply three functions: RandomCrop, RandomFlip and RandomContrast. Note: these 3 types of augmentation have been decided via testing different combinations, for shortness and clarity purposes I'm not going to display all of them.
For what regards everything else, the architechture will remain exactly the same. In this way we are going to test the improvements that this technique brings.
# Architecture definition
inputs = keras.Input((None,None,3))
x = inputs
x = keras.layers.RandomCrop(224, 224)(x)
x = keras.layers.RandomFlip(mode='horizontal')(x)
x = keras.layers.RandomContrast(0.25)(x)
x = keras.layers.Conv2D(32, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Conv2D(64, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.GlobalMaxPooling2D()(x)
outputs = keras.layers.Dense(num_classes, activation="softmax")(x)
net = keras.Model(inputs, outputs)
# Compile the model for training
net.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.RMSprop(learning_rate=0.001),
metrics=['accuracy'])
# Model training
history = net.fit(train_ds_256,
epochs=40,
validation_data=val_ds)
Epoch 1/40 74/74 [==============================] - 8s 96ms/step - loss: 1.3436 - accuracy: 0.4874 - val_loss: 1.7722 - val_accuracy: 0.3952 Epoch 2/40 74/74 [==============================] - 6s 82ms/step - loss: 0.9842 - accuracy: 0.6113 - val_loss: 1.0545 - val_accuracy: 0.5809 Epoch 3/40 74/74 [==============================] - 6s 85ms/step - loss: 0.8703 - accuracy: 0.6552 - val_loss: 0.8448 - val_accuracy: 0.6627 Epoch 4/40 74/74 [==============================] - 8s 102ms/step - loss: 0.8052 - accuracy: 0.6901 - val_loss: 0.9303 - val_accuracy: 0.6440 Epoch 5/40 74/74 [==============================] - 8s 102ms/step - loss: 0.7661 - accuracy: 0.7016 - val_loss: 0.8709 - val_accuracy: 0.6678 Epoch 6/40 74/74 [==============================] - 8s 102ms/step - loss: 0.7624 - accuracy: 0.7143 - val_loss: 0.7269 - val_accuracy: 0.7223 Epoch 7/40 74/74 [==============================] - 8s 102ms/step - loss: 0.6959 - accuracy: 0.7318 - val_loss: 0.7989 - val_accuracy: 0.6934 Epoch 8/40 74/74 [==============================] - 8s 102ms/step - loss: 0.6920 - accuracy: 0.7361 - val_loss: 0.9533 - val_accuracy: 0.6354 Epoch 9/40 74/74 [==============================] - 8s 102ms/step - loss: 0.6681 - accuracy: 0.7484 - val_loss: 0.8612 - val_accuracy: 0.6934 Epoch 10/40 74/74 [==============================] - 8s 102ms/step - loss: 0.6730 - accuracy: 0.7314 - val_loss: 0.7826 - val_accuracy: 0.6985 Epoch 11/40 74/74 [==============================] - 8s 102ms/step - loss: 0.6420 - accuracy: 0.7544 - val_loss: 0.8309 - val_accuracy: 0.6797 Epoch 12/40 74/74 [==============================] - 8s 102ms/step - loss: 0.6308 - accuracy: 0.7718 - val_loss: 0.6283 - val_accuracy: 0.7513 Epoch 13/40 74/74 [==============================] - 8s 102ms/step - loss: 0.6210 - accuracy: 0.7599 - val_loss: 0.6973 - val_accuracy: 0.7308 Epoch 14/40 74/74 [==============================] - 8s 102ms/step - loss: 0.6098 - accuracy: 0.7654 - val_loss: 0.9147 - val_accuracy: 0.6508 Epoch 15/40 74/74 [==============================] - 8s 105ms/step - loss: 0.5968 - accuracy: 0.7722 - val_loss: 0.5948 - val_accuracy: 0.7513 Epoch 16/40 74/74 [==============================] - 8s 106ms/step - loss: 0.5622 - accuracy: 0.7914 - val_loss: 0.6408 - val_accuracy: 0.7496 Epoch 17/40 74/74 [==============================] - 8s 105ms/step - loss: 0.5561 - accuracy: 0.7871 - val_loss: 0.7929 - val_accuracy: 0.6985 Epoch 18/40 74/74 [==============================] - 9s 120ms/step - loss: 0.5691 - accuracy: 0.7876 - val_loss: 0.6081 - val_accuracy: 0.7598 Epoch 19/40 74/74 [==============================] - 10s 140ms/step - loss: 0.5526 - accuracy: 0.7940 - val_loss: 0.6719 - val_accuracy: 0.7496 Epoch 20/40 74/74 [==============================] - 11s 145ms/step - loss: 0.5376 - accuracy: 0.8012 - val_loss: 0.6843 - val_accuracy: 0.7376 Epoch 21/40 74/74 [==============================] - 12s 162ms/step - loss: 0.5292 - accuracy: 0.7969 - val_loss: 0.8255 - val_accuracy: 0.7121 Epoch 22/40 74/74 [==============================] - 12s 161ms/step - loss: 0.5283 - accuracy: 0.7995 - val_loss: 0.7709 - val_accuracy: 0.6865 Epoch 23/40 74/74 [==============================] - 13s 178ms/step - loss: 0.5315 - accuracy: 0.7995 - val_loss: 0.6507 - val_accuracy: 0.7581 Epoch 24/40 74/74 [==============================] - 14s 188ms/step - loss: 0.5148 - accuracy: 0.8110 - val_loss: 0.5927 - val_accuracy: 0.7853 Epoch 25/40 74/74 [==============================] - 14s 191ms/step - loss: 0.5048 - accuracy: 0.8072 - val_loss: 0.7018 - val_accuracy: 0.7445 Epoch 26/40 74/74 [==============================] - 15s 198ms/step - loss: 0.5118 - accuracy: 0.8050 - val_loss: 0.6363 - val_accuracy: 0.7411 Epoch 27/40 74/74 [==============================] - 14s 191ms/step - loss: 0.4918 - accuracy: 0.8191 - val_loss: 0.7743 - val_accuracy: 0.7291 Epoch 28/40 74/74 [==============================] - 15s 205ms/step - loss: 0.4896 - accuracy: 0.8165 - val_loss: 0.5867 - val_accuracy: 0.7683 Epoch 29/40 74/74 [==============================] - 14s 195ms/step - loss: 0.4812 - accuracy: 0.8221 - val_loss: 0.6388 - val_accuracy: 0.7547 Epoch 30/40 74/74 [==============================] - 15s 204ms/step - loss: 0.4766 - accuracy: 0.8199 - val_loss: 0.5497 - val_accuracy: 0.7973 Epoch 31/40 74/74 [==============================] - 16s 215ms/step - loss: 0.4924 - accuracy: 0.8169 - val_loss: 0.5546 - val_accuracy: 0.7888 Epoch 32/40 74/74 [==============================] - 16s 217ms/step - loss: 0.4519 - accuracy: 0.8357 - val_loss: 0.9878 - val_accuracy: 0.6559 Epoch 33/40 74/74 [==============================] - 16s 221ms/step - loss: 0.4612 - accuracy: 0.8272 - val_loss: 0.5623 - val_accuracy: 0.7683 Epoch 34/40 74/74 [==============================] - 16s 218ms/step - loss: 0.4693 - accuracy: 0.8272 - val_loss: 0.6548 - val_accuracy: 0.7513 Epoch 35/40 74/74 [==============================] - 16s 221ms/step - loss: 0.4385 - accuracy: 0.8357 - val_loss: 0.5771 - val_accuracy: 0.7905 Epoch 36/40 74/74 [==============================] - 17s 228ms/step - loss: 0.4331 - accuracy: 0.8433 - val_loss: 0.5939 - val_accuracy: 0.7802 Epoch 37/40 74/74 [==============================] - 17s 231ms/step - loss: 0.4391 - accuracy: 0.8429 - val_loss: 0.5964 - val_accuracy: 0.7615 Epoch 38/40 74/74 [==============================] - 17s 228ms/step - loss: 0.4496 - accuracy: 0.8272 - val_loss: 0.5499 - val_accuracy: 0.7956 Epoch 39/40 74/74 [==============================] - 17s 231ms/step - loss: 0.4413 - accuracy: 0.8387 - val_loss: 0.6639 - val_accuracy: 0.7359 Epoch 40/40 74/74 [==============================] - 17s 225ms/step - loss: 0.4262 - accuracy: 0.8421 - val_loss: 0.6685 - val_accuracy: 0.7445
# Visualization of the learning curves
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.ylim([0.0, 2.0])
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend(['train', 'valid'])
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.ylim([0.5, 1.0])
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(['train', 'valid'])
<matplotlib.legend.Legend at 0x26f0b1a3ac0>
Data augmentation did lower the accuracy on the training set, partially resolving the overfitting problem of the model. Though, we have a really high volatilty on the validation set, we are going to try to address this by lowering the Learning Rate.
inputs = keras.Input((None,None,3))
x = inputs
x = keras.layers.RandomCrop(224, 224)(x)
x = keras.layers.RandomFlip(mode='horizontal')(x)
x = keras.layers.RandomContrast(0.25)(x)
x = keras.layers.Conv2D(32, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Conv2D(64, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.GlobalMaxPooling2D()(x)
outputs = keras.layers.Dense(num_classes, activation="softmax")(x)
net = keras.Model(inputs, outputs)
# Compile the model for training
net.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.RMSprop(learning_rate=0.0005),
metrics=['accuracy'])
# Model training (v4)
history = net.fit(train_ds_256,
epochs=40,
validation_data=val_ds)
Epoch 1/40 74/74 [==============================] - 9s 102ms/step - loss: 1.5953 - accuracy: 0.4444 - val_loss: 2.8384 - val_accuracy: 0.3203 Epoch 2/40 74/74 [==============================] - 6s 80ms/step - loss: 1.0027 - accuracy: 0.6075 - val_loss: 1.7423 - val_accuracy: 0.4838 Epoch 3/40 74/74 [==============================] - 6s 82ms/step - loss: 0.8753 - accuracy: 0.6603 - val_loss: 0.9845 - val_accuracy: 0.6218 Epoch 4/40 74/74 [==============================] - 7s 87ms/step - loss: 0.8201 - accuracy: 0.6833 - val_loss: 0.9869 - val_accuracy: 0.6235 Epoch 5/40 74/74 [==============================] - 7s 99ms/step - loss: 0.7881 - accuracy: 0.7016 - val_loss: 0.7551 - val_accuracy: 0.7121 Epoch 6/40 74/74 [==============================] - 8s 102ms/step - loss: 0.7534 - accuracy: 0.7156 - val_loss: 0.7740 - val_accuracy: 0.6712 Epoch 7/40 74/74 [==============================] - 8s 102ms/step - loss: 0.7294 - accuracy: 0.7160 - val_loss: 0.7080 - val_accuracy: 0.7189 Epoch 8/40 74/74 [==============================] - 8s 102ms/step - loss: 0.7141 - accuracy: 0.7216 - val_loss: 0.8438 - val_accuracy: 0.6491 Epoch 9/40 74/74 [==============================] - 8s 102ms/step - loss: 0.6819 - accuracy: 0.7395 - val_loss: 0.7652 - val_accuracy: 0.7019 Epoch 10/40 74/74 [==============================] - 8s 103ms/step - loss: 0.6797 - accuracy: 0.7386 - val_loss: 0.7234 - val_accuracy: 0.6985 Epoch 11/40 74/74 [==============================] - 8s 104ms/step - loss: 0.6761 - accuracy: 0.7420 - val_loss: 0.7929 - val_accuracy: 0.6917 Epoch 12/40 74/74 [==============================] - 8s 103ms/step - loss: 0.6376 - accuracy: 0.7544 - val_loss: 0.6648 - val_accuracy: 0.7445 Epoch 13/40 74/74 [==============================] - 8s 102ms/step - loss: 0.6376 - accuracy: 0.7607 - val_loss: 0.6231 - val_accuracy: 0.7462 Epoch 14/40 74/74 [==============================] - 8s 102ms/step - loss: 0.6321 - accuracy: 0.7629 - val_loss: 0.7515 - val_accuracy: 0.6934 Epoch 15/40 74/74 [==============================] - 8s 102ms/step - loss: 0.6138 - accuracy: 0.7808 - val_loss: 0.6523 - val_accuracy: 0.7325 Epoch 16/40 74/74 [==============================] - 8s 103ms/step - loss: 0.5874 - accuracy: 0.7854 - val_loss: 0.7071 - val_accuracy: 0.7206 Epoch 17/40 74/74 [==============================] - 8s 103ms/step - loss: 0.5853 - accuracy: 0.7816 - val_loss: 0.6338 - val_accuracy: 0.7479 Epoch 18/40 74/74 [==============================] - 8s 103ms/step - loss: 0.5944 - accuracy: 0.7782 - val_loss: 0.6311 - val_accuracy: 0.7359 Epoch 19/40 74/74 [==============================] - 8s 106ms/step - loss: 0.5701 - accuracy: 0.7880 - val_loss: 0.7424 - val_accuracy: 0.6917 Epoch 20/40 74/74 [==============================] - 8s 111ms/step - loss: 0.5681 - accuracy: 0.7914 - val_loss: 0.6108 - val_accuracy: 0.7717 Epoch 21/40 74/74 [==============================] - 8s 110ms/step - loss: 0.5590 - accuracy: 0.7842 - val_loss: 0.7066 - val_accuracy: 0.7325 Epoch 22/40 74/74 [==============================] - 9s 116ms/step - loss: 0.5591 - accuracy: 0.7854 - val_loss: 0.6848 - val_accuracy: 0.7240 Epoch 23/40 74/74 [==============================] - 8s 111ms/step - loss: 0.5510 - accuracy: 0.7897 - val_loss: 0.6353 - val_accuracy: 0.7394 Epoch 24/40 74/74 [==============================] - 10s 136ms/step - loss: 0.5267 - accuracy: 0.8063 - val_loss: 0.6195 - val_accuracy: 0.7666 Epoch 25/40 74/74 [==============================] - 14s 192ms/step - loss: 0.5175 - accuracy: 0.8029 - val_loss: 0.6502 - val_accuracy: 0.7462 Epoch 26/40 74/74 [==============================] - 15s 203ms/step - loss: 0.5375 - accuracy: 0.7978 - val_loss: 0.6433 - val_accuracy: 0.7411 Epoch 27/40 74/74 [==============================] - 17s 232ms/step - loss: 0.5148 - accuracy: 0.8157 - val_loss: 0.7694 - val_accuracy: 0.6985 Epoch 28/40 74/74 [==============================] - 18s 239ms/step - loss: 0.5121 - accuracy: 0.8118 - val_loss: 0.7182 - val_accuracy: 0.7155 Epoch 29/40 74/74 [==============================] - 18s 240ms/step - loss: 0.5051 - accuracy: 0.8093 - val_loss: 0.5768 - val_accuracy: 0.7785 Epoch 30/40 74/74 [==============================] - 18s 234ms/step - loss: 0.4833 - accuracy: 0.8242 - val_loss: 0.6223 - val_accuracy: 0.7734 Epoch 31/40 74/74 [==============================] - 17s 234ms/step - loss: 0.4980 - accuracy: 0.8186 - val_loss: 0.6950 - val_accuracy: 0.7342 Epoch 32/40 74/74 [==============================] - 17s 233ms/step - loss: 0.4957 - accuracy: 0.8272 - val_loss: 0.5990 - val_accuracy: 0.7700 Epoch 33/40 74/74 [==============================] - 15s 204ms/step - loss: 0.4892 - accuracy: 0.8186 - val_loss: 0.5941 - val_accuracy: 0.7802 Epoch 34/40 74/74 [==============================] - 14s 188ms/step - loss: 0.4904 - accuracy: 0.8225 - val_loss: 0.7020 - val_accuracy: 0.7223 Epoch 35/40 74/74 [==============================] - 17s 227ms/step - loss: 0.4722 - accuracy: 0.8318 - val_loss: 0.5980 - val_accuracy: 0.7581 Epoch 36/40 74/74 [==============================] - 17s 232ms/step - loss: 0.4696 - accuracy: 0.8335 - val_loss: 0.5836 - val_accuracy: 0.7888 Epoch 37/40 74/74 [==============================] - 17s 232ms/step - loss: 0.4704 - accuracy: 0.8297 - val_loss: 0.6748 - val_accuracy: 0.7445 Epoch 38/40 74/74 [==============================] - 17s 234ms/step - loss: 0.4576 - accuracy: 0.8352 - val_loss: 0.5817 - val_accuracy: 0.7905 Epoch 39/40 74/74 [==============================] - 17s 234ms/step - loss: 0.4481 - accuracy: 0.8276 - val_loss: 0.5982 - val_accuracy: 0.7649 Epoch 40/40 74/74 [==============================] - 18s 236ms/step - loss: 0.4517 - accuracy: 0.8438 - val_loss: 0.6717 - val_accuracy: 0.7291
# Visualization of the learning curves
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.ylim([0.0, 2.0])
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend(['train', 'valid'])
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.ylim([0.5, 1.0])
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(['train', 'valid'])
<matplotlib.legend.Legend at 0x29190aacfd0>
The volatility in the validation set did decrease a little, though, it is still present. Another possible cause of this could be that we chose a validation set that is too small. By choosing a small validation set, it could be possible that, at each epoch, the changes in the weights of the model that occur influence the classification of a big portion of the observation. We are going to try to see if, by increasing the validation set to a 30%, the validation accuracy is going to result more stable.
The train data is going to be split in 70% train set and 30% validation set. The test data is not going to be touched.
To recap: we firstly split the entire dataset in 80% train and 20% test. Now, we split the train set in 70% train and 30% validation. In this way, we have 0.56% train + 0.24% validation + 20% test.
train_ds = keras.preprocessing.image_dataset_from_directory(train_path,
image_size=(224,224),
batch_size=32,
label_mode='categorical',
subset='training',
validation_split = 0.3,
shuffle=True,
seed=1)
val_ds = keras.preprocessing.image_dataset_from_directory(train_path,
image_size=(224,224),
batch_size=32,
label_mode='categorical',
subset='validation',
validation_split = 0.3,
shuffle=True,
seed=1)
# Data loader with (slightly) larger images
# In this way, we can augment the images with RandomCrop
train_ds_256 = keras.preprocessing.image_dataset_from_directory(train_path,
image_size=(256,256),
batch_size=32,
label_mode='categorical',
subset='training',
validation_split = 0.3,
shuffle=True,
seed=1)
Found 2936 files belonging to 5 classes. Using 2056 files for training. Found 2936 files belonging to 5 classes. Using 880 files for validation. Found 2936 files belonging to 5 classes. Using 2056 files for training.
# We check if the file did not change. This should be the case since we inserted the same seed.
train_ds.file_paths == train_ds_256.file_paths
True
We are now going to retrain the exact same model, in order to evaluate the effects that this change in train/validation proportion have caused.
inputs = keras.Input((None,None,3))
x = inputs
x = keras.layers.RandomCrop(224, 224)(x)
x = keras.layers.RandomFlip(mode='horizontal')(x)
x = keras.layers.RandomContrast(0.25)(x)
x = keras.layers.Conv2D(32, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Conv2D(64, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.GlobalMaxPooling2D()(x)
outputs = keras.layers.Dense(num_classes, activation="softmax")(x)
net = keras.Model(inputs, outputs)
# Compile the model for training
net.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.RMSprop(learning_rate=0.0005),
metrics=['accuracy'])
# Model training (v4)
history = net.fit(train_ds_256,
epochs=40,
validation_data=val_ds)
Epoch 1/40 65/65 [==============================] - 7s 87ms/step - loss: 1.3042 - accuracy: 0.4762 - val_loss: 2.0753 - val_accuracy: 0.2500 Epoch 2/40 65/65 [==============================] - 5s 83ms/step - loss: 1.0225 - accuracy: 0.5963 - val_loss: 1.6847 - val_accuracy: 0.3591 Epoch 3/40 65/65 [==============================] - 5s 81ms/step - loss: 0.9078 - accuracy: 0.6552 - val_loss: 1.0748 - val_accuracy: 0.5943 Epoch 4/40 65/65 [==============================] - 5s 83ms/step - loss: 0.8515 - accuracy: 0.6727 - val_loss: 0.9327 - val_accuracy: 0.6557 Epoch 5/40 65/65 [==============================] - 5s 82ms/step - loss: 0.8149 - accuracy: 0.6916 - val_loss: 0.7812 - val_accuracy: 0.7125 Epoch 6/40 65/65 [==============================] - 5s 82ms/step - loss: 0.8000 - accuracy: 0.6960 - val_loss: 0.7368 - val_accuracy: 0.7239 Epoch 7/40 65/65 [==============================] - 5s 83ms/step - loss: 0.7586 - accuracy: 0.6994 - val_loss: 0.7413 - val_accuracy: 0.7193 Epoch 8/40 65/65 [==============================] - 6s 90ms/step - loss: 0.7401 - accuracy: 0.7155 - val_loss: 0.7022 - val_accuracy: 0.7409 Epoch 9/40 65/65 [==============================] - 6s 99ms/step - loss: 0.7204 - accuracy: 0.7281 - val_loss: 0.6799 - val_accuracy: 0.7545 Epoch 10/40 65/65 [==============================] - 7s 102ms/step - loss: 0.6974 - accuracy: 0.7451 - val_loss: 0.6902 - val_accuracy: 0.7420 Epoch 11/40 65/65 [==============================] - 7s 102ms/step - loss: 0.6932 - accuracy: 0.7417 - val_loss: 0.6731 - val_accuracy: 0.7330 Epoch 12/40 65/65 [==============================] - 7s 104ms/step - loss: 0.6616 - accuracy: 0.7544 - val_loss: 0.6477 - val_accuracy: 0.7648 Epoch 13/40 65/65 [==============================] - 7s 105ms/step - loss: 0.6597 - accuracy: 0.7539 - val_loss: 0.6650 - val_accuracy: 0.7523 Epoch 14/40 65/65 [==============================] - 7s 104ms/step - loss: 0.6553 - accuracy: 0.7510 - val_loss: 0.6314 - val_accuracy: 0.7705 Epoch 15/40 65/65 [==============================] - 7s 103ms/step - loss: 0.6380 - accuracy: 0.7631 - val_loss: 0.7422 - val_accuracy: 0.7114 Epoch 16/40 65/65 [==============================] - 7s 103ms/step - loss: 0.6191 - accuracy: 0.7685 - val_loss: 0.6797 - val_accuracy: 0.7489 Epoch 17/40 65/65 [==============================] - 7s 104ms/step - loss: 0.6023 - accuracy: 0.7729 - val_loss: 0.6411 - val_accuracy: 0.7670 Epoch 18/40 65/65 [==============================] - 7s 105ms/step - loss: 0.6151 - accuracy: 0.7631 - val_loss: 0.6419 - val_accuracy: 0.7648 Epoch 19/40 65/65 [==============================] - 7s 104ms/step - loss: 0.5948 - accuracy: 0.7840 - val_loss: 0.6076 - val_accuracy: 0.7784 Epoch 20/40 65/65 [==============================] - 7s 106ms/step - loss: 0.5941 - accuracy: 0.7855 - val_loss: 0.6179 - val_accuracy: 0.7761 Epoch 21/40 65/65 [==============================] - 7s 105ms/step - loss: 0.5789 - accuracy: 0.7875 - val_loss: 0.5913 - val_accuracy: 0.7886 Epoch 22/40 65/65 [==============================] - 7s 106ms/step - loss: 0.5659 - accuracy: 0.7928 - val_loss: 0.6034 - val_accuracy: 0.7920 Epoch 23/40 65/65 [==============================] - 7s 105ms/step - loss: 0.5554 - accuracy: 0.7967 - val_loss: 0.6032 - val_accuracy: 0.7773 Epoch 24/40 65/65 [==============================] - 7s 106ms/step - loss: 0.5604 - accuracy: 0.7840 - val_loss: 0.6507 - val_accuracy: 0.7545 Epoch 25/40 65/65 [==============================] - 7s 106ms/step - loss: 0.5399 - accuracy: 0.8040 - val_loss: 0.5865 - val_accuracy: 0.7716 Epoch 26/40 65/65 [==============================] - 7s 106ms/step - loss: 0.5455 - accuracy: 0.8084 - val_loss: 0.6499 - val_accuracy: 0.7670 Epoch 27/40 65/65 [==============================] - 7s 105ms/step - loss: 0.5299 - accuracy: 0.7972 - val_loss: 0.6414 - val_accuracy: 0.7636 Epoch 28/40 65/65 [==============================] - 7s 111ms/step - loss: 0.5370 - accuracy: 0.7899 - val_loss: 0.6361 - val_accuracy: 0.7705 Epoch 29/40 65/65 [==============================] - 8s 120ms/step - loss: 0.5387 - accuracy: 0.8006 - val_loss: 0.6129 - val_accuracy: 0.7670 Epoch 30/40 65/65 [==============================] - 9s 139ms/step - loss: 0.5332 - accuracy: 0.8084 - val_loss: 0.6121 - val_accuracy: 0.7648 Epoch 31/40 65/65 [==============================] - 9s 139ms/step - loss: 0.5283 - accuracy: 0.8093 - val_loss: 0.7042 - val_accuracy: 0.7375 Epoch 32/40 65/65 [==============================] - 10s 155ms/step - loss: 0.5090 - accuracy: 0.8181 - val_loss: 0.6109 - val_accuracy: 0.7773 Epoch 33/40 65/65 [==============================] - 10s 158ms/step - loss: 0.5148 - accuracy: 0.8205 - val_loss: 0.5606 - val_accuracy: 0.7977 Epoch 34/40 65/65 [==============================] - 10s 160ms/step - loss: 0.5220 - accuracy: 0.8093 - val_loss: 0.5806 - val_accuracy: 0.8000 Epoch 35/40 65/65 [==============================] - 10s 151ms/step - loss: 0.5034 - accuracy: 0.8074 - val_loss: 0.6464 - val_accuracy: 0.7466 Epoch 36/40 65/65 [==============================] - 12s 184ms/step - loss: 0.4980 - accuracy: 0.8152 - val_loss: 0.6571 - val_accuracy: 0.7648 Epoch 37/40 65/65 [==============================] - 12s 185ms/step - loss: 0.4958 - accuracy: 0.8230 - val_loss: 0.5518 - val_accuracy: 0.8034 Epoch 38/40 65/65 [==============================] - 12s 188ms/step - loss: 0.4931 - accuracy: 0.8166 - val_loss: 0.5952 - val_accuracy: 0.7750 Epoch 39/40 65/65 [==============================] - 13s 207ms/step - loss: 0.4759 - accuracy: 0.8220 - val_loss: 0.6290 - val_accuracy: 0.7932 Epoch 40/40 65/65 [==============================] - 14s 215ms/step - loss: 0.4899 - accuracy: 0.8157 - val_loss: 0.5530 - val_accuracy: 0.7898
# Visualization of the learning curves
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.ylim([0.0, 2.0])
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend(['train', 'valid'])
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.ylim([0.5, 1.0])
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(['train', 'valid'])
<matplotlib.legend.Legend at 0x1cc18b1d610>
The validation accuracy seems more stable than before.
In conclusion: as we expected, data augmentation partially resolves the problem of over fitting, and achieves better validation accuracy. This of course came at the cost of lower performances on the training set. We will tackle this issue by increasing the model complexity.
As a first thing, we are going to add a third hidden layer of 128 neurons.
# Architecture definition
inputs = keras.Input((None,None,3))
x = inputs
x = keras.layers.RandomCrop(224, 224)(x)
x = keras.layers.RandomFlip(mode='horizontal')(x)
x = keras.layers.RandomContrast(0.25)(x)
x = keras.layers.Conv2D(32, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Conv2D(64, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Conv2D(128, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.GlobalMaxPooling2D()(x)
outputs = keras.layers.Dense(num_classes, activation="softmax")(x)
net = keras.Model(inputs, outputs)
# Compile the model for training
net.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.RMSprop(learning_rate=0.0005),
metrics=['accuracy'])
# Model training
history = net.fit(train_ds_256,
epochs=40,
validation_data=val_ds)
Epoch 1/40 74/74 [==============================] - 9s 104ms/step - loss: 1.1801 - accuracy: 0.5615 - val_loss: 2.9854 - val_accuracy: 0.3101 Epoch 2/40 74/74 [==============================] - 8s 107ms/step - loss: 0.8641 - accuracy: 0.6662 - val_loss: 1.1181 - val_accuracy: 0.5537 Epoch 3/40 74/74 [==============================] - 9s 112ms/step - loss: 0.7560 - accuracy: 0.7071 - val_loss: 1.0258 - val_accuracy: 0.6167 Epoch 4/40 74/74 [==============================] - 8s 110ms/step - loss: 0.6986 - accuracy: 0.7335 - val_loss: 0.8233 - val_accuracy: 0.6780 Epoch 5/40 74/74 [==============================] - 8s 109ms/step - loss: 0.6259 - accuracy: 0.7548 - val_loss: 0.9193 - val_accuracy: 0.6968 Epoch 6/40 74/74 [==============================] - 8s 105ms/step - loss: 0.5955 - accuracy: 0.7850 - val_loss: 0.7864 - val_accuracy: 0.7138 Epoch 7/40 74/74 [==============================] - 8s 105ms/step - loss: 0.5705 - accuracy: 0.7914 - val_loss: 0.6738 - val_accuracy: 0.7376 Epoch 8/40 74/74 [==============================] - 8s 106ms/step - loss: 0.5586 - accuracy: 0.7884 - val_loss: 0.6647 - val_accuracy: 0.7530 Epoch 9/40 74/74 [==============================] - 8s 105ms/step - loss: 0.5033 - accuracy: 0.8165 - val_loss: 0.7908 - val_accuracy: 0.7138 Epoch 10/40 74/74 [==============================] - 8s 106ms/step - loss: 0.4942 - accuracy: 0.8131 - val_loss: 0.6498 - val_accuracy: 0.7394 Epoch 11/40 74/74 [==============================] - 8s 106ms/step - loss: 0.4764 - accuracy: 0.8208 - val_loss: 0.6490 - val_accuracy: 0.7888 Epoch 12/40 74/74 [==============================] - 8s 106ms/step - loss: 0.4443 - accuracy: 0.8306 - val_loss: 0.6542 - val_accuracy: 0.7496 Epoch 13/40 74/74 [==============================] - 8s 109ms/step - loss: 0.4315 - accuracy: 0.8370 - val_loss: 0.9572 - val_accuracy: 0.6542 Epoch 14/40 74/74 [==============================] - 9s 127ms/step - loss: 0.4178 - accuracy: 0.8467 - val_loss: 0.6553 - val_accuracy: 0.7768 Epoch 15/40 74/74 [==============================] - 10s 135ms/step - loss: 0.4019 - accuracy: 0.8570 - val_loss: 0.6063 - val_accuracy: 0.7853 Epoch 16/40 74/74 [==============================] - 11s 143ms/step - loss: 0.3753 - accuracy: 0.8616 - val_loss: 0.5881 - val_accuracy: 0.7751 Epoch 17/40 74/74 [==============================] - 11s 147ms/step - loss: 0.3722 - accuracy: 0.8693 - val_loss: 0.5423 - val_accuracy: 0.7888 Epoch 18/40 74/74 [==============================] - 11s 152ms/step - loss: 0.3640 - accuracy: 0.8778 - val_loss: 0.6124 - val_accuracy: 0.7598 Epoch 19/40 74/74 [==============================] - 12s 166ms/step - loss: 0.3582 - accuracy: 0.8770 - val_loss: 0.5808 - val_accuracy: 0.7922 Epoch 20/40 74/74 [==============================] - 12s 160ms/step - loss: 0.3224 - accuracy: 0.8799 - val_loss: 0.5237 - val_accuracy: 0.8177 Epoch 21/40 74/74 [==============================] - 12s 162ms/step - loss: 0.3214 - accuracy: 0.8851 - val_loss: 0.5256 - val_accuracy: 0.8092 Epoch 22/40 74/74 [==============================] - 13s 180ms/step - loss: 0.3229 - accuracy: 0.8872 - val_loss: 0.5818 - val_accuracy: 0.7751 Epoch 23/40 74/74 [==============================] - 13s 177ms/step - loss: 0.3120 - accuracy: 0.8936 - val_loss: 0.5717 - val_accuracy: 0.7785 Epoch 24/40 74/74 [==============================] - 12s 166ms/step - loss: 0.2927 - accuracy: 0.8948 - val_loss: 0.5214 - val_accuracy: 0.8126 Epoch 25/40 74/74 [==============================] - 14s 184ms/step - loss: 0.2820 - accuracy: 0.9017 - val_loss: 0.4979 - val_accuracy: 0.8313 Epoch 26/40 74/74 [==============================] - 14s 189ms/step - loss: 0.2875 - accuracy: 0.9034 - val_loss: 0.5901 - val_accuracy: 0.7649 Epoch 27/40 74/74 [==============================] - 15s 201ms/step - loss: 0.2771 - accuracy: 0.9012 - val_loss: 0.6517 - val_accuracy: 0.7700 Epoch 28/40 74/74 [==============================] - 17s 228ms/step - loss: 0.2645 - accuracy: 0.9072 - val_loss: 0.5557 - val_accuracy: 0.7785 Epoch 29/40 74/74 [==============================] - 16s 211ms/step - loss: 0.2541 - accuracy: 0.9170 - val_loss: 0.5317 - val_accuracy: 0.7871 Epoch 30/40 74/74 [==============================] - 15s 206ms/step - loss: 0.2428 - accuracy: 0.9212 - val_loss: 0.4973 - val_accuracy: 0.8143 Epoch 31/40 74/74 [==============================] - 14s 195ms/step - loss: 0.2525 - accuracy: 0.9127 - val_loss: 0.6951 - val_accuracy: 0.7700 Epoch 32/40 74/74 [==============================] - 15s 197ms/step - loss: 0.2427 - accuracy: 0.9127 - val_loss: 0.5116 - val_accuracy: 0.8143 Epoch 33/40 74/74 [==============================] - 15s 201ms/step - loss: 0.2192 - accuracy: 0.9276 - val_loss: 0.6174 - val_accuracy: 0.7871 Epoch 34/40 74/74 [==============================] - 15s 205ms/step - loss: 0.2184 - accuracy: 0.9268 - val_loss: 0.5795 - val_accuracy: 0.7922 Epoch 35/40 74/74 [==============================] - 16s 218ms/step - loss: 0.2221 - accuracy: 0.9242 - val_loss: 0.5509 - val_accuracy: 0.7836 Epoch 36/40 74/74 [==============================] - 15s 197ms/step - loss: 0.2219 - accuracy: 0.9268 - val_loss: 0.4793 - val_accuracy: 0.8177 Epoch 37/40 74/74 [==============================] - 15s 197ms/step - loss: 0.2011 - accuracy: 0.9383 - val_loss: 0.5662 - val_accuracy: 0.8075 Epoch 38/40 74/74 [==============================] - 15s 205ms/step - loss: 0.1995 - accuracy: 0.9361 - val_loss: 0.5317 - val_accuracy: 0.7973 Epoch 39/40 74/74 [==============================] - 16s 219ms/step - loss: 0.2013 - accuracy: 0.9353 - val_loss: 0.4922 - val_accuracy: 0.8126 Epoch 40/40 74/74 [==============================] - 15s 207ms/step - loss: 0.1946 - accuracy: 0.9378 - val_loss: 0.5878 - val_accuracy: 0.7990
# Visualization of the learning curves
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.ylim([0.0, 2.0])
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend(['train', 'valid'])
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.ylim([0.5, 1.0])
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(['train', 'valid'])
<matplotlib.legend.Legend at 0x29195eb15e0>
To fights this variability in validation accuracy as the epoches pass, we are going to introduce a time-decaying learning rate.
# Architecture definition
inputs = keras.Input((None,None,3))
x = inputs
x = keras.layers.RandomCrop(224, 224)(x)
x = keras.layers.RandomFlip(mode='horizontal')(x)
x = keras.layers.RandomContrast(0.25)(x)
x = keras.layers.Conv2D(32, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Conv2D(64, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Conv2D(128, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.GlobalMaxPooling2D()(x)
outputs = keras.layers.Dense(num_classes, activation="softmax")(x)
net = keras.Model(inputs, outputs)
callback = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)
lr_schedule = keras.optimizers.schedules.InverseTimeDecay(
initial_learning_rate = 0.0005,
decay_steps = 65,
decay_rate = 0.08)
optimizer = keras.optimizers.RMSprop(learning_rate=lr_schedule)
net.compile(loss=keras.losses.categorical_crossentropy,
optimizer=optimizer,
metrics=['accuracy'])
# Model training
history = net.fit(train_ds_256,
epochs=80,
validation_data=val_ds,
callbacks=[callback])
Epoch 1/80 65/65 [==============================] - 7s 91ms/step - loss: 1.2730 - accuracy: 0.5263 - val_loss: 1.6327 - val_accuracy: 0.3432 Epoch 2/80 65/65 [==============================] - 6s 87ms/step - loss: 0.8948 - accuracy: 0.6445 - val_loss: 1.0282 - val_accuracy: 0.5977 Epoch 3/80 65/65 [==============================] - 6s 87ms/step - loss: 0.7678 - accuracy: 0.7067 - val_loss: 0.7859 - val_accuracy: 0.7114 Epoch 4/80 65/65 [==============================] - 6s 92ms/step - loss: 0.7034 - accuracy: 0.7354 - val_loss: 0.8250 - val_accuracy: 0.6841 Epoch 5/80 65/65 [==============================] - 7s 100ms/step - loss: 0.6387 - accuracy: 0.7665 - val_loss: 0.7197 - val_accuracy: 0.7205 Epoch 6/80 65/65 [==============================] - 7s 103ms/step - loss: 0.6156 - accuracy: 0.7690 - val_loss: 0.8018 - val_accuracy: 0.7080 Epoch 7/80 65/65 [==============================] - 7s 105ms/step - loss: 0.5696 - accuracy: 0.7884 - val_loss: 0.8430 - val_accuracy: 0.6841 Epoch 8/80 65/65 [==============================] - 7s 104ms/step - loss: 0.5270 - accuracy: 0.8054 - val_loss: 0.6586 - val_accuracy: 0.7523 Epoch 9/80 65/65 [==============================] - 7s 104ms/step - loss: 0.4984 - accuracy: 0.8113 - val_loss: 0.6562 - val_accuracy: 0.7432 Epoch 10/80 65/65 [==============================] - 7s 105ms/step - loss: 0.5081 - accuracy: 0.8127 - val_loss: 0.7417 - val_accuracy: 0.7182 Epoch 11/80 65/65 [==============================] - 7s 107ms/step - loss: 0.4846 - accuracy: 0.8322 - val_loss: 0.7101 - val_accuracy: 0.7466 Epoch 12/80 65/65 [==============================] - 7s 108ms/step - loss: 0.4498 - accuracy: 0.8478 - val_loss: 0.5766 - val_accuracy: 0.7795 Epoch 13/80 65/65 [==============================] - 7s 109ms/step - loss: 0.4265 - accuracy: 0.8512 - val_loss: 0.6581 - val_accuracy: 0.7545 Epoch 14/80 65/65 [==============================] - 7s 105ms/step - loss: 0.4314 - accuracy: 0.8400 - val_loss: 0.5665 - val_accuracy: 0.7886 Epoch 15/80 65/65 [==============================] - 7s 106ms/step - loss: 0.4116 - accuracy: 0.8614 - val_loss: 0.5597 - val_accuracy: 0.7807 Epoch 16/80 65/65 [==============================] - 7s 106ms/step - loss: 0.3953 - accuracy: 0.8628 - val_loss: 0.5849 - val_accuracy: 0.7670 Epoch 17/80 65/65 [==============================] - 7s 106ms/step - loss: 0.3808 - accuracy: 0.8619 - val_loss: 0.5355 - val_accuracy: 0.7943 Epoch 18/80 65/65 [==============================] - 7s 109ms/step - loss: 0.3804 - accuracy: 0.8672 - val_loss: 0.5708 - val_accuracy: 0.7682 Epoch 19/80 65/65 [==============================] - 9s 132ms/step - loss: 0.3759 - accuracy: 0.8760 - val_loss: 0.6136 - val_accuracy: 0.7795 Epoch 20/80 65/65 [==============================] - 10s 156ms/step - loss: 0.3449 - accuracy: 0.8925 - val_loss: 0.5439 - val_accuracy: 0.7966 Epoch 21/80 65/65 [==============================] - 11s 174ms/step - loss: 0.3600 - accuracy: 0.8760 - val_loss: 0.5576 - val_accuracy: 0.7852 Epoch 22/80 65/65 [==============================] - 12s 181ms/step - loss: 0.3387 - accuracy: 0.8857 - val_loss: 0.6080 - val_accuracy: 0.7693 Epoch 23/80 65/65 [==============================] - 13s 202ms/step - loss: 0.3291 - accuracy: 0.8901 - val_loss: 0.5611 - val_accuracy: 0.7955 Epoch 24/80 65/65 [==============================] - 14s 207ms/step - loss: 0.3314 - accuracy: 0.8872 - val_loss: 0.5657 - val_accuracy: 0.7886 Epoch 25/80 65/65 [==============================] - 15s 229ms/step - loss: 0.3224 - accuracy: 0.8954 - val_loss: 0.5143 - val_accuracy: 0.8091 Epoch 26/80 65/65 [==============================] - 15s 223ms/step - loss: 0.3132 - accuracy: 0.8945 - val_loss: 0.5261 - val_accuracy: 0.8034 Epoch 27/80 65/65 [==============================] - 15s 232ms/step - loss: 0.3005 - accuracy: 0.9018 - val_loss: 0.5106 - val_accuracy: 0.8216 Epoch 28/80 65/65 [==============================] - 15s 235ms/step - loss: 0.3048 - accuracy: 0.9003 - val_loss: 0.5258 - val_accuracy: 0.8114 Epoch 29/80 65/65 [==============================] - 16s 238ms/step - loss: 0.2931 - accuracy: 0.9086 - val_loss: 0.5045 - val_accuracy: 0.8091 Epoch 30/80 65/65 [==============================] - 15s 236ms/step - loss: 0.2900 - accuracy: 0.9095 - val_loss: 0.5242 - val_accuracy: 0.7898 Epoch 31/80 65/65 [==============================] - 16s 237ms/step - loss: 0.2767 - accuracy: 0.9183 - val_loss: 0.5198 - val_accuracy: 0.8034 Epoch 32/80 65/65 [==============================] - 15s 236ms/step - loss: 0.2764 - accuracy: 0.9129 - val_loss: 0.4957 - val_accuracy: 0.8227 Epoch 33/80 65/65 [==============================] - 15s 236ms/step - loss: 0.2578 - accuracy: 0.9202 - val_loss: 0.5045 - val_accuracy: 0.8091 Epoch 34/80 65/65 [==============================] - 15s 236ms/step - loss: 0.2710 - accuracy: 0.9163 - val_loss: 0.5075 - val_accuracy: 0.8125 Epoch 35/80 65/65 [==============================] - 15s 236ms/step - loss: 0.2573 - accuracy: 0.9207 - val_loss: 0.4790 - val_accuracy: 0.8193 Epoch 36/80 65/65 [==============================] - 15s 237ms/step - loss: 0.2516 - accuracy: 0.9270 - val_loss: 0.6071 - val_accuracy: 0.7670 Epoch 37/80 65/65 [==============================] - 16s 237ms/step - loss: 0.2538 - accuracy: 0.9256 - val_loss: 0.5329 - val_accuracy: 0.8023 Epoch 38/80 65/65 [==============================] - 15s 237ms/step - loss: 0.2574 - accuracy: 0.9168 - val_loss: 0.5426 - val_accuracy: 0.7920 Epoch 39/80 65/65 [==============================] - 16s 237ms/step - loss: 0.2364 - accuracy: 0.9373 - val_loss: 0.5345 - val_accuracy: 0.7886 Epoch 40/80 65/65 [==============================] - 16s 237ms/step - loss: 0.2593 - accuracy: 0.9163 - val_loss: 0.5236 - val_accuracy: 0.8000 Epoch 41/80 65/65 [==============================] - 16s 237ms/step - loss: 0.2454 - accuracy: 0.9241 - val_loss: 0.4954 - val_accuracy: 0.8125 Epoch 42/80 65/65 [==============================] - 16s 237ms/step - loss: 0.2382 - accuracy: 0.9334 - val_loss: 0.5312 - val_accuracy: 0.8045 Epoch 43/80 65/65 [==============================] - 16s 237ms/step - loss: 0.2326 - accuracy: 0.9334 - val_loss: 0.5053 - val_accuracy: 0.8057 Epoch 44/80 65/65 [==============================] - 16s 237ms/step - loss: 0.2251 - accuracy: 0.9382 - val_loss: 0.4967 - val_accuracy: 0.8136 Epoch 45/80 65/65 [==============================] - 16s 238ms/step - loss: 0.2296 - accuracy: 0.9329 - val_loss: 0.4888 - val_accuracy: 0.8205
# Visualization of the learning curves
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.ylim([0.0, 2.0])
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend(['train', 'valid'])
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.ylim([0.5, 1.0])
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(['train', 'valid'])
<matplotlib.legend.Legend at 0x216063bdfa0>
The addition of the Time-decaying Learning Rate helped to increase the accuracy of the validation set even at higher epochs.
# Architecture definition
inputs = keras.Input((None,None,3))
x = inputs
x = keras.layers.RandomCrop(224, 224)(x)
x = keras.layers.RandomFlip(mode='horizontal')(x)
x = keras.layers.RandomContrast(0.25)(x)
x = keras.layers.Conv2D(32, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Conv2D(64, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Conv2D(128, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.GlobalMaxPooling2D()(x)
outputs = keras.layers.Dense(num_classes, activation="softmax")(x)
net = keras.Model(inputs, outputs)
callback = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)
lr_schedule = keras.optimizers.schedules.InverseTimeDecay(
initial_learning_rate = 0.0005,
decay_steps = 65,
decay_rate = 0.08)
optimizer = keras.optimizers.Adam(learning_rate=lr_schedule)
net.compile(loss=keras.losses.categorical_crossentropy,
optimizer=optimizer,
metrics=['accuracy'])
# Model training
history = net.fit(train_ds_256,
epochs=80,
validation_data=val_ds,
callbacks=[callback])
Epoch 1/80 65/65 [==============================] - 7s 86ms/step - loss: 1.4620 - accuracy: 0.4912 - val_loss: 1.4347 - val_accuracy: 0.4364 Epoch 2/80 65/65 [==============================] - 6s 85ms/step - loss: 0.8596 - accuracy: 0.6644 - val_loss: 0.9720 - val_accuracy: 0.6023 Epoch 3/80 65/65 [==============================] - 6s 84ms/step - loss: 0.7387 - accuracy: 0.7237 - val_loss: 0.7942 - val_accuracy: 0.7114 Epoch 4/80 65/65 [==============================] - 6s 85ms/step - loss: 0.6981 - accuracy: 0.7349 - val_loss: 0.7216 - val_accuracy: 0.7420 Epoch 5/80 65/65 [==============================] - 6s 85ms/step - loss: 0.6538 - accuracy: 0.7554 - val_loss: 0.7498 - val_accuracy: 0.7182 Epoch 6/80 65/65 [==============================] - 6s 87ms/step - loss: 0.5931 - accuracy: 0.7899 - val_loss: 0.7111 - val_accuracy: 0.7295 Epoch 7/80 65/65 [==============================] - 6s 86ms/step - loss: 0.5946 - accuracy: 0.7865 - val_loss: 0.7053 - val_accuracy: 0.7420 Epoch 8/80 65/65 [==============================] - 6s 86ms/step - loss: 0.5534 - accuracy: 0.8025 - val_loss: 0.7194 - val_accuracy: 0.7170 Epoch 9/80 65/65 [==============================] - 6s 86ms/step - loss: 0.5324 - accuracy: 0.8084 - val_loss: 0.7671 - val_accuracy: 0.7182 Epoch 10/80 65/65 [==============================] - 6s 88ms/step - loss: 0.4909 - accuracy: 0.8268 - val_loss: 0.6170 - val_accuracy: 0.7682 Epoch 11/80 65/65 [==============================] - 6s 92ms/step - loss: 0.4690 - accuracy: 0.8419 - val_loss: 0.6160 - val_accuracy: 0.7705 Epoch 12/80 65/65 [==============================] - 6s 95ms/step - loss: 0.4457 - accuracy: 0.8487 - val_loss: 0.5988 - val_accuracy: 0.7830 Epoch 13/80 65/65 [==============================] - 7s 102ms/step - loss: 0.4416 - accuracy: 0.8434 - val_loss: 0.6491 - val_accuracy: 0.7614 Epoch 14/80 65/65 [==============================] - 7s 103ms/step - loss: 0.4405 - accuracy: 0.8487 - val_loss: 0.5738 - val_accuracy: 0.7841 Epoch 15/80 65/65 [==============================] - 7s 104ms/step - loss: 0.4155 - accuracy: 0.8580 - val_loss: 0.5651 - val_accuracy: 0.7966 Epoch 16/80 65/65 [==============================] - 7s 104ms/step - loss: 0.4064 - accuracy: 0.8624 - val_loss: 0.6185 - val_accuracy: 0.7625 Epoch 17/80 65/65 [==============================] - 7s 104ms/step - loss: 0.4041 - accuracy: 0.8604 - val_loss: 0.5421 - val_accuracy: 0.7852 Epoch 18/80 65/65 [==============================] - 7s 104ms/step - loss: 0.3901 - accuracy: 0.8658 - val_loss: 0.5831 - val_accuracy: 0.7898 Epoch 19/80 65/65 [==============================] - 7s 104ms/step - loss: 0.3833 - accuracy: 0.8716 - val_loss: 0.5546 - val_accuracy: 0.7932 Epoch 20/80 65/65 [==============================] - 7s 104ms/step - loss: 0.3771 - accuracy: 0.8726 - val_loss: 0.5794 - val_accuracy: 0.7898 Epoch 21/80 65/65 [==============================] - 7s 104ms/step - loss: 0.3504 - accuracy: 0.8842 - val_loss: 0.5652 - val_accuracy: 0.7795 Epoch 22/80 65/65 [==============================] - 7s 104ms/step - loss: 0.3554 - accuracy: 0.8784 - val_loss: 0.5040 - val_accuracy: 0.8102 Epoch 23/80 65/65 [==============================] - 7s 104ms/step - loss: 0.3383 - accuracy: 0.8911 - val_loss: 0.5171 - val_accuracy: 0.8045 Epoch 24/80 65/65 [==============================] - 7s 104ms/step - loss: 0.3350 - accuracy: 0.8881 - val_loss: 0.5052 - val_accuracy: 0.8102 Epoch 25/80 65/65 [==============================] - 7s 104ms/step - loss: 0.3390 - accuracy: 0.8935 - val_loss: 0.4899 - val_accuracy: 0.8170 Epoch 26/80 65/65 [==============================] - 7s 104ms/step - loss: 0.3239 - accuracy: 0.8998 - val_loss: 0.5045 - val_accuracy: 0.8057 Epoch 27/80 65/65 [==============================] - 7s 104ms/step - loss: 0.3203 - accuracy: 0.8964 - val_loss: 0.4735 - val_accuracy: 0.8261 Epoch 28/80 65/65 [==============================] - 7s 105ms/step - loss: 0.3170 - accuracy: 0.9003 - val_loss: 0.5107 - val_accuracy: 0.8205 Epoch 29/80 65/65 [==============================] - 7s 107ms/step - loss: 0.3026 - accuracy: 0.9018 - val_loss: 0.5015 - val_accuracy: 0.8273 Epoch 30/80 65/65 [==============================] - 7s 105ms/step - loss: 0.2982 - accuracy: 0.9047 - val_loss: 0.4851 - val_accuracy: 0.8102 Epoch 31/80 65/65 [==============================] - 7s 104ms/step - loss: 0.2923 - accuracy: 0.9134 - val_loss: 0.5089 - val_accuracy: 0.8080 Epoch 32/80 65/65 [==============================] - 7s 105ms/step - loss: 0.2791 - accuracy: 0.9110 - val_loss: 0.5080 - val_accuracy: 0.8205 Epoch 33/80 65/65 [==============================] - 7s 105ms/step - loss: 0.2858 - accuracy: 0.9042 - val_loss: 0.4798 - val_accuracy: 0.8250 Epoch 34/80 65/65 [==============================] - 7s 104ms/step - loss: 0.2953 - accuracy: 0.9061 - val_loss: 0.5145 - val_accuracy: 0.8034 Epoch 35/80 65/65 [==============================] - 7s 105ms/step - loss: 0.2820 - accuracy: 0.9076 - val_loss: 0.4725 - val_accuracy: 0.8193 Epoch 36/80 65/65 [==============================] - 7s 105ms/step - loss: 0.2889 - accuracy: 0.9071 - val_loss: 0.4865 - val_accuracy: 0.8193 Epoch 37/80 65/65 [==============================] - 7s 105ms/step - loss: 0.2847 - accuracy: 0.9095 - val_loss: 0.4739 - val_accuracy: 0.8227 Epoch 38/80 65/65 [==============================] - 7s 105ms/step - loss: 0.2686 - accuracy: 0.9227 - val_loss: 0.4883 - val_accuracy: 0.8227 Epoch 39/80 65/65 [==============================] - 7s 105ms/step - loss: 0.2637 - accuracy: 0.9212 - val_loss: 0.4806 - val_accuracy: 0.8239 Epoch 40/80 65/65 [==============================] - 7s 105ms/step - loss: 0.2555 - accuracy: 0.9280 - val_loss: 0.4735 - val_accuracy: 0.8318 Epoch 41/80 65/65 [==============================] - 7s 106ms/step - loss: 0.2522 - accuracy: 0.9236 - val_loss: 0.4649 - val_accuracy: 0.8318 Epoch 42/80 65/65 [==============================] - 7s 106ms/step - loss: 0.2510 - accuracy: 0.9285 - val_loss: 0.4739 - val_accuracy: 0.8205 Epoch 43/80 65/65 [==============================] - 7s 105ms/step - loss: 0.2530 - accuracy: 0.9261 - val_loss: 0.4700 - val_accuracy: 0.8239 Epoch 44/80 65/65 [==============================] - 7s 105ms/step - loss: 0.2446 - accuracy: 0.9222 - val_loss: 0.4673 - val_accuracy: 0.8227 Epoch 45/80 65/65 [==============================] - 7s 104ms/step - loss: 0.2506 - accuracy: 0.9251 - val_loss: 0.4629 - val_accuracy: 0.8295 Epoch 46/80 65/65 [==============================] - 7s 105ms/step - loss: 0.2394 - accuracy: 0.9246 - val_loss: 0.4609 - val_accuracy: 0.8352 Epoch 47/80 65/65 [==============================] - 7s 106ms/step - loss: 0.2323 - accuracy: 0.9397 - val_loss: 0.4955 - val_accuracy: 0.8205 Epoch 48/80 65/65 [==============================] - 7s 111ms/step - loss: 0.2475 - accuracy: 0.9241 - val_loss: 0.4819 - val_accuracy: 0.8170 Epoch 49/80 65/65 [==============================] - 8s 116ms/step - loss: 0.2286 - accuracy: 0.9329 - val_loss: 0.4684 - val_accuracy: 0.8295 Epoch 50/80 65/65 [==============================] - 8s 119ms/step - loss: 0.2250 - accuracy: 0.9392 - val_loss: 0.4593 - val_accuracy: 0.8307 Epoch 51/80 65/65 [==============================] - 8s 121ms/step - loss: 0.2306 - accuracy: 0.9295 - val_loss: 0.4683 - val_accuracy: 0.8261 Epoch 52/80 65/65 [==============================] - 8s 125ms/step - loss: 0.2263 - accuracy: 0.9387 - val_loss: 0.4503 - val_accuracy: 0.8375 Epoch 53/80 65/65 [==============================] - 8s 126ms/step - loss: 0.2178 - accuracy: 0.9470 - val_loss: 0.4706 - val_accuracy: 0.8273 Epoch 54/80 65/65 [==============================] - 9s 140ms/step - loss: 0.2223 - accuracy: 0.9402 - val_loss: 0.4532 - val_accuracy: 0.8352 Epoch 55/80 65/65 [==============================] - 8s 128ms/step - loss: 0.2165 - accuracy: 0.9416 - val_loss: 0.4444 - val_accuracy: 0.8375 Epoch 56/80 65/65 [==============================] - 9s 145ms/step - loss: 0.2212 - accuracy: 0.9314 - val_loss: 0.4455 - val_accuracy: 0.8420 Epoch 57/80 65/65 [==============================] - 9s 144ms/step - loss: 0.2169 - accuracy: 0.9441 - val_loss: 0.4498 - val_accuracy: 0.8341 Epoch 58/80 65/65 [==============================] - 9s 145ms/step - loss: 0.2058 - accuracy: 0.9426 - val_loss: 0.4391 - val_accuracy: 0.8409 Epoch 59/80 65/65 [==============================] - 9s 138ms/step - loss: 0.2171 - accuracy: 0.9377 - val_loss: 0.4656 - val_accuracy: 0.8250 Epoch 60/80 65/65 [==============================] - 9s 144ms/step - loss: 0.2022 - accuracy: 0.9553 - val_loss: 0.4503 - val_accuracy: 0.8386 Epoch 61/80 65/65 [==============================] - 10s 148ms/step - loss: 0.2149 - accuracy: 0.9407 - val_loss: 0.4642 - val_accuracy: 0.8216 Epoch 62/80 65/65 [==============================] - 10s 146ms/step - loss: 0.1976 - accuracy: 0.9416 - val_loss: 0.4440 - val_accuracy: 0.8330 Epoch 63/80 65/65 [==============================] - 10s 150ms/step - loss: 0.2050 - accuracy: 0.9421 - val_loss: 0.4419 - val_accuracy: 0.8364 Epoch 64/80 65/65 [==============================] - 10s 148ms/step - loss: 0.1968 - accuracy: 0.9465 - val_loss: 0.4427 - val_accuracy: 0.8341 Epoch 65/80 65/65 [==============================] - 10s 153ms/step - loss: 0.1978 - accuracy: 0.9446 - val_loss: 0.4402 - val_accuracy: 0.8455 Epoch 66/80 65/65 [==============================] - 10s 152ms/step - loss: 0.1881 - accuracy: 0.9523 - val_loss: 0.4467 - val_accuracy: 0.8375 Epoch 67/80 65/65 [==============================] - 10s 159ms/step - loss: 0.1904 - accuracy: 0.9528 - val_loss: 0.4531 - val_accuracy: 0.8250 Epoch 68/80 65/65 [==============================] - 11s 164ms/step - loss: 0.2093 - accuracy: 0.9373 - val_loss: 0.4409 - val_accuracy: 0.8341
# Visualization of the learning curves
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.ylim([0.0, 2.0])
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend(['train', 'valid'])
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.ylim([0.5, 1.0])
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(['train', 'valid'])
<matplotlib.legend.Legend at 0x2301fae4670>
By changing the optimizer to Adam, we have a notable increase in validation accuracy.
Even though the model is not technically overfitting, since the two curves are not diverging, we are going to test some Regularization methods. We do this in the hope that, by closing the gap between validation and train, we will be able to increase the validation accuracy further.
# Architecture definition
inputs = keras.Input((None,None,3))
x = inputs
x = keras.layers.RandomCrop(224, 224)(x)
x = keras.layers.RandomFlip(mode='horizontal')(x)
x = keras.layers.RandomContrast(0.25)(x)
x = keras.layers.Conv2D(32, 3, padding="same", kernel_regularizer=tf.keras.regularizers.l2(0.001))(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Conv2D(64, 3, padding="same", kernel_regularizer=tf.keras.regularizers.l2(0.001))(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Conv2D(128, 3, padding="same", kernel_regularizer=tf.keras.regularizers.l2(0.001))(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.GlobalMaxPooling2D()(x)
outputs = keras.layers.Dense(num_classes, activation="softmax", kernel_regularizer=tf.keras.regularizers.l2(0.001))(x)
net = keras.Model(inputs, outputs)
callback = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)
lr_schedule = keras.optimizers.schedules.InverseTimeDecay(
initial_learning_rate = 0.0005,
decay_steps = 65,
decay_rate = 0.08)
optimizer = keras.optimizers.Adam(learning_rate=lr_schedule)
net.compile(loss=keras.losses.categorical_crossentropy,
optimizer=optimizer,
metrics=['accuracy'])
# Model training
history = net.fit(train_ds_256,
epochs=80,
validation_data=val_ds,
callbacks=[callback])
Epoch 1/80 65/65 [==============================] - 7s 90ms/step - loss: 1.4885 - accuracy: 0.5019 - val_loss: 3.1283 - val_accuracy: 0.2250 Epoch 2/80 65/65 [==============================] - 6s 86ms/step - loss: 1.0031 - accuracy: 0.6615 - val_loss: 1.7334 - val_accuracy: 0.3716 Epoch 3/80 65/65 [==============================] - 6s 86ms/step - loss: 0.9414 - accuracy: 0.6980 - val_loss: 1.0869 - val_accuracy: 0.6523 Epoch 4/80 65/65 [==============================] - 6s 86ms/step - loss: 0.8583 - accuracy: 0.7247 - val_loss: 0.8709 - val_accuracy: 0.7330 Epoch 5/80 65/65 [==============================] - 6s 88ms/step - loss: 0.8036 - accuracy: 0.7466 - val_loss: 0.9929 - val_accuracy: 0.6648 Epoch 6/80 65/65 [==============================] - 6s 98ms/step - loss: 0.7671 - accuracy: 0.7665 - val_loss: 0.8278 - val_accuracy: 0.7364 Epoch 7/80 65/65 [==============================] - 7s 105ms/step - loss: 0.7624 - accuracy: 0.7690 - val_loss: 0.8384 - val_accuracy: 0.7250 Epoch 8/80 65/65 [==============================] - 7s 106ms/step - loss: 0.7317 - accuracy: 0.7806 - val_loss: 0.8585 - val_accuracy: 0.7205 Epoch 9/80 65/65 [==============================] - 7s 106ms/step - loss: 0.7002 - accuracy: 0.7913 - val_loss: 0.9113 - val_accuracy: 0.7091 Epoch 10/80 65/65 [==============================] - 7s 106ms/step - loss: 0.6707 - accuracy: 0.8084 - val_loss: 0.7858 - val_accuracy: 0.7557 Epoch 11/80 65/65 [==============================] - 7s 105ms/step - loss: 0.6332 - accuracy: 0.8171 - val_loss: 0.7403 - val_accuracy: 0.7795 Epoch 12/80 65/65 [==============================] - 7s 106ms/step - loss: 0.6100 - accuracy: 0.8361 - val_loss: 0.7530 - val_accuracy: 0.7568 Epoch 13/80 65/65 [==============================] - 7s 106ms/step - loss: 0.6147 - accuracy: 0.8303 - val_loss: 0.7855 - val_accuracy: 0.7602 Epoch 14/80 65/65 [==============================] - 7s 106ms/step - loss: 0.5925 - accuracy: 0.8448 - val_loss: 0.7242 - val_accuracy: 0.7784 Epoch 15/80 65/65 [==============================] - 7s 106ms/step - loss: 0.5762 - accuracy: 0.8424 - val_loss: 0.7965 - val_accuracy: 0.7489 Epoch 16/80 65/65 [==============================] - 7s 106ms/step - loss: 0.5733 - accuracy: 0.8492 - val_loss: 0.7465 - val_accuracy: 0.7705 Epoch 17/80 65/65 [==============================] - 7s 109ms/step - loss: 0.5488 - accuracy: 0.8662 - val_loss: 0.8506 - val_accuracy: 0.7477 Epoch 18/80 65/65 [==============================] - 7s 106ms/step - loss: 0.5307 - accuracy: 0.8614 - val_loss: 0.7129 - val_accuracy: 0.7943 Epoch 19/80 65/65 [==============================] - 7s 108ms/step - loss: 0.5437 - accuracy: 0.8541 - val_loss: 0.7134 - val_accuracy: 0.7886 Epoch 20/80 65/65 [==============================] - 7s 106ms/step - loss: 0.5233 - accuracy: 0.8677 - val_loss: 0.6684 - val_accuracy: 0.7886 Epoch 21/80 65/65 [==============================] - 7s 107ms/step - loss: 0.5084 - accuracy: 0.8638 - val_loss: 0.6343 - val_accuracy: 0.8125 Epoch 22/80 65/65 [==============================] - 7s 106ms/step - loss: 0.4909 - accuracy: 0.8847 - val_loss: 0.6889 - val_accuracy: 0.7955 Epoch 23/80 65/65 [==============================] - 7s 106ms/step - loss: 0.4905 - accuracy: 0.8794 - val_loss: 0.6515 - val_accuracy: 0.8011 Epoch 24/80 65/65 [==============================] - 7s 106ms/step - loss: 0.4798 - accuracy: 0.8857 - val_loss: 0.6662 - val_accuracy: 0.8170 Epoch 25/80 65/65 [==============================] - 8s 115ms/step - loss: 0.4796 - accuracy: 0.8867 - val_loss: 0.6641 - val_accuracy: 0.7943 Epoch 26/80 65/65 [==============================] - 8s 125ms/step - loss: 0.4710 - accuracy: 0.8920 - val_loss: 0.6397 - val_accuracy: 0.8125 Epoch 27/80 65/65 [==============================] - 8s 128ms/step - loss: 0.4678 - accuracy: 0.8911 - val_loss: 0.6581 - val_accuracy: 0.8091 Epoch 28/80 65/65 [==============================] - 9s 137ms/step - loss: 0.4585 - accuracy: 0.8959 - val_loss: 0.6495 - val_accuracy: 0.8182 Epoch 29/80 65/65 [==============================] - 9s 135ms/step - loss: 0.4470 - accuracy: 0.9003 - val_loss: 0.6299 - val_accuracy: 0.8136 Epoch 30/80 65/65 [==============================] - 9s 145ms/step - loss: 0.4432 - accuracy: 0.9066 - val_loss: 0.6321 - val_accuracy: 0.8102 Epoch 31/80 65/65 [==============================] - 10s 147ms/step - loss: 0.4442 - accuracy: 0.9022 - val_loss: 0.6523 - val_accuracy: 0.8023 Epoch 32/80 65/65 [==============================] - 10s 155ms/step - loss: 0.4333 - accuracy: 0.9037 - val_loss: 0.6592 - val_accuracy: 0.7943 Epoch 33/80 65/65 [==============================] - 11s 173ms/step - loss: 0.4270 - accuracy: 0.9129 - val_loss: 0.6083 - val_accuracy: 0.8205 Epoch 34/80 65/65 [==============================] - 11s 173ms/step - loss: 0.4238 - accuracy: 0.9090 - val_loss: 0.6053 - val_accuracy: 0.8193 Epoch 35/80 65/65 [==============================] - 12s 185ms/step - loss: 0.4117 - accuracy: 0.9149 - val_loss: 0.6022 - val_accuracy: 0.8216 Epoch 36/80 65/65 [==============================] - 11s 175ms/step - loss: 0.4157 - accuracy: 0.9115 - val_loss: 0.6388 - val_accuracy: 0.8216 Epoch 37/80 65/65 [==============================] - 13s 193ms/step - loss: 0.4042 - accuracy: 0.9173 - val_loss: 0.6435 - val_accuracy: 0.8182 Epoch 38/80 65/65 [==============================] - 13s 198ms/step - loss: 0.3951 - accuracy: 0.9261 - val_loss: 0.6061 - val_accuracy: 0.8091 Epoch 39/80 65/65 [==============================] - 12s 185ms/step - loss: 0.4038 - accuracy: 0.9149 - val_loss: 0.5985 - val_accuracy: 0.8239 Epoch 40/80 65/65 [==============================] - 12s 188ms/step - loss: 0.3848 - accuracy: 0.9232 - val_loss: 0.5964 - val_accuracy: 0.8284 Epoch 41/80 65/65 [==============================] - 14s 209ms/step - loss: 0.3813 - accuracy: 0.9314 - val_loss: 0.6402 - val_accuracy: 0.8193 Epoch 42/80 65/65 [==============================] - 14s 214ms/step - loss: 0.3785 - accuracy: 0.9304 - val_loss: 0.6061 - val_accuracy: 0.8170 Epoch 43/80 65/65 [==============================] - 13s 200ms/step - loss: 0.3761 - accuracy: 0.9334 - val_loss: 0.5777 - val_accuracy: 0.8341 Epoch 44/80 65/65 [==============================] - 14s 215ms/step - loss: 0.3786 - accuracy: 0.9232 - val_loss: 0.5844 - val_accuracy: 0.8307 Epoch 45/80 65/65 [==============================] - 14s 216ms/step - loss: 0.3671 - accuracy: 0.9290 - val_loss: 0.5845 - val_accuracy: 0.8307 Epoch 46/80 65/65 [==============================] - 13s 203ms/step - loss: 0.3707 - accuracy: 0.9368 - val_loss: 0.5745 - val_accuracy: 0.8409 Epoch 47/80 65/65 [==============================] - 14s 217ms/step - loss: 0.3627 - accuracy: 0.9353 - val_loss: 0.5805 - val_accuracy: 0.8364 Epoch 48/80 65/65 [==============================] - 15s 223ms/step - loss: 0.3617 - accuracy: 0.9339 - val_loss: 0.5805 - val_accuracy: 0.8364 Epoch 49/80 65/65 [==============================] - 15s 228ms/step - loss: 0.3571 - accuracy: 0.9392 - val_loss: 0.5781 - val_accuracy: 0.8284 Epoch 50/80 65/65 [==============================] - 15s 233ms/step - loss: 0.3675 - accuracy: 0.9358 - val_loss: 0.5962 - val_accuracy: 0.8170 Epoch 51/80 65/65 [==============================] - 15s 235ms/step - loss: 0.3540 - accuracy: 0.9446 - val_loss: 0.5830 - val_accuracy: 0.8250 Epoch 52/80 65/65 [==============================] - 16s 238ms/step - loss: 0.3491 - accuracy: 0.9446 - val_loss: 0.5673 - val_accuracy: 0.8341 Epoch 53/80 65/65 [==============================] - 15s 237ms/step - loss: 0.3478 - accuracy: 0.9411 - val_loss: 0.5667 - val_accuracy: 0.8341 Epoch 54/80 65/65 [==============================] - 15s 235ms/step - loss: 0.3479 - accuracy: 0.9397 - val_loss: 0.5665 - val_accuracy: 0.8409 Epoch 55/80 65/65 [==============================] - 15s 237ms/step - loss: 0.3496 - accuracy: 0.9363 - val_loss: 0.5781 - val_accuracy: 0.8398 Epoch 56/80 65/65 [==============================] - 15s 237ms/step - loss: 0.3441 - accuracy: 0.9407 - val_loss: 0.5743 - val_accuracy: 0.8364 Epoch 57/80 65/65 [==============================] - 15s 237ms/step - loss: 0.3459 - accuracy: 0.9358 - val_loss: 0.5538 - val_accuracy: 0.8432 Epoch 58/80 65/65 [==============================] - 15s 237ms/step - loss: 0.3439 - accuracy: 0.9402 - val_loss: 0.5568 - val_accuracy: 0.8318 Epoch 59/80 65/65 [==============================] - 15s 237ms/step - loss: 0.3280 - accuracy: 0.9538 - val_loss: 0.5593 - val_accuracy: 0.8307 Epoch 60/80 65/65 [==============================] - 15s 237ms/step - loss: 0.3254 - accuracy: 0.9470 - val_loss: 0.5715 - val_accuracy: 0.8284 Epoch 61/80 65/65 [==============================] - 15s 237ms/step - loss: 0.3357 - accuracy: 0.9436 - val_loss: 0.6162 - val_accuracy: 0.8080 Epoch 62/80 65/65 [==============================] - 15s 237ms/step - loss: 0.3232 - accuracy: 0.9514 - val_loss: 0.5827 - val_accuracy: 0.8295 Epoch 63/80 65/65 [==============================] - 15s 237ms/step - loss: 0.3249 - accuracy: 0.9475 - val_loss: 0.5676 - val_accuracy: 0.8318 Epoch 64/80 65/65 [==============================] - 15s 237ms/step - loss: 0.3285 - accuracy: 0.9504 - val_loss: 0.5768 - val_accuracy: 0.8307 Epoch 65/80 65/65 [==============================] - 15s 237ms/step - loss: 0.3210 - accuracy: 0.9533 - val_loss: 0.5639 - val_accuracy: 0.8261 Epoch 66/80 65/65 [==============================] - 15s 237ms/step - loss: 0.3192 - accuracy: 0.9504 - val_loss: 0.5715 - val_accuracy: 0.8261 Epoch 67/80 65/65 [==============================] - 15s 237ms/step - loss: 0.3232 - accuracy: 0.9504 - val_loss: 0.5547 - val_accuracy: 0.8455
# Visualization of the learning curves
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.ylim([0.0, 2.0])
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend(['train', 'valid'])
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.ylim([0.5, 1.0])
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(['train', 'valid'])
<matplotlib.legend.Legend at 0x230205357f0>
The addition of a regularizer does not seem to benefit the model in a notable way. Other attempts were made (changing the parameter, using the L1 regularizer) but none of them brought a substantial improvement in the model quality. We are then going to try another regularization method: DropOut layers.
After Testing different combinations of Dropout layers, two were selected:
# Architecture definition
inputs = keras.Input((None,None,3))
x = inputs
x = keras.layers.RandomCrop(224, 224)(x)
x = keras.layers.RandomFlip(mode='horizontal')(x)
x = keras.layers.RandomContrast(0.25)(x)
x = keras.layers.Conv2D(32, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Conv2D(64, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.Conv2D(128, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.Dropout(0.2)(x)
x = keras.layers.GlobalMaxPooling2D()(x)
outputs = keras.layers.Dense(num_classes, activation="softmax")(x)
net = keras.Model(inputs, outputs)
callback = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)
lr_schedule = keras.optimizers.schedules.InverseTimeDecay(
initial_learning_rate = 0.0005,
decay_steps = 65,
decay_rate = 0.08)
optimizer = keras.optimizers.Adam(learning_rate=lr_schedule)
net.compile(loss=keras.losses.categorical_crossentropy,
optimizer=optimizer,
metrics=['accuracy'])
# Model training
history = net.fit(train_ds_256,
epochs=80,
validation_data=val_ds,
callbacks=[callback])
Epoch 1/80 65/65 [==============================] - 14s 194ms/step - loss: 1.4038 - accuracy: 0.5049 - val_loss: 1.5637 - val_accuracy: 0.4295 Epoch 2/80 65/65 [==============================] - 14s 215ms/step - loss: 0.9336 - accuracy: 0.6411 - val_loss: 1.1013 - val_accuracy: 0.5659 Epoch 3/80 65/65 [==============================] - 13s 197ms/step - loss: 0.8578 - accuracy: 0.6697 - val_loss: 0.9209 - val_accuracy: 0.6307 Epoch 4/80 65/65 [==============================] - 14s 213ms/step - loss: 0.7904 - accuracy: 0.7004 - val_loss: 0.7873 - val_accuracy: 0.7057 Epoch 5/80 65/65 [==============================] - 14s 213ms/step - loss: 0.7285 - accuracy: 0.7257 - val_loss: 0.7394 - val_accuracy: 0.7261 Epoch 6/80 65/65 [==============================] - 15s 225ms/step - loss: 0.7166 - accuracy: 0.7354 - val_loss: 0.7698 - val_accuracy: 0.7170 Epoch 7/80 65/65 [==============================] - 15s 229ms/step - loss: 0.6774 - accuracy: 0.7485 - val_loss: 0.7441 - val_accuracy: 0.7148 Epoch 8/80 65/65 [==============================] - 15s 234ms/step - loss: 0.6341 - accuracy: 0.7714 - val_loss: 0.6918 - val_accuracy: 0.7398 Epoch 9/80 65/65 [==============================] - 14s 215ms/step - loss: 0.5985 - accuracy: 0.7797 - val_loss: 0.6602 - val_accuracy: 0.7557 Epoch 10/80 65/65 [==============================] - 15s 227ms/step - loss: 0.6166 - accuracy: 0.7695 - val_loss: 0.6884 - val_accuracy: 0.7591 Epoch 11/80 65/65 [==============================] - 15s 223ms/step - loss: 0.5901 - accuracy: 0.7821 - val_loss: 0.6280 - val_accuracy: 0.7716 Epoch 12/80 65/65 [==============================] - 15s 223ms/step - loss: 0.5737 - accuracy: 0.8001 - val_loss: 0.6202 - val_accuracy: 0.7750 Epoch 13/80 65/65 [==============================] - 15s 235ms/step - loss: 0.5678 - accuracy: 0.7879 - val_loss: 0.6162 - val_accuracy: 0.7761 Epoch 14/80 65/65 [==============================] - 15s 228ms/step - loss: 0.5573 - accuracy: 0.8001 - val_loss: 0.6524 - val_accuracy: 0.7568 Epoch 15/80 65/65 [==============================] - 14s 218ms/step - loss: 0.5237 - accuracy: 0.8113 - val_loss: 0.5988 - val_accuracy: 0.8000 Epoch 16/80 65/65 [==============================] - 15s 238ms/step - loss: 0.5083 - accuracy: 0.8191 - val_loss: 0.6159 - val_accuracy: 0.7727 Epoch 17/80 65/65 [==============================] - 15s 235ms/step - loss: 0.4977 - accuracy: 0.8181 - val_loss: 0.5977 - val_accuracy: 0.7818 Epoch 18/80 65/65 [==============================] - 15s 235ms/step - loss: 0.4974 - accuracy: 0.8186 - val_loss: 0.5990 - val_accuracy: 0.7875 Epoch 19/80 65/65 [==============================] - 15s 225ms/step - loss: 0.4674 - accuracy: 0.8337 - val_loss: 0.6037 - val_accuracy: 0.7693 Epoch 20/80 65/65 [==============================] - 15s 229ms/step - loss: 0.4758 - accuracy: 0.8239 - val_loss: 0.5870 - val_accuracy: 0.7886 Epoch 21/80 65/65 [==============================] - 16s 243ms/step - loss: 0.4651 - accuracy: 0.8322 - val_loss: 0.5723 - val_accuracy: 0.7875 Epoch 22/80 65/65 [==============================] - 15s 238ms/step - loss: 0.4801 - accuracy: 0.8259 - val_loss: 0.6195 - val_accuracy: 0.7659 Epoch 23/80 65/65 [==============================] - 15s 228ms/step - loss: 0.4536 - accuracy: 0.8322 - val_loss: 0.5850 - val_accuracy: 0.7841 Epoch 24/80 65/65 [==============================] - 16s 240ms/step - loss: 0.4381 - accuracy: 0.8473 - val_loss: 0.5656 - val_accuracy: 0.7852 Epoch 25/80 65/65 [==============================] - 15s 230ms/step - loss: 0.4278 - accuracy: 0.8444 - val_loss: 0.5640 - val_accuracy: 0.7795 Epoch 26/80 65/65 [==============================] - 15s 238ms/step - loss: 0.4253 - accuracy: 0.8551 - val_loss: 0.5465 - val_accuracy: 0.8023 Epoch 27/80 65/65 [==============================] - 15s 236ms/step - loss: 0.4276 - accuracy: 0.8502 - val_loss: 0.5438 - val_accuracy: 0.8170 Epoch 28/80 65/65 [==============================] - 16s 238ms/step - loss: 0.4223 - accuracy: 0.8531 - val_loss: 0.5372 - val_accuracy: 0.8034 Epoch 29/80 65/65 [==============================] - 15s 236ms/step - loss: 0.4192 - accuracy: 0.8482 - val_loss: 0.5344 - val_accuracy: 0.8102 Epoch 30/80 65/65 [==============================] - 15s 238ms/step - loss: 0.4092 - accuracy: 0.8492 - val_loss: 0.5235 - val_accuracy: 0.8102 Epoch 31/80 65/65 [==============================] - 15s 236ms/step - loss: 0.3964 - accuracy: 0.8604 - val_loss: 0.5309 - val_accuracy: 0.8045 Epoch 32/80 65/65 [==============================] - 16s 239ms/step - loss: 0.4029 - accuracy: 0.8589 - val_loss: 0.5251 - val_accuracy: 0.8102 Epoch 33/80 65/65 [==============================] - 15s 236ms/step - loss: 0.4019 - accuracy: 0.8570 - val_loss: 0.5250 - val_accuracy: 0.8045 Epoch 34/80 65/65 [==============================] - 15s 238ms/step - loss: 0.3761 - accuracy: 0.8692 - val_loss: 0.5314 - val_accuracy: 0.7955 Epoch 35/80 65/65 [==============================] - 16s 238ms/step - loss: 0.3824 - accuracy: 0.8638 - val_loss: 0.5108 - val_accuracy: 0.8136 Epoch 36/80 65/65 [==============================] - 16s 239ms/step - loss: 0.3793 - accuracy: 0.8628 - val_loss: 0.5216 - val_accuracy: 0.8136 Epoch 37/80 65/65 [==============================] - 16s 238ms/step - loss: 0.3634 - accuracy: 0.8774 - val_loss: 0.5584 - val_accuracy: 0.8000 Epoch 38/80 65/65 [==============================] - 16s 240ms/step - loss: 0.3785 - accuracy: 0.8706 - val_loss: 0.5148 - val_accuracy: 0.8205 Epoch 39/80 65/65 [==============================] - 15s 233ms/step - loss: 0.3710 - accuracy: 0.8696 - val_loss: 0.5166 - val_accuracy: 0.8159 Epoch 40/80 65/65 [==============================] - 16s 241ms/step - loss: 0.3676 - accuracy: 0.8740 - val_loss: 0.5369 - val_accuracy: 0.8080 Epoch 41/80 65/65 [==============================] - 16s 239ms/step - loss: 0.3605 - accuracy: 0.8755 - val_loss: 0.5122 - val_accuracy: 0.8136 Epoch 42/80 65/65 [==============================] - 16s 239ms/step - loss: 0.3738 - accuracy: 0.8716 - val_loss: 0.5113 - val_accuracy: 0.8068 Epoch 43/80 65/65 [==============================] - 16s 238ms/step - loss: 0.3670 - accuracy: 0.8662 - val_loss: 0.5173 - val_accuracy: 0.7977 Epoch 44/80 65/65 [==============================] - 16s 240ms/step - loss: 0.3556 - accuracy: 0.8808 - val_loss: 0.5117 - val_accuracy: 0.8114 Epoch 45/80 65/65 [==============================] - 16s 241ms/step - loss: 0.3402 - accuracy: 0.8847 - val_loss: 0.5001 - val_accuracy: 0.8182 Epoch 46/80 65/65 [==============================] - 16s 241ms/step - loss: 0.3496 - accuracy: 0.8823 - val_loss: 0.5126 - val_accuracy: 0.8023 Epoch 47/80 65/65 [==============================] - 16s 240ms/step - loss: 0.3330 - accuracy: 0.8842 - val_loss: 0.4949 - val_accuracy: 0.8205 Epoch 48/80 65/65 [==============================] - 16s 241ms/step - loss: 0.3407 - accuracy: 0.8915 - val_loss: 0.5089 - val_accuracy: 0.8125 Epoch 49/80 65/65 [==============================] - 16s 241ms/step - loss: 0.3272 - accuracy: 0.8857 - val_loss: 0.4977 - val_accuracy: 0.8216 Epoch 50/80 65/65 [==============================] - 16s 241ms/step - loss: 0.3334 - accuracy: 0.8906 - val_loss: 0.5078 - val_accuracy: 0.8182 Epoch 51/80 65/65 [==============================] - 16s 241ms/step - loss: 0.3226 - accuracy: 0.8891 - val_loss: 0.4885 - val_accuracy: 0.8182 Epoch 52/80 65/65 [==============================] - 16s 241ms/step - loss: 0.3411 - accuracy: 0.8804 - val_loss: 0.5080 - val_accuracy: 0.8125 Epoch 53/80 65/65 [==============================] - 16s 240ms/step - loss: 0.3239 - accuracy: 0.8959 - val_loss: 0.4837 - val_accuracy: 0.8273 Epoch 54/80 65/65 [==============================] - 16s 241ms/step - loss: 0.3189 - accuracy: 0.8886 - val_loss: 0.4995 - val_accuracy: 0.8068 Epoch 55/80 65/65 [==============================] - 16s 241ms/step - loss: 0.3213 - accuracy: 0.8901 - val_loss: 0.4823 - val_accuracy: 0.8227 Epoch 56/80 65/65 [==============================] - 16s 239ms/step - loss: 0.3246 - accuracy: 0.8867 - val_loss: 0.4830 - val_accuracy: 0.8261 Epoch 57/80 65/65 [==============================] - 16s 241ms/step - loss: 0.3214 - accuracy: 0.8979 - val_loss: 0.4930 - val_accuracy: 0.8295 Epoch 58/80 65/65 [==============================] - 16s 241ms/step - loss: 0.3093 - accuracy: 0.8954 - val_loss: 0.4909 - val_accuracy: 0.8341 Epoch 59/80 65/65 [==============================] - 16s 241ms/step - loss: 0.3019 - accuracy: 0.9003 - val_loss: 0.5005 - val_accuracy: 0.8148 Epoch 60/80 65/65 [==============================] - 16s 240ms/step - loss: 0.2890 - accuracy: 0.9090 - val_loss: 0.4927 - val_accuracy: 0.8182 Epoch 61/80 65/65 [==============================] - 16s 241ms/step - loss: 0.2967 - accuracy: 0.9013 - val_loss: 0.4960 - val_accuracy: 0.8136 Epoch 62/80 65/65 [==============================] - 16s 241ms/step - loss: 0.3067 - accuracy: 0.9008 - val_loss: 0.4869 - val_accuracy: 0.8193 Epoch 63/80 65/65 [==============================] - 16s 241ms/step - loss: 0.3004 - accuracy: 0.9052 - val_loss: 0.4937 - val_accuracy: 0.8205 Epoch 64/80 65/65 [==============================] - 16s 241ms/step - loss: 0.2983 - accuracy: 0.8945 - val_loss: 0.4778 - val_accuracy: 0.8307 Epoch 65/80 65/65 [==============================] - 16s 241ms/step - loss: 0.3093 - accuracy: 0.8876 - val_loss: 0.4978 - val_accuracy: 0.8239 Epoch 66/80 65/65 [==============================] - 16s 241ms/step - loss: 0.2971 - accuracy: 0.9066 - val_loss: 0.4856 - val_accuracy: 0.8250 Epoch 67/80 65/65 [==============================] - 16s 241ms/step - loss: 0.2988 - accuracy: 0.8998 - val_loss: 0.4988 - val_accuracy: 0.8091 Epoch 68/80 65/65 [==============================] - 16s 241ms/step - loss: 0.2979 - accuracy: 0.8974 - val_loss: 0.4810 - val_accuracy: 0.8307 Epoch 69/80 65/65 [==============================] - 16s 241ms/step - loss: 0.2958 - accuracy: 0.9027 - val_loss: 0.4811 - val_accuracy: 0.8239 Epoch 70/80 65/65 [==============================] - 16s 238ms/step - loss: 0.2924 - accuracy: 0.9052 - val_loss: 0.4825 - val_accuracy: 0.8239 Epoch 71/80 65/65 [==============================] - 16s 241ms/step - loss: 0.2946 - accuracy: 0.8993 - val_loss: 0.4774 - val_accuracy: 0.8250 Epoch 72/80 65/65 [==============================] - 16s 241ms/step - loss: 0.2937 - accuracy: 0.9032 - val_loss: 0.4898 - val_accuracy: 0.8136 Epoch 73/80 65/65 [==============================] - 16s 241ms/step - loss: 0.2844 - accuracy: 0.9032 - val_loss: 0.4707 - val_accuracy: 0.8284 Epoch 74/80 65/65 [==============================] - 16s 241ms/step - loss: 0.2905 - accuracy: 0.9032 - val_loss: 0.4793 - val_accuracy: 0.8273 Epoch 75/80 65/65 [==============================] - 16s 241ms/step - loss: 0.2728 - accuracy: 0.9134 - val_loss: 0.4627 - val_accuracy: 0.8386 Epoch 76/80 65/65 [==============================] - 16s 241ms/step - loss: 0.2777 - accuracy: 0.9086 - val_loss: 0.4730 - val_accuracy: 0.8284 Epoch 77/80 65/65 [==============================] - 16s 241ms/step - loss: 0.2890 - accuracy: 0.9071 - val_loss: 0.4771 - val_accuracy: 0.8250 Epoch 78/80 65/65 [==============================] - 16s 241ms/step - loss: 0.2703 - accuracy: 0.9163 - val_loss: 0.4920 - val_accuracy: 0.8091 Epoch 79/80 65/65 [==============================] - 16s 241ms/step - loss: 0.2811 - accuracy: 0.9095 - val_loss: 0.4670 - val_accuracy: 0.8284 Epoch 80/80 65/65 [==============================] - 16s 242ms/step - loss: 0.2726 - accuracy: 0.9154 - val_loss: 0.4727 - val_accuracy: 0.8386
# Visualization of the learning curves
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.ylim([0.0, 2.0])
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend(['train', 'valid'])
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.ylim([0.5, 1.0])
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(['train', 'valid'])
<matplotlib.legend.Legend at 0x230225ef970>
net.save("models/B3DropRMS.keras")
This combination of Dropout layers reduces the overfitting without affecting validation accuracy. There is a bit of a gap in train and validation accuracy, but the two curves do not diverge, demonstrating that, even if the model has better performances on train than on validation, the increase in train accuracy brings an increase also in validation accuracy. Since this is one of the best models we have, we are going to test its accuracy on the test set.
net = keras.models.load_model("models/B3DropRMS.keras")
net.evaluate(test_ds)
23/23 [==============================] - 4s 74ms/step - loss: 0.4477 - accuracy: 0.8365
[0.4477007985115051, 0.8365122675895691]
The test accuracy is of 83.65%. This is in line with the accuracy we had on validation set. We are going to compare this result with the one we achieve with a variant of the next combination.
# Architecture definition
inputs = keras.Input((None,None,3))
x = inputs
x = keras.layers.RandomCrop(224, 224)(x)
x = keras.layers.RandomFlip(mode='horizontal')(x)
x = keras.layers.RandomContrast(0.25)(x)
x = keras.layers.Conv2D(32, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.Conv2D(64, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Dropout(0.2)(x)
x = keras.layers.Conv2D(128, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.Dropout(0.3)(x)
x = keras.layers.GlobalMaxPooling2D()(x)
outputs = keras.layers.Dense(num_classes, activation="softmax")(x)
net = keras.Model(inputs, outputs)
callback = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)
lr_schedule = keras.optimizers.schedules.InverseTimeDecay(
initial_learning_rate = 0.0005,
decay_steps = 65,
decay_rate = 0.08)
optimizer = keras.optimizers.Adam(learning_rate=lr_schedule)
net.compile(loss=keras.losses.categorical_crossentropy,
optimizer=optimizer,
metrics=['accuracy'])
# Model training
history = net.fit(train_ds_256,
epochs=80,
validation_data=val_ds,
callbacks=[callback])
Epoch 1/80 65/65 [==============================] - 8s 96ms/step - loss: 1.7872 - accuracy: 0.4509 - val_loss: 3.3091 - val_accuracy: 0.1841 Epoch 2/80 65/65 [==============================] - 6s 89ms/step - loss: 1.0530 - accuracy: 0.5875 - val_loss: 1.6237 - val_accuracy: 0.3193 Epoch 3/80 65/65 [==============================] - 6s 89ms/step - loss: 0.9619 - accuracy: 0.6304 - val_loss: 1.1959 - val_accuracy: 0.5341 Epoch 4/80 65/65 [==============================] - 6s 90ms/step - loss: 0.9180 - accuracy: 0.6459 - val_loss: 1.0566 - val_accuracy: 0.6057 Epoch 5/80 65/65 [==============================] - 6s 92ms/step - loss: 0.8424 - accuracy: 0.6678 - val_loss: 0.9566 - val_accuracy: 0.6307 Epoch 6/80 65/65 [==============================] - 7s 104ms/step - loss: 0.8379 - accuracy: 0.6804 - val_loss: 0.9065 - val_accuracy: 0.6682 Epoch 7/80 65/65 [==============================] - 7s 108ms/step - loss: 0.7702 - accuracy: 0.7053 - val_loss: 0.9177 - val_accuracy: 0.6477 Epoch 8/80 65/65 [==============================] - 7s 109ms/step - loss: 0.7612 - accuracy: 0.7155 - val_loss: 0.8579 - val_accuracy: 0.6818 Epoch 9/80 65/65 [==============================] - 7s 108ms/step - loss: 0.7122 - accuracy: 0.7305 - val_loss: 0.8717 - val_accuracy: 0.6761 Epoch 10/80 65/65 [==============================] - 7s 109ms/step - loss: 0.7161 - accuracy: 0.7237 - val_loss: 0.8707 - val_accuracy: 0.6886 Epoch 11/80 65/65 [==============================] - 7s 109ms/step - loss: 0.7028 - accuracy: 0.7359 - val_loss: 0.7498 - val_accuracy: 0.7295 Epoch 12/80 65/65 [==============================] - 7s 109ms/step - loss: 0.7027 - accuracy: 0.7315 - val_loss: 0.7955 - val_accuracy: 0.7091 Epoch 13/80 65/65 [==============================] - 7s 109ms/step - loss: 0.6379 - accuracy: 0.7661 - val_loss: 0.7371 - val_accuracy: 0.7307 Epoch 14/80 65/65 [==============================] - 7s 109ms/step - loss: 0.6463 - accuracy: 0.7568 - val_loss: 0.7812 - val_accuracy: 0.7193 Epoch 15/80 65/65 [==============================] - 7s 109ms/step - loss: 0.6336 - accuracy: 0.7578 - val_loss: 0.7118 - val_accuracy: 0.7466 Epoch 16/80 65/65 [==============================] - 7s 109ms/step - loss: 0.6192 - accuracy: 0.7675 - val_loss: 0.6928 - val_accuracy: 0.7466 Epoch 17/80 65/65 [==============================] - 7s 109ms/step - loss: 0.6138 - accuracy: 0.7758 - val_loss: 0.7229 - val_accuracy: 0.7352 Epoch 18/80 65/65 [==============================] - 7s 110ms/step - loss: 0.5753 - accuracy: 0.7943 - val_loss: 0.7063 - val_accuracy: 0.7432 Epoch 19/80 65/65 [==============================] - 7s 109ms/step - loss: 0.5780 - accuracy: 0.7758 - val_loss: 0.6975 - val_accuracy: 0.7273 Epoch 20/80 65/65 [==============================] - 7s 109ms/step - loss: 0.5681 - accuracy: 0.7923 - val_loss: 0.6757 - val_accuracy: 0.7580 Epoch 21/80 65/65 [==============================] - 7s 110ms/step - loss: 0.5650 - accuracy: 0.7943 - val_loss: 0.7459 - val_accuracy: 0.7307 Epoch 22/80 65/65 [==============================] - 8s 122ms/step - loss: 0.5533 - accuracy: 0.7884 - val_loss: 0.7118 - val_accuracy: 0.7398 Epoch 23/80 65/65 [==============================] - 9s 130ms/step - loss: 0.5717 - accuracy: 0.7831 - val_loss: 0.6429 - val_accuracy: 0.7625 Epoch 24/80 65/65 [==============================] - 9s 142ms/step - loss: 0.5477 - accuracy: 0.7928 - val_loss: 0.6544 - val_accuracy: 0.7648 Epoch 25/80 65/65 [==============================] - 10s 153ms/step - loss: 0.5500 - accuracy: 0.7977 - val_loss: 0.6530 - val_accuracy: 0.7568 Epoch 26/80 65/65 [==============================] - 11s 161ms/step - loss: 0.5245 - accuracy: 0.8157 - val_loss: 0.6647 - val_accuracy: 0.7511 Epoch 27/80 65/65 [==============================] - 11s 167ms/step - loss: 0.5185 - accuracy: 0.8074 - val_loss: 0.6406 - val_accuracy: 0.7727 Epoch 28/80 65/65 [==============================] - 11s 172ms/step - loss: 0.5222 - accuracy: 0.8089 - val_loss: 0.6446 - val_accuracy: 0.7648 Epoch 29/80 65/65 [==============================] - 12s 179ms/step - loss: 0.5108 - accuracy: 0.8205 - val_loss: 0.6421 - val_accuracy: 0.7670 Epoch 30/80 65/65 [==============================] - 13s 197ms/step - loss: 0.5265 - accuracy: 0.8074 - val_loss: 0.6366 - val_accuracy: 0.7500 Epoch 31/80 65/65 [==============================] - 12s 191ms/step - loss: 0.5000 - accuracy: 0.8142 - val_loss: 0.6114 - val_accuracy: 0.7841 Epoch 32/80 65/65 [==============================] - 13s 198ms/step - loss: 0.4927 - accuracy: 0.8215 - val_loss: 0.6258 - val_accuracy: 0.7875 Epoch 33/80 65/65 [==============================] - 13s 200ms/step - loss: 0.5253 - accuracy: 0.8137 - val_loss: 0.6120 - val_accuracy: 0.7841 Epoch 34/80 65/65 [==============================] - 13s 204ms/step - loss: 0.5104 - accuracy: 0.8171 - val_loss: 0.6292 - val_accuracy: 0.7693 Epoch 35/80 65/65 [==============================] - 13s 206ms/step - loss: 0.5016 - accuracy: 0.8127 - val_loss: 0.6058 - val_accuracy: 0.7807 Epoch 36/80 65/65 [==============================] - 14s 219ms/step - loss: 0.4808 - accuracy: 0.8283 - val_loss: 0.6090 - val_accuracy: 0.7693 Epoch 37/80 65/65 [==============================] - 13s 205ms/step - loss: 0.4706 - accuracy: 0.8303 - val_loss: 0.6275 - val_accuracy: 0.7716 Epoch 38/80 65/65 [==============================] - 14s 217ms/step - loss: 0.4650 - accuracy: 0.8307 - val_loss: 0.6521 - val_accuracy: 0.7557 Epoch 39/80 65/65 [==============================] - 14s 218ms/step - loss: 0.4695 - accuracy: 0.8288 - val_loss: 0.5960 - val_accuracy: 0.7773 Epoch 40/80 65/65 [==============================] - 14s 216ms/step - loss: 0.4742 - accuracy: 0.8327 - val_loss: 0.6046 - val_accuracy: 0.7875 Epoch 41/80 65/65 [==============================] - 15s 236ms/step - loss: 0.4680 - accuracy: 0.8332 - val_loss: 0.5862 - val_accuracy: 0.7875 Epoch 42/80 65/65 [==============================] - 15s 233ms/step - loss: 0.4660 - accuracy: 0.8298 - val_loss: 0.5886 - val_accuracy: 0.7830 Epoch 43/80 65/65 [==============================] - 15s 226ms/step - loss: 0.4763 - accuracy: 0.8191 - val_loss: 0.5914 - val_accuracy: 0.7886 Epoch 44/80 65/65 [==============================] - 15s 226ms/step - loss: 0.4707 - accuracy: 0.8341 - val_loss: 0.5892 - val_accuracy: 0.7955 Epoch 45/80 65/65 [==============================] - 15s 237ms/step - loss: 0.4640 - accuracy: 0.8346 - val_loss: 0.5915 - val_accuracy: 0.7784 Epoch 46/80 65/65 [==============================] - 15s 231ms/step - loss: 0.4465 - accuracy: 0.8419 - val_loss: 0.6042 - val_accuracy: 0.7886 Epoch 47/80 65/65 [==============================] - 15s 231ms/step - loss: 0.4369 - accuracy: 0.8497 - val_loss: 0.5647 - val_accuracy: 0.7989 Epoch 48/80 65/65 [==============================] - 15s 229ms/step - loss: 0.4455 - accuracy: 0.8361 - val_loss: 0.5791 - val_accuracy: 0.7932 Epoch 49/80 65/65 [==============================] - 16s 240ms/step - loss: 0.4412 - accuracy: 0.8322 - val_loss: 0.5670 - val_accuracy: 0.8023 Epoch 50/80 65/65 [==============================] - 15s 230ms/step - loss: 0.4523 - accuracy: 0.8385 - val_loss: 0.5833 - val_accuracy: 0.7784 Epoch 51/80 65/65 [==============================] - 16s 242ms/step - loss: 0.4447 - accuracy: 0.8395 - val_loss: 0.5820 - val_accuracy: 0.7875 Epoch 52/80 65/65 [==============================] - 16s 242ms/step - loss: 0.4188 - accuracy: 0.8531 - val_loss: 0.5793 - val_accuracy: 0.7966 Epoch 53/80 65/65 [==============================] - 15s 233ms/step - loss: 0.4281 - accuracy: 0.8390 - val_loss: 0.6048 - val_accuracy: 0.7818 Epoch 54/80 65/65 [==============================] - 16s 245ms/step - loss: 0.4438 - accuracy: 0.8468 - val_loss: 0.5724 - val_accuracy: 0.7898 Epoch 55/80 65/65 [==============================] - 15s 237ms/step - loss: 0.4182 - accuracy: 0.8517 - val_loss: 0.5473 - val_accuracy: 0.8057 Epoch 56/80 65/65 [==============================] - 16s 246ms/step - loss: 0.4199 - accuracy: 0.8444 - val_loss: 0.5526 - val_accuracy: 0.8011 Epoch 57/80 65/65 [==============================] - 16s 239ms/step - loss: 0.4135 - accuracy: 0.8512 - val_loss: 0.5775 - val_accuracy: 0.7909 Epoch 58/80 65/65 [==============================] - 16s 245ms/step - loss: 0.4083 - accuracy: 0.8624 - val_loss: 0.5696 - val_accuracy: 0.7909 Epoch 59/80 65/65 [==============================] - 16s 244ms/step - loss: 0.4208 - accuracy: 0.8478 - val_loss: 0.5717 - val_accuracy: 0.7920 Epoch 60/80 65/65 [==============================] - 16s 246ms/step - loss: 0.4332 - accuracy: 0.8497 - val_loss: 0.5910 - val_accuracy: 0.7864 Epoch 61/80 65/65 [==============================] - 16s 246ms/step - loss: 0.4105 - accuracy: 0.8541 - val_loss: 0.5524 - val_accuracy: 0.7977 Epoch 62/80 65/65 [==============================] - 16s 245ms/step - loss: 0.4038 - accuracy: 0.8531 - val_loss: 0.5598 - val_accuracy: 0.7909 Epoch 63/80 65/65 [==============================] - 16s 246ms/step - loss: 0.3978 - accuracy: 0.8594 - val_loss: 0.5601 - val_accuracy: 0.7966 Epoch 64/80 65/65 [==============================] - 16s 246ms/step - loss: 0.4117 - accuracy: 0.8463 - val_loss: 0.5496 - val_accuracy: 0.7989 Epoch 65/80 65/65 [==============================] - 16s 246ms/step - loss: 0.4070 - accuracy: 0.8575 - val_loss: 0.5611 - val_accuracy: 0.7989
# Visualization of the learning curves
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.ylim([0.0, 2.0])
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend(['train', 'valid'])
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.ylim([0.5, 1.0])
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(['train', 'valid'])
<matplotlib.legend.Legend at 0x22ecaf7caf0>
net.save("models/B3DropAv2.keras")
This second combination has stronger regularization power. In this way, the gap between train and validation is further decreased, but this time it does affect validation accuracy. What we can do, though, is deepening further the architechture of the model, in the hope that we can achieve the same (or better) validation accuracy but with a lower gap between train and validation.
# Architecture definition
inputs = keras.Input((None,None,3))
x = inputs
x = keras.layers.RandomCrop(224, 224)(x)
x = keras.layers.RandomFlip(mode='horizontal')(x)
x = keras.layers.RandomContrast(0.25)(x)
x = keras.layers.Conv2D(32, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.Conv2D(64, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Dropout(0.2)(x)
x = keras.layers.Conv2D(128, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.Dropout(0.3)(x)
x = keras.layers.GlobalMaxPooling2D()(x)
outputs = keras.layers.Dense(1024, activation="softmax")(x)
outputs = keras.layers.Dense(num_classes, activation="softmax")(x)
net = keras.Model(inputs, outputs)
callback = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)
lr_schedule = keras.optimizers.schedules.InverseTimeDecay(
initial_learning_rate = 0.0005,
decay_steps = 65,
decay_rate = 0.08)
optimizer = keras.optimizers.Adam(learning_rate=lr_schedule)
net.compile(loss=keras.losses.categorical_crossentropy,
optimizer=optimizer,
metrics=['accuracy'])
# Model training
history = net.fit(train_ds_256,
epochs=80,
validation_data=val_ds,
callbacks=[callback])
Epoch 1/80 65/65 [==============================] - 8s 112ms/step - loss: 1.6127 - accuracy: 0.4455 - val_loss: 1.7215 - val_accuracy: 0.3443 Epoch 2/80 65/65 [==============================] - 7s 109ms/step - loss: 1.0411 - accuracy: 0.6002 - val_loss: 1.1926 - val_accuracy: 0.4784 Epoch 3/80 65/65 [==============================] - 7s 108ms/step - loss: 0.9358 - accuracy: 0.6167 - val_loss: 0.9347 - val_accuracy: 0.6250 Epoch 4/80 65/65 [==============================] - 7s 109ms/step - loss: 0.8748 - accuracy: 0.6571 - val_loss: 0.8851 - val_accuracy: 0.6614 Epoch 5/80 65/65 [==============================] - 7s 108ms/step - loss: 0.8485 - accuracy: 0.6639 - val_loss: 0.8678 - val_accuracy: 0.6795 Epoch 6/80 65/65 [==============================] - 7s 109ms/step - loss: 0.8018 - accuracy: 0.6960 - val_loss: 0.9080 - val_accuracy: 0.6409 Epoch 7/80 65/65 [==============================] - 8s 122ms/step - loss: 0.7544 - accuracy: 0.7077 - val_loss: 0.8347 - val_accuracy: 0.6818 Epoch 8/80 65/65 [==============================] - 12s 180ms/step - loss: 0.7341 - accuracy: 0.7169 - val_loss: 0.7649 - val_accuracy: 0.7125 Epoch 9/80 65/65 [==============================] - 15s 228ms/step - loss: 0.6959 - accuracy: 0.7296 - val_loss: 0.8440 - val_accuracy: 0.6830 Epoch 10/80 65/65 [==============================] - 16s 248ms/step - loss: 0.7005 - accuracy: 0.7310 - val_loss: 0.8153 - val_accuracy: 0.7045 Epoch 11/80 65/65 [==============================] - 16s 245ms/step - loss: 0.6794 - accuracy: 0.7432 - val_loss: 0.8106 - val_accuracy: 0.7125 Epoch 12/80 65/65 [==============================] - 16s 245ms/step - loss: 0.6508 - accuracy: 0.7510 - val_loss: 0.7777 - val_accuracy: 0.7091 Epoch 13/80 65/65 [==============================] - 16s 244ms/step - loss: 0.6385 - accuracy: 0.7573 - val_loss: 0.7747 - val_accuracy: 0.7216 Epoch 14/80 65/65 [==============================] - 16s 246ms/step - loss: 0.6546 - accuracy: 0.7446 - val_loss: 0.6844 - val_accuracy: 0.7545 Epoch 15/80 65/65 [==============================] - 16s 245ms/step - loss: 0.6329 - accuracy: 0.7505 - val_loss: 0.6782 - val_accuracy: 0.7523 Epoch 16/80 65/65 [==============================] - 16s 245ms/step - loss: 0.5911 - accuracy: 0.7855 - val_loss: 0.7048 - val_accuracy: 0.7318 Epoch 17/80 65/65 [==============================] - 16s 246ms/step - loss: 0.6196 - accuracy: 0.7646 - val_loss: 0.6955 - val_accuracy: 0.7409 Epoch 18/80 65/65 [==============================] - 16s 246ms/step - loss: 0.5884 - accuracy: 0.7768 - val_loss: 0.6922 - val_accuracy: 0.7443 Epoch 19/80 65/65 [==============================] - 16s 246ms/step - loss: 0.5752 - accuracy: 0.7772 - val_loss: 0.6784 - val_accuracy: 0.7602 Epoch 20/80 65/65 [==============================] - 16s 246ms/step - loss: 0.5749 - accuracy: 0.7884 - val_loss: 0.6450 - val_accuracy: 0.7648 Epoch 21/80 65/65 [==============================] - 16s 246ms/step - loss: 0.5595 - accuracy: 0.7884 - val_loss: 0.6366 - val_accuracy: 0.7682 Epoch 22/80 65/65 [==============================] - 16s 247ms/step - loss: 0.5590 - accuracy: 0.7889 - val_loss: 0.6425 - val_accuracy: 0.7648 Epoch 23/80 65/65 [==============================] - 16s 247ms/step - loss: 0.5329 - accuracy: 0.8040 - val_loss: 0.6275 - val_accuracy: 0.7795 Epoch 24/80 65/65 [==============================] - 16s 248ms/step - loss: 0.5468 - accuracy: 0.7991 - val_loss: 0.7022 - val_accuracy: 0.7432 Epoch 25/80 65/65 [==============================] - 16s 248ms/step - loss: 0.5199 - accuracy: 0.8040 - val_loss: 0.6436 - val_accuracy: 0.7830 Epoch 26/80 65/65 [==============================] - 16s 247ms/step - loss: 0.5244 - accuracy: 0.8079 - val_loss: 0.6282 - val_accuracy: 0.7682 Epoch 27/80 65/65 [==============================] - 16s 248ms/step - loss: 0.5307 - accuracy: 0.8054 - val_loss: 0.6757 - val_accuracy: 0.7500 Epoch 28/80 65/65 [==============================] - 16s 248ms/step - loss: 0.5205 - accuracy: 0.8074 - val_loss: 0.6276 - val_accuracy: 0.7670 Epoch 29/80 65/65 [==============================] - 16s 249ms/step - loss: 0.5065 - accuracy: 0.8103 - val_loss: 0.6162 - val_accuracy: 0.7773 Epoch 30/80 65/65 [==============================] - 16s 247ms/step - loss: 0.4912 - accuracy: 0.8225 - val_loss: 0.6014 - val_accuracy: 0.7886 Epoch 31/80 65/65 [==============================] - 16s 248ms/step - loss: 0.4677 - accuracy: 0.8273 - val_loss: 0.5913 - val_accuracy: 0.7909 Epoch 32/80 65/65 [==============================] - 16s 248ms/step - loss: 0.4940 - accuracy: 0.8093 - val_loss: 0.6860 - val_accuracy: 0.7398 Epoch 33/80 65/65 [==============================] - 16s 250ms/step - loss: 0.4890 - accuracy: 0.8239 - val_loss: 0.6120 - val_accuracy: 0.7750 Epoch 34/80 65/65 [==============================] - 16s 248ms/step - loss: 0.4872 - accuracy: 0.8108 - val_loss: 0.6058 - val_accuracy: 0.7818 Epoch 35/80 65/65 [==============================] - 16s 249ms/step - loss: 0.4851 - accuracy: 0.8264 - val_loss: 0.5959 - val_accuracy: 0.7807 Epoch 36/80 65/65 [==============================] - 16s 248ms/step - loss: 0.4840 - accuracy: 0.8220 - val_loss: 0.6069 - val_accuracy: 0.7841 Epoch 37/80 65/65 [==============================] - 17s 251ms/step - loss: 0.4804 - accuracy: 0.8186 - val_loss: 0.6111 - val_accuracy: 0.7761 Epoch 38/80 65/65 [==============================] - 16s 249ms/step - loss: 0.4814 - accuracy: 0.8225 - val_loss: 0.6003 - val_accuracy: 0.7795 Epoch 39/80 65/65 [==============================] - 16s 249ms/step - loss: 0.4823 - accuracy: 0.8249 - val_loss: 0.5994 - val_accuracy: 0.7898 Epoch 40/80 65/65 [==============================] - 16s 250ms/step - loss: 0.4491 - accuracy: 0.8410 - val_loss: 0.6034 - val_accuracy: 0.7830 Epoch 41/80 65/65 [==============================] - 16s 250ms/step - loss: 0.4629 - accuracy: 0.8337 - val_loss: 0.6150 - val_accuracy: 0.7648
# Visualization of the learning curves
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.ylim([0.0, 2.0])
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend(['train', 'valid'])
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.ylim([0.5, 1.0])
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(['train', 'valid'])
<matplotlib.legend.Legend at 0x21608c17580>
An additional dense layer of 1024 further reduces the gap between train and validation.
We are going to try and remove the first convolutional layer of 32 neuron while adding a last layer of 256.
# Architecture definition
inputs = keras.Input((None,None,3))
x = inputs
x = keras.layers.RandomCrop(224, 224)(x)
x = keras.layers.RandomFlip(mode='horizontal')(x)
x = keras.layers.RandomContrast(0.25)(x)
x = keras.layers.Conv2D(64, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.Conv2D(128, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Dropout(0.2)(x)
x = keras.layers.Conv2D(256, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.Dropout(0.3)(x)
x = keras.layers.GlobalMaxPooling2D()(x)
outputs = keras.layers.Dense(1024, activation="softmax")(x)
outputs = keras.layers.Dense(num_classes, activation="softmax")(x)
net = keras.Model(inputs, outputs)
callback = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)
lr_schedule = keras.optimizers.schedules.InverseTimeDecay(
initial_learning_rate = 0.0005,
decay_steps = 65,
decay_rate = 0.08)
optimizer = keras.optimizers.Adam(learning_rate=lr_schedule)
net.compile(loss=keras.losses.categorical_crossentropy,
optimizer=optimizer,
metrics=['accuracy'])
# Model training
history = net.fit(train_ds_256,
epochs=80,
validation_data=val_ds,
callbacks=[callback])
Epoch 1/80 65/65 [==============================] - 43s 529ms/step - loss: 1.5438 - accuracy: 0.4874 - val_loss: 1.6398 - val_accuracy: 0.3818 Epoch 2/80 65/65 [==============================] - 31s 482ms/step - loss: 1.0108 - accuracy: 0.6172 - val_loss: 0.9065 - val_accuracy: 0.6602 Epoch 3/80 65/65 [==============================] - 31s 483ms/step - loss: 0.8682 - accuracy: 0.6790 - val_loss: 0.9420 - val_accuracy: 0.6102 Epoch 4/80 65/65 [==============================] - 31s 483ms/step - loss: 0.7686 - accuracy: 0.6975 - val_loss: 0.7677 - val_accuracy: 0.7273 Epoch 5/80 65/65 [==============================] - 32s 483ms/step - loss: 0.7064 - accuracy: 0.7388 - val_loss: 0.7310 - val_accuracy: 0.7205 Epoch 6/80 65/65 [==============================] - 32s 486ms/step - loss: 0.6821 - accuracy: 0.7378 - val_loss: 0.6750 - val_accuracy: 0.7568 Epoch 7/80 65/65 [==============================] - 32s 485ms/step - loss: 0.6349 - accuracy: 0.7612 - val_loss: 0.7188 - val_accuracy: 0.7466 Epoch 8/80 65/65 [==============================] - 32s 486ms/step - loss: 0.5991 - accuracy: 0.7772 - val_loss: 0.7192 - val_accuracy: 0.7352 Epoch 9/80 65/65 [==============================] - 32s 486ms/step - loss: 0.5791 - accuracy: 0.7782 - val_loss: 0.7442 - val_accuracy: 0.7159 Epoch 10/80 65/65 [==============================] - 32s 485ms/step - loss: 0.5598 - accuracy: 0.7996 - val_loss: 0.7725 - val_accuracy: 0.6932 Epoch 11/80 65/65 [==============================] - 32s 486ms/step - loss: 0.5097 - accuracy: 0.8118 - val_loss: 0.6366 - val_accuracy: 0.7670 Epoch 12/80 65/65 [==============================] - 32s 488ms/step - loss: 0.5256 - accuracy: 0.8064 - val_loss: 0.6341 - val_accuracy: 0.7818 Epoch 13/80 65/65 [==============================] - 32s 489ms/step - loss: 0.5222 - accuracy: 0.8045 - val_loss: 0.5914 - val_accuracy: 0.7886 Epoch 14/80 65/65 [==============================] - 32s 488ms/step - loss: 0.4869 - accuracy: 0.8181 - val_loss: 0.6238 - val_accuracy: 0.7739 Epoch 15/80 65/65 [==============================] - 32s 489ms/step - loss: 0.4889 - accuracy: 0.8118 - val_loss: 0.5819 - val_accuracy: 0.7920 Epoch 16/80 65/65 [==============================] - 32s 487ms/step - loss: 0.4641 - accuracy: 0.8327 - val_loss: 0.5832 - val_accuracy: 0.8011 Epoch 17/80 65/65 [==============================] - 32s 486ms/step - loss: 0.4458 - accuracy: 0.8390 - val_loss: 0.5856 - val_accuracy: 0.7898 Epoch 18/80 65/65 [==============================] - 32s 485ms/step - loss: 0.4241 - accuracy: 0.8560 - val_loss: 0.5621 - val_accuracy: 0.8000 Epoch 19/80 65/65 [==============================] - 32s 493ms/step - loss: 0.4369 - accuracy: 0.8341 - val_loss: 0.5798 - val_accuracy: 0.7909 Epoch 20/80 65/65 [==============================] - 32s 489ms/step - loss: 0.4139 - accuracy: 0.8487 - val_loss: 0.6356 - val_accuracy: 0.7557 Epoch 21/80 65/65 [==============================] - 32s 488ms/step - loss: 0.4220 - accuracy: 0.8487 - val_loss: 0.5574 - val_accuracy: 0.7886 Epoch 22/80 65/65 [==============================] - 32s 489ms/step - loss: 0.3938 - accuracy: 0.8541 - val_loss: 0.5794 - val_accuracy: 0.7830 Epoch 23/80 65/65 [==============================] - 32s 487ms/step - loss: 0.4151 - accuracy: 0.8453 - val_loss: 0.5484 - val_accuracy: 0.8148 Epoch 24/80 65/65 [==============================] - 32s 486ms/step - loss: 0.3698 - accuracy: 0.8716 - val_loss: 0.5480 - val_accuracy: 0.8000 Epoch 25/80 65/65 [==============================] - 32s 488ms/step - loss: 0.3724 - accuracy: 0.8696 - val_loss: 0.5409 - val_accuracy: 0.8034 Epoch 26/80 65/65 [==============================] - 32s 487ms/step - loss: 0.3638 - accuracy: 0.8765 - val_loss: 0.5397 - val_accuracy: 0.8068 Epoch 27/80 65/65 [==============================] - 32s 489ms/step - loss: 0.3672 - accuracy: 0.8682 - val_loss: 0.5765 - val_accuracy: 0.7943 Epoch 28/80 65/65 [==============================] - 32s 486ms/step - loss: 0.3615 - accuracy: 0.8755 - val_loss: 0.5475 - val_accuracy: 0.8023 Epoch 29/80 65/65 [==============================] - 32s 490ms/step - loss: 0.3476 - accuracy: 0.8706 - val_loss: 0.5396 - val_accuracy: 0.8114 Epoch 30/80 65/65 [==============================] - 32s 489ms/step - loss: 0.3382 - accuracy: 0.8794 - val_loss: 0.5152 - val_accuracy: 0.8170 Epoch 31/80 65/65 [==============================] - 32s 487ms/step - loss: 0.3457 - accuracy: 0.8755 - val_loss: 0.5228 - val_accuracy: 0.8068 Epoch 32/80 65/65 [==============================] - 32s 486ms/step - loss: 0.3335 - accuracy: 0.8828 - val_loss: 0.5105 - val_accuracy: 0.8227 Epoch 33/80 65/65 [==============================] - 32s 487ms/step - loss: 0.3127 - accuracy: 0.9022 - val_loss: 0.5113 - val_accuracy: 0.8091 Epoch 34/80 65/65 [==============================] - 32s 487ms/step - loss: 0.3163 - accuracy: 0.8911 - val_loss: 0.5084 - val_accuracy: 0.8205 Epoch 35/80 65/65 [==============================] - 32s 487ms/step - loss: 0.3111 - accuracy: 0.8949 - val_loss: 0.5017 - val_accuracy: 0.8261 Epoch 36/80 65/65 [==============================] - 32s 486ms/step - loss: 0.3052 - accuracy: 0.8925 - val_loss: 0.5069 - val_accuracy: 0.8182 Epoch 37/80 65/65 [==============================] - 32s 487ms/step - loss: 0.2901 - accuracy: 0.9061 - val_loss: 0.5023 - val_accuracy: 0.8068 Epoch 38/80 65/65 [==============================] - 32s 487ms/step - loss: 0.2966 - accuracy: 0.9008 - val_loss: 0.4951 - val_accuracy: 0.8182 Epoch 39/80 65/65 [==============================] - 32s 487ms/step - loss: 0.2883 - accuracy: 0.9032 - val_loss: 0.5355 - val_accuracy: 0.8091 Epoch 40/80 65/65 [==============================] - 32s 486ms/step - loss: 0.2909 - accuracy: 0.8998 - val_loss: 0.4939 - val_accuracy: 0.8193 Epoch 41/80 65/65 [==============================] - 32s 487ms/step - loss: 0.2785 - accuracy: 0.9061 - val_loss: 0.4965 - val_accuracy: 0.8284 Epoch 42/80 65/65 [==============================] - 32s 486ms/step - loss: 0.2674 - accuracy: 0.9066 - val_loss: 0.4925 - val_accuracy: 0.8182 Epoch 43/80 65/65 [==============================] - 32s 486ms/step - loss: 0.2683 - accuracy: 0.9115 - val_loss: 0.4917 - val_accuracy: 0.8284 Epoch 44/80 65/65 [==============================] - 32s 487ms/step - loss: 0.2648 - accuracy: 0.9120 - val_loss: 0.4875 - val_accuracy: 0.8261 Epoch 45/80 65/65 [==============================] - 32s 486ms/step - loss: 0.2731 - accuracy: 0.9115 - val_loss: 0.5000 - val_accuracy: 0.8284 Epoch 46/80 65/65 [==============================] - 32s 486ms/step - loss: 0.2749 - accuracy: 0.9061 - val_loss: 0.4856 - val_accuracy: 0.8182 Epoch 47/80 65/65 [==============================] - 32s 487ms/step - loss: 0.2605 - accuracy: 0.9071 - val_loss: 0.4911 - val_accuracy: 0.8239 Epoch 48/80 65/65 [==============================] - 32s 488ms/step - loss: 0.2519 - accuracy: 0.9212 - val_loss: 0.4900 - val_accuracy: 0.8216 Epoch 49/80 65/65 [==============================] - 32s 487ms/step - loss: 0.2587 - accuracy: 0.9154 - val_loss: 0.4992 - val_accuracy: 0.8148 Epoch 50/80 65/65 [==============================] - 32s 487ms/step - loss: 0.2447 - accuracy: 0.9163 - val_loss: 0.5090 - val_accuracy: 0.8148 Epoch 51/80 65/65 [==============================] - 32s 487ms/step - loss: 0.2472 - accuracy: 0.9183 - val_loss: 0.4843 - val_accuracy: 0.8273 Epoch 52/80 65/65 [==============================] - 32s 486ms/step - loss: 0.2556 - accuracy: 0.9154 - val_loss: 0.4456 - val_accuracy: 0.8443 Epoch 53/80 65/65 [==============================] - 32s 487ms/step - loss: 0.2661 - accuracy: 0.9105 - val_loss: 0.4673 - val_accuracy: 0.8420 Epoch 54/80 65/65 [==============================] - 32s 487ms/step - loss: 0.2342 - accuracy: 0.9270 - val_loss: 0.4754 - val_accuracy: 0.8318 Epoch 55/80 65/65 [==============================] - 32s 486ms/step - loss: 0.2502 - accuracy: 0.9217 - val_loss: 0.4667 - val_accuracy: 0.8364 Epoch 56/80 65/65 [==============================] - 32s 486ms/step - loss: 0.2399 - accuracy: 0.9275 - val_loss: 0.4610 - val_accuracy: 0.8364 Epoch 57/80 65/65 [==============================] - 32s 486ms/step - loss: 0.2356 - accuracy: 0.9304 - val_loss: 0.4735 - val_accuracy: 0.8182 Epoch 58/80 65/65 [==============================] - 32s 486ms/step - loss: 0.2222 - accuracy: 0.9343 - val_loss: 0.4568 - val_accuracy: 0.8398 Epoch 59/80 65/65 [==============================] - 32s 488ms/step - loss: 0.2315 - accuracy: 0.9256 - val_loss: 0.4681 - val_accuracy: 0.8239 Epoch 60/80 65/65 [==============================] - 32s 486ms/step - loss: 0.2203 - accuracy: 0.9319 - val_loss: 0.4489 - val_accuracy: 0.8398 Epoch 61/80 65/65 [==============================] - 32s 488ms/step - loss: 0.2250 - accuracy: 0.9270 - val_loss: 0.4526 - val_accuracy: 0.8295 Epoch 62/80 65/65 [==============================] - 32s 487ms/step - loss: 0.2243 - accuracy: 0.9212 - val_loss: 0.4584 - val_accuracy: 0.8295
# Visualization of the learning curves
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.ylim([0.0, 2.0])
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend(['train', 'valid'])
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.ylim([0.5, 1.0])
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(['train', 'valid'])
<matplotlib.legend.Legend at 0x21616f19940>
net.save("models/B64ADrop.keras")
This modification in the architechture does bring an improvement. Of course, since we have more neurons, we have (again) increased the gap between train and validation. After other testing, we came to this architechture: adding another dense layer of 512 and adding a Dropout layer to the first dense layer.
# Architecture definition
inputs = keras.Input((None,None,3))
x = inputs
x = keras.layers.RandomCrop(224, 224)(x)
x = keras.layers.RandomFlip(mode='horizontal')(x)
x = keras.layers.RandomContrast(0.25)(x)
x = keras.layers.Conv2D(64, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.Conv2D(128, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Dropout(0.2)(x)
x = keras.layers.Conv2D(256, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.Dropout(0.2)(x)
x = keras.layers.GlobalMaxPooling2D()(x)
outputs = keras.layers.Dense(1024, activation="softmax")(x)
x = keras.layers.Dropout(0.1)(x)
outputs = keras.layers.Dense(512, activation="softmax")(x)
outputs = keras.layers.Dense(num_classes, activation="softmax")(x)
net = keras.Model(inputs, outputs)
callback = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)
lr_schedule = keras.optimizers.schedules.InverseTimeDecay(
initial_learning_rate = 0.0005,
decay_steps = 65,
decay_rate = 0.08)
optimizer = keras.optimizers.Adam(learning_rate=lr_schedule)
net.compile(loss=keras.losses.categorical_crossentropy,
optimizer=optimizer,
metrics=['accuracy'])
# Model training
history = net.fit(train_ds_256,
epochs=80,
validation_data=val_ds,
callbacks=[callback])
Epoch 1/80 65/65 [==============================] - 14s 183ms/step - loss: 1.8859 - accuracy: 0.4703 - val_loss: 3.2992 - val_accuracy: 0.3000 Epoch 2/80 65/65 [==============================] - 13s 198ms/step - loss: 1.2943 - accuracy: 0.5696 - val_loss: 1.2053 - val_accuracy: 0.5170 Epoch 3/80 65/65 [==============================] - 13s 198ms/step - loss: 1.1326 - accuracy: 0.5968 - val_loss: 0.9673 - val_accuracy: 0.6455 Epoch 4/80 65/65 [==============================] - 13s 198ms/step - loss: 1.0899 - accuracy: 0.6172 - val_loss: 0.7542 - val_accuracy: 0.7216 Epoch 5/80 65/65 [==============================] - 13s 200ms/step - loss: 0.9838 - accuracy: 0.6459 - val_loss: 0.7256 - val_accuracy: 0.7182 Epoch 6/80 65/65 [==============================] - 19s 290ms/step - loss: 0.8945 - accuracy: 0.6775 - val_loss: 0.7948 - val_accuracy: 0.6943 Epoch 7/80 65/65 [==============================] - 30s 470ms/step - loss: 0.8563 - accuracy: 0.6960 - val_loss: 0.8255 - val_accuracy: 0.6830 Epoch 8/80 65/65 [==============================] - 31s 479ms/step - loss: 0.8284 - accuracy: 0.7038 - val_loss: 0.8459 - val_accuracy: 0.6943 Epoch 9/80 65/65 [==============================] - 31s 482ms/step - loss: 0.8205 - accuracy: 0.7004 - val_loss: 0.6965 - val_accuracy: 0.7443 Epoch 10/80 65/65 [==============================] - 31s 483ms/step - loss: 0.7780 - accuracy: 0.7130 - val_loss: 0.6953 - val_accuracy: 0.7455 Epoch 11/80 65/65 [==============================] - 31s 482ms/step - loss: 0.7269 - accuracy: 0.7330 - val_loss: 0.7213 - val_accuracy: 0.7375 Epoch 12/80 65/65 [==============================] - 31s 483ms/step - loss: 0.7273 - accuracy: 0.7378 - val_loss: 0.6059 - val_accuracy: 0.7739 Epoch 13/80 65/65 [==============================] - 32s 484ms/step - loss: 0.7469 - accuracy: 0.7262 - val_loss: 0.6504 - val_accuracy: 0.7602 Epoch 14/80 65/65 [==============================] - 32s 484ms/step - loss: 0.7115 - accuracy: 0.7335 - val_loss: 0.7031 - val_accuracy: 0.7523 Epoch 15/80 65/65 [==============================] - 32s 484ms/step - loss: 0.6672 - accuracy: 0.7578 - val_loss: 0.6071 - val_accuracy: 0.7807 Epoch 16/80 65/65 [==============================] - 32s 484ms/step - loss: 0.7046 - accuracy: 0.7344 - val_loss: 0.6054 - val_accuracy: 0.7830 Epoch 17/80 65/65 [==============================] - 32s 485ms/step - loss: 0.6495 - accuracy: 0.7617 - val_loss: 0.6571 - val_accuracy: 0.7580 Epoch 18/80 65/65 [==============================] - 32s 484ms/step - loss: 0.6569 - accuracy: 0.7631 - val_loss: 0.6189 - val_accuracy: 0.7716 Epoch 19/80 65/65 [==============================] - 32s 485ms/step - loss: 0.6486 - accuracy: 0.7622 - val_loss: 0.6332 - val_accuracy: 0.7705 Epoch 20/80 65/65 [==============================] - 32s 485ms/step - loss: 0.6259 - accuracy: 0.7597 - val_loss: 0.5570 - val_accuracy: 0.7852 Epoch 21/80 65/65 [==============================] - 32s 485ms/step - loss: 0.6037 - accuracy: 0.7719 - val_loss: 0.5820 - val_accuracy: 0.7864 Epoch 22/80 65/65 [==============================] - 32s 485ms/step - loss: 0.6138 - accuracy: 0.7840 - val_loss: 0.5729 - val_accuracy: 0.8000 Epoch 23/80 65/65 [==============================] - 32s 485ms/step - loss: 0.5609 - accuracy: 0.8030 - val_loss: 0.6272 - val_accuracy: 0.7705 Epoch 24/80 65/65 [==============================] - 32s 485ms/step - loss: 0.5776 - accuracy: 0.7850 - val_loss: 0.6072 - val_accuracy: 0.7670 Epoch 25/80 65/65 [==============================] - 32s 485ms/step - loss: 0.5860 - accuracy: 0.7928 - val_loss: 0.5671 - val_accuracy: 0.7909 Epoch 26/80 65/65 [==============================] - 32s 486ms/step - loss: 0.5879 - accuracy: 0.7768 - val_loss: 0.5958 - val_accuracy: 0.7818 Epoch 27/80 65/65 [==============================] - 32s 486ms/step - loss: 0.5704 - accuracy: 0.7986 - val_loss: 0.5407 - val_accuracy: 0.7955 Epoch 28/80 65/65 [==============================] - 32s 485ms/step - loss: 0.5207 - accuracy: 0.8050 - val_loss: 0.5266 - val_accuracy: 0.8068 Epoch 29/80 65/65 [==============================] - 32s 486ms/step - loss: 0.5785 - accuracy: 0.7962 - val_loss: 0.5195 - val_accuracy: 0.8080 Epoch 30/80 65/65 [==============================] - 32s 486ms/step - loss: 0.5412 - accuracy: 0.8035 - val_loss: 0.5055 - val_accuracy: 0.8148 Epoch 31/80 65/65 [==============================] - 32s 486ms/step - loss: 0.5248 - accuracy: 0.8006 - val_loss: 0.5657 - val_accuracy: 0.7875 Epoch 32/80 65/65 [==============================] - 32s 486ms/step - loss: 0.5053 - accuracy: 0.8176 - val_loss: 0.5376 - val_accuracy: 0.8045 Epoch 33/80 65/65 [==============================] - 32s 486ms/step - loss: 0.5336 - accuracy: 0.8011 - val_loss: 0.5257 - val_accuracy: 0.8125 Epoch 34/80 65/65 [==============================] - 32s 486ms/step - loss: 0.4949 - accuracy: 0.8196 - val_loss: 0.5597 - val_accuracy: 0.7920 Epoch 35/80 65/65 [==============================] - 32s 486ms/step - loss: 0.5130 - accuracy: 0.7996 - val_loss: 0.4878 - val_accuracy: 0.8284 Epoch 36/80 65/65 [==============================] - 32s 486ms/step - loss: 0.4793 - accuracy: 0.8186 - val_loss: 0.5223 - val_accuracy: 0.8045 Epoch 37/80 65/65 [==============================] - 32s 486ms/step - loss: 0.4737 - accuracy: 0.8225 - val_loss: 0.5287 - val_accuracy: 0.8045 Epoch 38/80 65/65 [==============================] - 32s 486ms/step - loss: 0.4954 - accuracy: 0.8103 - val_loss: 0.5251 - val_accuracy: 0.7966 Epoch 39/80 65/65 [==============================] - 32s 487ms/step - loss: 0.4840 - accuracy: 0.8157 - val_loss: 0.5587 - val_accuracy: 0.7932 Epoch 40/80 65/65 [==============================] - 32s 487ms/step - loss: 0.4855 - accuracy: 0.8147 - val_loss: 0.5365 - val_accuracy: 0.8080 Epoch 41/80 65/65 [==============================] - 32s 487ms/step - loss: 0.4871 - accuracy: 0.8259 - val_loss: 0.4964 - val_accuracy: 0.8205 Epoch 42/80 65/65 [==============================] - 32s 488ms/step - loss: 0.4625 - accuracy: 0.8200 - val_loss: 0.4985 - val_accuracy: 0.8091 Epoch 43/80 65/65 [==============================] - 32s 488ms/step - loss: 0.4572 - accuracy: 0.8303 - val_loss: 0.5099 - val_accuracy: 0.8216 Epoch 44/80 65/65 [==============================] - 32s 488ms/step - loss: 0.4539 - accuracy: 0.8337 - val_loss: 0.5253 - val_accuracy: 0.8045 Epoch 45/80 65/65 [==============================] - 32s 487ms/step - loss: 0.4627 - accuracy: 0.8356 - val_loss: 0.5123 - val_accuracy: 0.8114
# Visualization of the learning curves
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.ylim([0.0, 2.0])
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend(['train', 'valid'])
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.ylim([0.5, 1.0])
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(['train', 'valid'])
<matplotlib.legend.Legend at 0x215a7700820>
By decreasing the strength of the dropout layer, we could be able to let the model learn more:
# Architecture definition
inputs = keras.Input((None,None,3))
x = inputs
x = keras.layers.RandomCrop(224, 224)(x)
x = keras.layers.RandomFlip(mode='horizontal')(x)
x = keras.layers.RandomContrast(0.25)(x)
x = keras.layers.Conv2D(64, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.Conv2D(128, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.Conv2D(256, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.GlobalMaxPooling2D()(x)
outputs = keras.layers.Dense(1024, activation="softmax")(x)
x = keras.layers.Dropout(0.2)(x)
outputs = keras.layers.Dense(512, activation="softmax")(x)
outputs = keras.layers.Dense(num_classes, activation="softmax")(x)
net = keras.Model(inputs, outputs)
callback = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)
lr_schedule = keras.optimizers.schedules.InverseTimeDecay(
initial_learning_rate = 0.0005,
decay_steps = 65,
decay_rate = 0.08)
optimizer = keras.optimizers.Adam(learning_rate=lr_schedule)
net.compile(loss=keras.losses.categorical_crossentropy,
optimizer=optimizer,
metrics=['accuracy'])
# Model training
history = net.fit(train_ds_256,
epochs=80,
validation_data=val_ds,
callbacks=[callback])
Epoch 1/80 74/74 [==============================] - 20s 196ms/step - loss: 1.9844 - accuracy: 0.4551 - val_loss: 2.4820 - val_accuracy: 0.3646 Epoch 2/80 74/74 [==============================] - 12s 165ms/step - loss: 1.3621 - accuracy: 0.5645 - val_loss: 1.3708 - val_accuracy: 0.5468 Epoch 3/80 74/74 [==============================] - 14s 184ms/step - loss: 1.2446 - accuracy: 0.5824 - val_loss: 0.9081 - val_accuracy: 0.6661 Epoch 4/80 74/74 [==============================] - 14s 185ms/step - loss: 1.1093 - accuracy: 0.6301 - val_loss: 0.8527 - val_accuracy: 0.6644 Epoch 5/80 74/74 [==============================] - 14s 185ms/step - loss: 1.0274 - accuracy: 0.6356 - val_loss: 0.8337 - val_accuracy: 0.6985 Epoch 6/80 74/74 [==============================] - 14s 185ms/step - loss: 1.0037 - accuracy: 0.6564 - val_loss: 0.8142 - val_accuracy: 0.7189 Epoch 7/80 74/74 [==============================] - 14s 186ms/step - loss: 0.9306 - accuracy: 0.6701 - val_loss: 0.8056 - val_accuracy: 0.7223 Epoch 8/80 74/74 [==============================] - 14s 185ms/step - loss: 0.9002 - accuracy: 0.6790 - val_loss: 0.7858 - val_accuracy: 0.7155 Epoch 9/80 74/74 [==============================] - 14s 186ms/step - loss: 0.8724 - accuracy: 0.6943 - val_loss: 0.7612 - val_accuracy: 0.7223 Epoch 10/80 74/74 [==============================] - 14s 189ms/step - loss: 0.8404 - accuracy: 0.7024 - val_loss: 0.8242 - val_accuracy: 0.6814 Epoch 11/80 74/74 [==============================] - 15s 205ms/step - loss: 0.8075 - accuracy: 0.7097 - val_loss: 0.7140 - val_accuracy: 0.7257 Epoch 12/80 74/74 [==============================] - 19s 258ms/step - loss: 0.7972 - accuracy: 0.7033 - val_loss: 0.7650 - val_accuracy: 0.7070 Epoch 13/80 74/74 [==============================] - 32s 434ms/step - loss: 0.7726 - accuracy: 0.7169 - val_loss: 0.6636 - val_accuracy: 0.7342 Epoch 14/80 74/74 [==============================] - 33s 443ms/step - loss: 0.7656 - accuracy: 0.7135 - val_loss: 0.7408 - val_accuracy: 0.7359 Epoch 15/80 74/74 [==============================] - 29s 390ms/step - loss: 0.7856 - accuracy: 0.7143 - val_loss: 0.7319 - val_accuracy: 0.7240 Epoch 16/80 74/74 [==============================] - 32s 432ms/step - loss: 0.7181 - accuracy: 0.7267 - val_loss: 0.6348 - val_accuracy: 0.7649 Epoch 17/80 74/74 [==============================] - 34s 455ms/step - loss: 0.6919 - accuracy: 0.7531 - val_loss: 0.7148 - val_accuracy: 0.7445 Epoch 18/80 74/74 [==============================] - 34s 454ms/step - loss: 0.6770 - accuracy: 0.7518 - val_loss: 0.6076 - val_accuracy: 0.7734 Epoch 19/80 74/74 [==============================] - 34s 455ms/step - loss: 0.6906 - accuracy: 0.7382 - val_loss: 0.6340 - val_accuracy: 0.7751 Epoch 20/80 74/74 [==============================] - 34s 454ms/step - loss: 0.6754 - accuracy: 0.7467 - val_loss: 0.6440 - val_accuracy: 0.7547 Epoch 21/80 74/74 [==============================] - 34s 455ms/step - loss: 0.6702 - accuracy: 0.7458 - val_loss: 0.6200 - val_accuracy: 0.7632 Epoch 22/80 74/74 [==============================] - 34s 457ms/step - loss: 0.6738 - accuracy: 0.7480 - val_loss: 0.5940 - val_accuracy: 0.7853 Epoch 23/80 74/74 [==============================] - 34s 455ms/step - loss: 0.6334 - accuracy: 0.7671 - val_loss: 0.5580 - val_accuracy: 0.7853 Epoch 24/80 74/74 [==============================] - 34s 455ms/step - loss: 0.6414 - accuracy: 0.7710 - val_loss: 0.5683 - val_accuracy: 0.7888 Epoch 25/80 74/74 [==============================] - 34s 455ms/step - loss: 0.6289 - accuracy: 0.7799 - val_loss: 0.6002 - val_accuracy: 0.7785 Epoch 26/80 74/74 [==============================] - 34s 455ms/step - loss: 0.5742 - accuracy: 0.7905 - val_loss: 0.6284 - val_accuracy: 0.7666 Epoch 27/80 74/74 [==============================] - 34s 454ms/step - loss: 0.6165 - accuracy: 0.7756 - val_loss: 0.5915 - val_accuracy: 0.7785 Epoch 28/80 74/74 [==============================] - 34s 454ms/step - loss: 0.6174 - accuracy: 0.7693 - val_loss: 0.5421 - val_accuracy: 0.7922 Epoch 29/80 74/74 [==============================] - 34s 454ms/step - loss: 0.5481 - accuracy: 0.7944 - val_loss: 0.5401 - val_accuracy: 0.8109 Epoch 30/80 74/74 [==============================] - 34s 454ms/step - loss: 0.5843 - accuracy: 0.7910 - val_loss: 0.5518 - val_accuracy: 0.7871 Epoch 31/80 74/74 [==============================] - 34s 455ms/step - loss: 0.5620 - accuracy: 0.7867 - val_loss: 0.5149 - val_accuracy: 0.8092 Epoch 32/80 74/74 [==============================] - 34s 454ms/step - loss: 0.5748 - accuracy: 0.7944 - val_loss: 0.5708 - val_accuracy: 0.7939 Epoch 33/80 74/74 [==============================] - 34s 454ms/step - loss: 0.5504 - accuracy: 0.7850 - val_loss: 0.6118 - val_accuracy: 0.7802 Epoch 34/80 74/74 [==============================] - 34s 454ms/step - loss: 0.5628 - accuracy: 0.7888 - val_loss: 0.5052 - val_accuracy: 0.8092 Epoch 35/80 74/74 [==============================] - 34s 454ms/step - loss: 0.5564 - accuracy: 0.7969 - val_loss: 0.5953 - val_accuracy: 0.7853 Epoch 36/80 74/74 [==============================] - 34s 455ms/step - loss: 0.5528 - accuracy: 0.7923 - val_loss: 0.5994 - val_accuracy: 0.7888 Epoch 37/80 74/74 [==============================] - 34s 455ms/step - loss: 0.5300 - accuracy: 0.8118 - val_loss: 0.5234 - val_accuracy: 0.8160 Epoch 38/80 74/74 [==============================] - 34s 454ms/step - loss: 0.5220 - accuracy: 0.8135 - val_loss: 0.5333 - val_accuracy: 0.8109 Epoch 39/80 74/74 [==============================] - 34s 455ms/step - loss: 0.5078 - accuracy: 0.8050 - val_loss: 0.5911 - val_accuracy: 0.7905 Epoch 40/80 74/74 [==============================] - 34s 455ms/step - loss: 0.5376 - accuracy: 0.8076 - val_loss: 0.5477 - val_accuracy: 0.7836 Epoch 41/80 74/74 [==============================] - 34s 457ms/step - loss: 0.5082 - accuracy: 0.8050 - val_loss: 0.5029 - val_accuracy: 0.8041 Epoch 42/80 74/74 [==============================] - 34s 456ms/step - loss: 0.5141 - accuracy: 0.8042 - val_loss: 0.5414 - val_accuracy: 0.8075 Epoch 43/80 74/74 [==============================] - 34s 454ms/step - loss: 0.4895 - accuracy: 0.8123 - val_loss: 0.5246 - val_accuracy: 0.8075 Epoch 44/80 74/74 [==============================] - 34s 454ms/step - loss: 0.5343 - accuracy: 0.8123 - val_loss: 0.5642 - val_accuracy: 0.7922 Epoch 45/80 74/74 [==============================] - 34s 454ms/step - loss: 0.5052 - accuracy: 0.8140 - val_loss: 0.5084 - val_accuracy: 0.8143 Epoch 46/80 74/74 [==============================] - 34s 455ms/step - loss: 0.5415 - accuracy: 0.7952 - val_loss: 0.5637 - val_accuracy: 0.7973 Epoch 47/80 74/74 [==============================] - 34s 456ms/step - loss: 0.4939 - accuracy: 0.8229 - val_loss: 0.5383 - val_accuracy: 0.8109 Epoch 48/80 74/74 [==============================] - 34s 455ms/step - loss: 0.4718 - accuracy: 0.8203 - val_loss: 0.4880 - val_accuracy: 0.8245 Epoch 49/80 74/74 [==============================] - 34s 456ms/step - loss: 0.5012 - accuracy: 0.8089 - val_loss: 0.5435 - val_accuracy: 0.7990 Epoch 50/80 74/74 [==============================] - 34s 457ms/step - loss: 0.4789 - accuracy: 0.8186 - val_loss: 0.4766 - val_accuracy: 0.8330 Epoch 51/80 74/74 [==============================] - 34s 456ms/step - loss: 0.4702 - accuracy: 0.8246 - val_loss: 0.5048 - val_accuracy: 0.8143 Epoch 52/80 74/74 [==============================] - 34s 456ms/step - loss: 0.4763 - accuracy: 0.8276 - val_loss: 0.5325 - val_accuracy: 0.8075 Epoch 53/80 74/74 [==============================] - 34s 457ms/step - loss: 0.5007 - accuracy: 0.8135 - val_loss: 0.4931 - val_accuracy: 0.8143 Epoch 54/80 74/74 [==============================] - 34s 456ms/step - loss: 0.4764 - accuracy: 0.8165 - val_loss: 0.4932 - val_accuracy: 0.8126 Epoch 55/80 74/74 [==============================] - 34s 458ms/step - loss: 0.4799 - accuracy: 0.8323 - val_loss: 0.4713 - val_accuracy: 0.8296 Epoch 56/80 74/74 [==============================] - 34s 461ms/step - loss: 0.4630 - accuracy: 0.8323 - val_loss: 0.5393 - val_accuracy: 0.8109 Epoch 57/80 74/74 [==============================] - 34s 456ms/step - loss: 0.4511 - accuracy: 0.8284 - val_loss: 0.5037 - val_accuracy: 0.8211 Epoch 58/80 74/74 [==============================] - 34s 458ms/step - loss: 0.4497 - accuracy: 0.8293 - val_loss: 0.5124 - val_accuracy: 0.8143 Epoch 59/80 74/74 [==============================] - 34s 459ms/step - loss: 0.4836 - accuracy: 0.8199 - val_loss: 0.4896 - val_accuracy: 0.8211 Epoch 60/80 74/74 [==============================] - 34s 458ms/step - loss: 0.4422 - accuracy: 0.8365 - val_loss: 0.4836 - val_accuracy: 0.8160 Epoch 61/80 74/74 [==============================] - 34s 457ms/step - loss: 0.4249 - accuracy: 0.8378 - val_loss: 0.5015 - val_accuracy: 0.8160 Epoch 62/80 74/74 [==============================] - 34s 455ms/step - loss: 0.4239 - accuracy: 0.8455 - val_loss: 0.4825 - val_accuracy: 0.8228 Epoch 63/80 74/74 [==============================] - 34s 458ms/step - loss: 0.4614 - accuracy: 0.8306 - val_loss: 0.5102 - val_accuracy: 0.8160 Epoch 64/80 74/74 [==============================] - 34s 456ms/step - loss: 0.4431 - accuracy: 0.8348 - val_loss: 0.4949 - val_accuracy: 0.8160 Epoch 65/80 74/74 [==============================] - 34s 457ms/step - loss: 0.4297 - accuracy: 0.8378 - val_loss: 0.4692 - val_accuracy: 0.8313 Epoch 66/80 74/74 [==============================] - 34s 458ms/step - loss: 0.4329 - accuracy: 0.8378 - val_loss: 0.4937 - val_accuracy: 0.8228 Epoch 67/80 74/74 [==============================] - 34s 455ms/step - loss: 0.4148 - accuracy: 0.8455 - val_loss: 0.4974 - val_accuracy: 0.8245 Epoch 68/80 74/74 [==============================] - 34s 457ms/step - loss: 0.4551 - accuracy: 0.8370 - val_loss: 0.4953 - val_accuracy: 0.8211 Epoch 69/80 74/74 [==============================] - 34s 454ms/step - loss: 0.4448 - accuracy: 0.8301 - val_loss: 0.4762 - val_accuracy: 0.8279 Epoch 70/80 74/74 [==============================] - 34s 456ms/step - loss: 0.4316 - accuracy: 0.8382 - val_loss: 0.5186 - val_accuracy: 0.8075 Epoch 71/80 74/74 [==============================] - 34s 454ms/step - loss: 0.4135 - accuracy: 0.8442 - val_loss: 0.4732 - val_accuracy: 0.8416 Epoch 72/80 74/74 [==============================] - 34s 454ms/step - loss: 0.4464 - accuracy: 0.8374 - val_loss: 0.4651 - val_accuracy: 0.8313 Epoch 73/80 74/74 [==============================] - 34s 454ms/step - loss: 0.4416 - accuracy: 0.8357 - val_loss: 0.4681 - val_accuracy: 0.8365 Epoch 74/80 74/74 [==============================] - 34s 455ms/step - loss: 0.4474 - accuracy: 0.8348 - val_loss: 0.4427 - val_accuracy: 0.8484 Epoch 75/80 74/74 [==============================] - 34s 457ms/step - loss: 0.4234 - accuracy: 0.8429 - val_loss: 0.4529 - val_accuracy: 0.8399 Epoch 76/80 74/74 [==============================] - 34s 455ms/step - loss: 0.4029 - accuracy: 0.8561 - val_loss: 0.4713 - val_accuracy: 0.8262 Epoch 77/80 74/74 [==============================] - 34s 454ms/step - loss: 0.4278 - accuracy: 0.8446 - val_loss: 0.4788 - val_accuracy: 0.8194 Epoch 78/80 74/74 [==============================] - 34s 453ms/step - loss: 0.4035 - accuracy: 0.8480 - val_loss: 0.4780 - val_accuracy: 0.8177 Epoch 79/80 74/74 [==============================] - 34s 454ms/step - loss: 0.3988 - accuracy: 0.8472 - val_loss: 0.4661 - val_accuracy: 0.8296 Epoch 80/80 74/74 [==============================] - 34s 454ms/step - loss: 0.4322 - accuracy: 0.8425 - val_loss: 0.4736 - val_accuracy: 0.8330
# Visualization of the learning curves
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.ylim([0.0, 2.0])
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend(['train', 'valid'])
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.ylim([0.5, 1.0])
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(['train', 'valid'])
<matplotlib.legend.Legend at 0x257d6994850>
net.save("models/B3D2DropA.keras")
We achieved a model with zero gap between train and validation accuracy, while retaining nearly the same validation accuracy as the first model we tested. Since the early stopping did not stop the training of the model, we are going to let it train for another bit:
# Train until the early stopping blocks it
# Model training
history = net.fit(train_ds_256,
epochs=80,
validation_data=val_ds,
callbacks=[callback])
Epoch 1/80 74/74 [==============================] - 11s 148ms/step - loss: 0.4120 - accuracy: 0.8506 - val_loss: 0.4953 - val_accuracy: 0.8109 Epoch 2/80 74/74 [==============================] - 11s 150ms/step - loss: 0.4338 - accuracy: 0.8318 - val_loss: 0.4753 - val_accuracy: 0.8279 Epoch 3/80 74/74 [==============================] - 12s 158ms/step - loss: 0.4116 - accuracy: 0.8484 - val_loss: 0.4669 - val_accuracy: 0.8296 Epoch 4/80 74/74 [==============================] - 14s 183ms/step - loss: 0.3943 - accuracy: 0.8523 - val_loss: 0.4768 - val_accuracy: 0.8296 Epoch 5/80 74/74 [==============================] - 14s 184ms/step - loss: 0.3898 - accuracy: 0.8595 - val_loss: 0.4913 - val_accuracy: 0.8143 Epoch 6/80 74/74 [==============================] - 14s 184ms/step - loss: 0.3964 - accuracy: 0.8446 - val_loss: 0.4813 - val_accuracy: 0.8245 Epoch 7/80 74/74 [==============================] - 14s 183ms/step - loss: 0.3874 - accuracy: 0.8599 - val_loss: 0.4444 - val_accuracy: 0.8313 Epoch 8/80 74/74 [==============================] - 14s 184ms/step - loss: 0.3964 - accuracy: 0.8493 - val_loss: 0.4764 - val_accuracy: 0.8279 Epoch 9/80 74/74 [==============================] - 14s 184ms/step - loss: 0.3940 - accuracy: 0.8574 - val_loss: 0.5159 - val_accuracy: 0.8211 Epoch 10/80 74/74 [==============================] - 14s 183ms/step - loss: 0.3876 - accuracy: 0.8629 - val_loss: 0.4401 - val_accuracy: 0.8416 Epoch 11/80 74/74 [==============================] - 14s 184ms/step - loss: 0.4075 - accuracy: 0.8459 - val_loss: 0.4741 - val_accuracy: 0.8245 Epoch 12/80 74/74 [==============================] - 14s 184ms/step - loss: 0.4054 - accuracy: 0.8484 - val_loss: 0.4832 - val_accuracy: 0.8313 Epoch 13/80 74/74 [==============================] - 14s 185ms/step - loss: 0.3990 - accuracy: 0.8476 - val_loss: 0.4822 - val_accuracy: 0.8330 Epoch 14/80 74/74 [==============================] - 15s 200ms/step - loss: 0.3897 - accuracy: 0.8595 - val_loss: 0.4300 - val_accuracy: 0.8416 Epoch 15/80 74/74 [==============================] - 16s 219ms/step - loss: 0.4141 - accuracy: 0.8459 - val_loss: 0.4623 - val_accuracy: 0.8450 Epoch 16/80 74/74 [==============================] - 18s 243ms/step - loss: 0.3785 - accuracy: 0.8612 - val_loss: 0.4448 - val_accuracy: 0.8416 Epoch 17/80 74/74 [==============================] - 18s 248ms/step - loss: 0.3796 - accuracy: 0.8578 - val_loss: 0.4371 - val_accuracy: 0.8416 Epoch 18/80 74/74 [==============================] - 20s 269ms/step - loss: 0.3986 - accuracy: 0.8540 - val_loss: 0.4315 - val_accuracy: 0.8484 Epoch 19/80 74/74 [==============================] - 21s 283ms/step - loss: 0.3591 - accuracy: 0.8625 - val_loss: 0.4633 - val_accuracy: 0.8330 Epoch 20/80 74/74 [==============================] - 21s 289ms/step - loss: 0.3971 - accuracy: 0.8421 - val_loss: 0.4394 - val_accuracy: 0.8416 Epoch 21/80 74/74 [==============================] - 23s 306ms/step - loss: 0.3793 - accuracy: 0.8506 - val_loss: 0.4855 - val_accuracy: 0.8160 Epoch 22/80 74/74 [==============================] - 24s 321ms/step - loss: 0.3669 - accuracy: 0.8570 - val_loss: 0.4509 - val_accuracy: 0.8399 Epoch 23/80 74/74 [==============================] - 23s 317ms/step - loss: 0.3808 - accuracy: 0.8557 - val_loss: 0.4186 - val_accuracy: 0.8450 Epoch 24/80 74/74 [==============================] - 23s 305ms/step - loss: 0.3633 - accuracy: 0.8629 - val_loss: 0.4526 - val_accuracy: 0.8365 Epoch 25/80 74/74 [==============================] - 26s 346ms/step - loss: 0.4011 - accuracy: 0.8455 - val_loss: 0.4627 - val_accuracy: 0.8382 Epoch 26/80 74/74 [==============================] - 25s 337ms/step - loss: 0.3569 - accuracy: 0.8668 - val_loss: 0.4531 - val_accuracy: 0.8330 Epoch 27/80 74/74 [==============================] - 25s 344ms/step - loss: 0.3600 - accuracy: 0.8646 - val_loss: 0.4746 - val_accuracy: 0.8348 Epoch 28/80 74/74 [==============================] - 25s 337ms/step - loss: 0.3692 - accuracy: 0.8638 - val_loss: 0.4580 - val_accuracy: 0.8399 Epoch 29/80 74/74 [==============================] - 26s 347ms/step - loss: 0.3644 - accuracy: 0.8638 - val_loss: 0.4454 - val_accuracy: 0.8416 Epoch 30/80 74/74 [==============================] - 26s 352ms/step - loss: 0.3758 - accuracy: 0.8582 - val_loss: 0.4348 - val_accuracy: 0.8467 Epoch 31/80 74/74 [==============================] - 28s 375ms/step - loss: 0.3589 - accuracy: 0.8702 - val_loss: 0.4663 - val_accuracy: 0.8296 Epoch 32/80 74/74 [==============================] - 28s 375ms/step - loss: 0.3601 - accuracy: 0.8608 - val_loss: 0.4550 - val_accuracy: 0.8279 Epoch 33/80 74/74 [==============================] - 28s 382ms/step - loss: 0.3554 - accuracy: 0.8710 - val_loss: 0.4712 - val_accuracy: 0.8313
net.save("models/B3D2DropA2.keras")
Lets now test its performances on the test set:
net.evaluate(test_ds)
23/23 [==============================] - 1s 47ms/step - loss: 0.4168 - accuracy: 0.8474
[0.4167979061603546, 0.8474114537239075]
The test accuracy is of 84.74%, this is even better than the first model we tested.
We are going to try and tune the parameter of the model. Searching for a combination with better performances:
# Architecture definition LR decay 0.05
inputs = keras.Input((None,None,3))
x = inputs
x = keras.layers.RandomCrop(224, 224)(x)
x = keras.layers.RandomFlip(mode='horizontal')(x)
x = keras.layers.RandomContrast(0.25)(x)
x = keras.layers.Conv2D(64, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.Conv2D(128, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.Conv2D(256, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.GlobalMaxPooling2D()(x)
outputs = keras.layers.Dense(1024, activation="softmax")(x)
x = keras.layers.Dropout(0.2)(x)
outputs = keras.layers.Dense(512, activation="softmax")(x)
outputs = keras.layers.Dense(num_classes, activation="softmax")(x)
net = keras.Model(inputs, outputs)
callback = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)
lr_schedule = keras.optimizers.schedules.InverseTimeDecay(
initial_learning_rate = 0.0005,
decay_steps = 65,
decay_rate = 0.05)
optimizer = keras.optimizers.Adam(learning_rate=lr_schedule)
net.compile(loss=keras.losses.categorical_crossentropy,
optimizer=optimizer,
metrics=['accuracy'])
# Model training
history = net.fit(train_ds_256,
epochs=80,
validation_data=val_ds,
callbacks=[callback])
Epoch 1/80 74/74 [==============================] - 13s 156ms/step - loss: 1.8820 - accuracy: 0.4576 - val_loss: 2.6713 - val_accuracy: 0.3612 Epoch 2/80 74/74 [==============================] - 13s 178ms/step - loss: 1.3386 - accuracy: 0.5547 - val_loss: 1.4557 - val_accuracy: 0.5315 Epoch 3/80 74/74 [==============================] - 14s 184ms/step - loss: 1.1921 - accuracy: 0.5905 - val_loss: 1.2134 - val_accuracy: 0.5963 Epoch 4/80 74/74 [==============================] - 14s 184ms/step - loss: 1.1202 - accuracy: 0.6224 - val_loss: 0.9911 - val_accuracy: 0.6457 Epoch 5/80 74/74 [==============================] - 14s 184ms/step - loss: 1.0416 - accuracy: 0.6424 - val_loss: 0.7881 - val_accuracy: 0.6899 Epoch 6/80 74/74 [==============================] - 14s 185ms/step - loss: 0.9600 - accuracy: 0.6577 - val_loss: 0.7651 - val_accuracy: 0.7087 Epoch 7/80 74/74 [==============================] - 17s 226ms/step - loss: 0.8992 - accuracy: 0.6880 - val_loss: 0.7939 - val_accuracy: 0.7070 Epoch 8/80 74/74 [==============================] - 27s 364ms/step - loss: 0.8580 - accuracy: 0.6918 - val_loss: 0.6931 - val_accuracy: 0.7223 Epoch 9/80 74/74 [==============================] - 32s 441ms/step - loss: 0.8392 - accuracy: 0.6943 - val_loss: 0.6811 - val_accuracy: 0.7513 Epoch 10/80 74/74 [==============================] - 34s 454ms/step - loss: 0.8519 - accuracy: 0.7016 - val_loss: 0.7328 - val_accuracy: 0.7274 Epoch 11/80 74/74 [==============================] - 34s 455ms/step - loss: 0.7715 - accuracy: 0.7233 - val_loss: 0.7701 - val_accuracy: 0.7155 Epoch 12/80 74/74 [==============================] - 34s 455ms/step - loss: 0.7909 - accuracy: 0.7190 - val_loss: 0.6620 - val_accuracy: 0.7496 Epoch 13/80 74/74 [==============================] - 34s 456ms/step - loss: 0.7477 - accuracy: 0.7331 - val_loss: 0.6665 - val_accuracy: 0.7598 Epoch 14/80 74/74 [==============================] - 34s 456ms/step - loss: 0.7420 - accuracy: 0.7212 - val_loss: 0.6552 - val_accuracy: 0.7428 Epoch 15/80 74/74 [==============================] - 34s 456ms/step - loss: 0.7379 - accuracy: 0.7263 - val_loss: 0.7248 - val_accuracy: 0.7206 Epoch 16/80 74/74 [==============================] - 34s 457ms/step - loss: 0.6935 - accuracy: 0.7446 - val_loss: 0.6758 - val_accuracy: 0.7581 Epoch 17/80 74/74 [==============================] - 34s 457ms/step - loss: 0.7128 - accuracy: 0.7458 - val_loss: 0.6316 - val_accuracy: 0.7547 Epoch 18/80 74/74 [==============================] - 34s 458ms/step - loss: 0.6565 - accuracy: 0.7625 - val_loss: 0.6084 - val_accuracy: 0.7802 Epoch 19/80 74/74 [==============================] - 34s 459ms/step - loss: 0.6281 - accuracy: 0.7735 - val_loss: 0.5692 - val_accuracy: 0.7939 Epoch 20/80 74/74 [==============================] - 34s 458ms/step - loss: 0.6568 - accuracy: 0.7688 - val_loss: 0.6026 - val_accuracy: 0.7802 Epoch 21/80 74/74 [==============================] - 34s 460ms/step - loss: 0.6298 - accuracy: 0.7642 - val_loss: 0.6680 - val_accuracy: 0.7666 Epoch 22/80 74/74 [==============================] - 34s 459ms/step - loss: 0.6002 - accuracy: 0.7739 - val_loss: 0.5836 - val_accuracy: 0.7922 Epoch 23/80 74/74 [==============================] - 34s 461ms/step - loss: 0.6209 - accuracy: 0.7718 - val_loss: 0.6036 - val_accuracy: 0.7632 Epoch 24/80 74/74 [==============================] - 34s 460ms/step - loss: 0.5795 - accuracy: 0.7791 - val_loss: 0.5369 - val_accuracy: 0.8160 Epoch 25/80 74/74 [==============================] - 34s 460ms/step - loss: 0.5688 - accuracy: 0.7871 - val_loss: 0.6609 - val_accuracy: 0.7700 Epoch 26/80 74/74 [==============================] - 34s 460ms/step - loss: 0.5724 - accuracy: 0.7859 - val_loss: 0.6368 - val_accuracy: 0.7717 Epoch 27/80 74/74 [==============================] - 34s 462ms/step - loss: 0.5841 - accuracy: 0.7867 - val_loss: 0.6143 - val_accuracy: 0.7888 Epoch 28/80 74/74 [==============================] - 34s 461ms/step - loss: 0.5593 - accuracy: 0.7944 - val_loss: 0.6207 - val_accuracy: 0.7683 Epoch 29/80 74/74 [==============================] - 34s 462ms/step - loss: 0.5478 - accuracy: 0.8080 - val_loss: 0.5421 - val_accuracy: 0.8143 Epoch 30/80 74/74 [==============================] - 35s 463ms/step - loss: 0.5553 - accuracy: 0.7957 - val_loss: 0.6288 - val_accuracy: 0.7785 Epoch 31/80 74/74 [==============================] - 35s 463ms/step - loss: 0.5364 - accuracy: 0.8033 - val_loss: 0.5677 - val_accuracy: 0.7956 Epoch 32/80 74/74 [==============================] - 35s 462ms/step - loss: 0.5353 - accuracy: 0.8008 - val_loss: 0.5050 - val_accuracy: 0.8177 Epoch 33/80 74/74 [==============================] - 35s 463ms/step - loss: 0.5327 - accuracy: 0.7931 - val_loss: 0.5286 - val_accuracy: 0.8092 Epoch 34/80 74/74 [==============================] - 35s 464ms/step - loss: 0.4982 - accuracy: 0.8182 - val_loss: 0.5487 - val_accuracy: 0.7973 Epoch 35/80 74/74 [==============================] - 35s 465ms/step - loss: 0.5025 - accuracy: 0.8037 - val_loss: 0.5164 - val_accuracy: 0.8143 Epoch 36/80 74/74 [==============================] - 35s 463ms/step - loss: 0.4868 - accuracy: 0.8238 - val_loss: 0.5123 - val_accuracy: 0.8143 Epoch 37/80 74/74 [==============================] - 35s 465ms/step - loss: 0.4997 - accuracy: 0.8072 - val_loss: 0.4611 - val_accuracy: 0.8348 Epoch 38/80 74/74 [==============================] - 35s 463ms/step - loss: 0.4617 - accuracy: 0.8263 - val_loss: 0.5251 - val_accuracy: 0.8109 Epoch 39/80 74/74 [==============================] - 35s 465ms/step - loss: 0.4830 - accuracy: 0.8169 - val_loss: 0.5330 - val_accuracy: 0.8041 Epoch 40/80 74/74 [==============================] - 35s 466ms/step - loss: 0.4690 - accuracy: 0.8229 - val_loss: 0.5794 - val_accuracy: 0.7700 Epoch 41/80 74/74 [==============================] - 35s 465ms/step - loss: 0.4657 - accuracy: 0.8250 - val_loss: 0.4679 - val_accuracy: 0.8382 Epoch 42/80 74/74 [==============================] - 35s 463ms/step - loss: 0.4941 - accuracy: 0.8123 - val_loss: 0.4858 - val_accuracy: 0.8228 Epoch 43/80 74/74 [==============================] - 35s 466ms/step - loss: 0.4500 - accuracy: 0.8297 - val_loss: 0.4614 - val_accuracy: 0.8365 Epoch 44/80 74/74 [==============================] - 35s 464ms/step - loss: 0.4776 - accuracy: 0.8169 - val_loss: 0.5513 - val_accuracy: 0.7853 Epoch 45/80 74/74 [==============================] - 35s 466ms/step - loss: 0.4634 - accuracy: 0.8280 - val_loss: 0.5430 - val_accuracy: 0.7990 Epoch 46/80 74/74 [==============================] - 35s 464ms/step - loss: 0.4478 - accuracy: 0.8365 - val_loss: 0.5213 - val_accuracy: 0.8177 Epoch 47/80 74/74 [==============================] - 35s 465ms/step - loss: 0.4520 - accuracy: 0.8365 - val_loss: 0.4982 - val_accuracy: 0.8177
# Visualization of the learning curves
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.ylim([0.0, 2.0])
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend(['train', 'valid'])
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.ylim([0.5, 1.0])
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(['train', 'valid'])
<matplotlib.legend.Legend at 0x257e022c5b0>
net.save("models/B3D2DropAFine1.keras")
# Architecture definition 5
inputs = keras.Input((None,None,3))
x = inputs
x = keras.layers.RandomCrop(224, 224)(x)
x = keras.layers.RandomFlip(mode='horizontal')(x)
x = keras.layers.RandomContrast(0.25)(x)
x = keras.layers.Conv2D(64, 5, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.Conv2D(128, 5, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.Conv2D(256, 5, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.GlobalMaxPooling2D()(x)
outputs = keras.layers.Dense(1024, activation="softmax")(x)
x = keras.layers.Dropout(0.2)(x)
outputs = keras.layers.Dense(512, activation="softmax")(x)
outputs = keras.layers.Dense(num_classes, activation="softmax")(x)
net = keras.Model(inputs, outputs)
callback = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)
lr_schedule = keras.optimizers.schedules.InverseTimeDecay(
initial_learning_rate = 0.0005,
decay_steps = 65,
decay_rate = 0.08)
optimizer = keras.optimizers.Adam(learning_rate=lr_schedule)
net.compile(loss=keras.losses.categorical_crossentropy,
optimizer=optimizer,
metrics=['accuracy'])
# Model training
history = net.fit(train_ds_256,
epochs=80,
validation_data=val_ds,
callbacks=[callback])
Epoch 1/80 74/74 [==============================] - 70s 628ms/step - loss: 1.9723 - accuracy: 0.4572 - val_loss: 3.0639 - val_accuracy: 0.4123 Epoch 2/80 74/74 [==============================] - 34s 467ms/step - loss: 1.2672 - accuracy: 0.5568 - val_loss: 1.9430 - val_accuracy: 0.4514 Epoch 3/80 74/74 [==============================] - 36s 485ms/step - loss: 1.1827 - accuracy: 0.5892 - val_loss: 0.9465 - val_accuracy: 0.6320 Epoch 4/80 74/74 [==============================] - 35s 480ms/step - loss: 1.0537 - accuracy: 0.6377 - val_loss: 0.9106 - val_accuracy: 0.6491 Epoch 5/80 74/74 [==============================] - 36s 486ms/step - loss: 1.0364 - accuracy: 0.6394 - val_loss: 0.7594 - val_accuracy: 0.7206 Epoch 6/80 74/74 [==============================] - 35s 479ms/step - loss: 0.9545 - accuracy: 0.6671 - val_loss: 0.7358 - val_accuracy: 0.7138 Epoch 7/80 74/74 [==============================] - 36s 483ms/step - loss: 0.8745 - accuracy: 0.6854 - val_loss: 0.7895 - val_accuracy: 0.7121 Epoch 8/80 74/74 [==============================] - 36s 486ms/step - loss: 0.8328 - accuracy: 0.7080 - val_loss: 0.7764 - val_accuracy: 0.7070 Epoch 9/80 74/74 [==============================] - 36s 481ms/step - loss: 0.8246 - accuracy: 0.7050 - val_loss: 0.6681 - val_accuracy: 0.7308 Epoch 10/80 74/74 [==============================] - 36s 487ms/step - loss: 0.7454 - accuracy: 0.7271 - val_loss: 0.7120 - val_accuracy: 0.7342 Epoch 11/80 74/74 [==============================] - 36s 486ms/step - loss: 0.7493 - accuracy: 0.7186 - val_loss: 0.6116 - val_accuracy: 0.7666 Epoch 12/80 74/74 [==============================] - 36s 483ms/step - loss: 0.7184 - accuracy: 0.7382 - val_loss: 0.6680 - val_accuracy: 0.7615 Epoch 13/80 74/74 [==============================] - 36s 485ms/step - loss: 0.7030 - accuracy: 0.7510 - val_loss: 0.6577 - val_accuracy: 0.7666 Epoch 14/80 74/74 [==============================] - 36s 485ms/step - loss: 0.6629 - accuracy: 0.7569 - val_loss: 0.6102 - val_accuracy: 0.7683 Epoch 15/80 74/74 [==============================] - 36s 491ms/step - loss: 0.6383 - accuracy: 0.7629 - val_loss: 0.7078 - val_accuracy: 0.7564 Epoch 16/80 74/74 [==============================] - 36s 491ms/step - loss: 0.6192 - accuracy: 0.7722 - val_loss: 0.6290 - val_accuracy: 0.7700 Epoch 17/80 74/74 [==============================] - 36s 485ms/step - loss: 0.5985 - accuracy: 0.7825 - val_loss: 0.6485 - val_accuracy: 0.7462 Epoch 18/80 74/74 [==============================] - 36s 488ms/step - loss: 0.6086 - accuracy: 0.7705 - val_loss: 0.8143 - val_accuracy: 0.7223 Epoch 19/80 74/74 [==============================] - 36s 491ms/step - loss: 0.5763 - accuracy: 0.7808 - val_loss: 0.6018 - val_accuracy: 0.7836 Epoch 20/80 74/74 [==============================] - 36s 489ms/step - loss: 0.5878 - accuracy: 0.7850 - val_loss: 0.5289 - val_accuracy: 0.8262 Epoch 21/80 74/74 [==============================] - 36s 492ms/step - loss: 0.5544 - accuracy: 0.7969 - val_loss: 0.5722 - val_accuracy: 0.8041 Epoch 22/80 74/74 [==============================] - 36s 491ms/step - loss: 0.5402 - accuracy: 0.8020 - val_loss: 0.6061 - val_accuracy: 0.7836 Epoch 23/80 74/74 [==============================] - 36s 491ms/step - loss: 0.5272 - accuracy: 0.8016 - val_loss: 0.7183 - val_accuracy: 0.7513 Epoch 24/80 74/74 [==============================] - 36s 491ms/step - loss: 0.5300 - accuracy: 0.8059 - val_loss: 0.6860 - val_accuracy: 0.7428 Epoch 25/80 74/74 [==============================] - 36s 491ms/step - loss: 0.4716 - accuracy: 0.8242 - val_loss: 0.5214 - val_accuracy: 0.8143 Epoch 26/80 74/74 [==============================] - 36s 490ms/step - loss: 0.4892 - accuracy: 0.8203 - val_loss: 0.5150 - val_accuracy: 0.8194 Epoch 27/80 74/74 [==============================] - 36s 487ms/step - loss: 0.4843 - accuracy: 0.8267 - val_loss: 0.6179 - val_accuracy: 0.7717 Epoch 28/80 74/74 [==============================] - 36s 487ms/step - loss: 0.4709 - accuracy: 0.8233 - val_loss: 0.5313 - val_accuracy: 0.8109 Epoch 29/80 74/74 [==============================] - 36s 485ms/step - loss: 0.4921 - accuracy: 0.8152 - val_loss: 0.6142 - val_accuracy: 0.7802 Epoch 30/80 74/74 [==============================] - 36s 486ms/step - loss: 0.4661 - accuracy: 0.8314 - val_loss: 0.6157 - val_accuracy: 0.7683 Epoch 31/80 74/74 [==============================] - 36s 490ms/step - loss: 0.4270 - accuracy: 0.8382 - val_loss: 0.5151 - val_accuracy: 0.8126 Epoch 32/80 74/74 [==============================] - 36s 492ms/step - loss: 0.4274 - accuracy: 0.8408 - val_loss: 0.5333 - val_accuracy: 0.8211 Epoch 33/80 74/74 [==============================] - 37s 494ms/step - loss: 0.4425 - accuracy: 0.8327 - val_loss: 0.5284 - val_accuracy: 0.8160 Epoch 34/80 74/74 [==============================] - 37s 495ms/step - loss: 0.4163 - accuracy: 0.8433 - val_loss: 0.5098 - val_accuracy: 0.8126 Epoch 35/80 74/74 [==============================] - 37s 495ms/step - loss: 0.4106 - accuracy: 0.8510 - val_loss: 0.5483 - val_accuracy: 0.7956 Epoch 36/80 74/74 [==============================] - 37s 496ms/step - loss: 0.4352 - accuracy: 0.8382 - val_loss: 0.5015 - val_accuracy: 0.8313 Epoch 37/80 74/74 [==============================] - 37s 497ms/step - loss: 0.4004 - accuracy: 0.8540 - val_loss: 0.4969 - val_accuracy: 0.8330 Epoch 38/80 74/74 [==============================] - 37s 497ms/step - loss: 0.4063 - accuracy: 0.8472 - val_loss: 0.5872 - val_accuracy: 0.7785 Epoch 39/80 74/74 [==============================] - 37s 498ms/step - loss: 0.3842 - accuracy: 0.8561 - val_loss: 0.4957 - val_accuracy: 0.8296 Epoch 40/80 74/74 [==============================] - 37s 500ms/step - loss: 0.3688 - accuracy: 0.8655 - val_loss: 0.5243 - val_accuracy: 0.8143 Epoch 41/80 74/74 [==============================] - 37s 499ms/step - loss: 0.3777 - accuracy: 0.8527 - val_loss: 0.4983 - val_accuracy: 0.8262 Epoch 42/80 74/74 [==============================] - 37s 501ms/step - loss: 0.3728 - accuracy: 0.8557 - val_loss: 0.4954 - val_accuracy: 0.8262 Epoch 43/80 74/74 [==============================] - 37s 500ms/step - loss: 0.3836 - accuracy: 0.8599 - val_loss: 0.5006 - val_accuracy: 0.8075 Epoch 44/80 74/74 [==============================] - 37s 501ms/step - loss: 0.3626 - accuracy: 0.8685 - val_loss: 0.4967 - val_accuracy: 0.8296 Epoch 45/80 74/74 [==============================] - 37s 501ms/step - loss: 0.3672 - accuracy: 0.8659 - val_loss: 0.4865 - val_accuracy: 0.8228 Epoch 46/80 74/74 [==============================] - 37s 501ms/step - loss: 0.3436 - accuracy: 0.8748 - val_loss: 0.4235 - val_accuracy: 0.8535 Epoch 47/80 74/74 [==============================] - 37s 501ms/step - loss: 0.3676 - accuracy: 0.8612 - val_loss: 0.4728 - val_accuracy: 0.8330 Epoch 48/80 74/74 [==============================] - 38s 504ms/step - loss: 0.3482 - accuracy: 0.8655 - val_loss: 0.4464 - val_accuracy: 0.8399 Epoch 49/80 74/74 [==============================] - 38s 502ms/step - loss: 0.3303 - accuracy: 0.8770 - val_loss: 0.4197 - val_accuracy: 0.8518 Epoch 50/80 74/74 [==============================] - 38s 503ms/step - loss: 0.3237 - accuracy: 0.8782 - val_loss: 0.4473 - val_accuracy: 0.8484 Epoch 51/80 74/74 [==============================] - 38s 503ms/step - loss: 0.3364 - accuracy: 0.8765 - val_loss: 0.4770 - val_accuracy: 0.8296 Epoch 52/80 74/74 [==============================] - 38s 503ms/step - loss: 0.3416 - accuracy: 0.8663 - val_loss: 0.4995 - val_accuracy: 0.8143 Epoch 53/80 74/74 [==============================] - 38s 504ms/step - loss: 0.3153 - accuracy: 0.8804 - val_loss: 0.4546 - val_accuracy: 0.8433 Epoch 54/80 74/74 [==============================] - 38s 504ms/step - loss: 0.3368 - accuracy: 0.8757 - val_loss: 0.4601 - val_accuracy: 0.8450 Epoch 55/80 74/74 [==============================] - 38s 505ms/step - loss: 0.3104 - accuracy: 0.8817 - val_loss: 0.5010 - val_accuracy: 0.8279 Epoch 56/80 74/74 [==============================] - 38s 504ms/step - loss: 0.3179 - accuracy: 0.8761 - val_loss: 0.4905 - val_accuracy: 0.8348 Epoch 57/80 74/74 [==============================] - 38s 504ms/step - loss: 0.3270 - accuracy: 0.8770 - val_loss: 0.4539 - val_accuracy: 0.8348 Epoch 58/80 74/74 [==============================] - 38s 507ms/step - loss: 0.2982 - accuracy: 0.8876 - val_loss: 0.5045 - val_accuracy: 0.8245 Epoch 59/80 74/74 [==============================] - 38s 506ms/step - loss: 0.3111 - accuracy: 0.8804 - val_loss: 0.4730 - val_accuracy: 0.8416
# Visualization of the learning curves
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.ylim([0.0, 2.0])
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend(['train', 'valid'])
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.ylim([0.5, 1.0])
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(['train', 'valid'])
<matplotlib.legend.Legend at 0x2580fd37ca0>
net.save("models/B3D2DropAFine2.keras")
# Architecture definition
inputs = keras.Input((None,None,3))
x = inputs
x = keras.layers.RandomCrop(224, 224)(x)
x = keras.layers.RandomFlip(mode='horizontal')(x)
x = keras.layers.RandomContrast(0.25)(x)
x = keras.layers.Conv2D(64, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.Conv2D(128, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.Conv2D(256, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.GlobalMaxPooling2D()(x)
outputs = keras.layers.Dense(1024, activation="softmax")(x)
x = keras.layers.Dropout(0.2)(x)
outputs = keras.layers.Dense(512, activation="softmax")(x)
outputs = keras.layers.Dense(num_classes, activation="softmax")(x)
net = keras.Model(inputs, outputs)
callback = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)
lr_schedule = keras.optimizers.schedules.InverseTimeDecay(
initial_learning_rate = 0.0005,
decay_steps = 65,
decay_rate = 0.08)
optimizer = keras.optimizers.RMSprop(learning_rate=lr_schedule)
net.compile(loss=keras.losses.categorical_crossentropy,
optimizer=optimizer,
metrics=['accuracy'])
# Model training
history = net.fit(train_ds_256,
epochs=80,
validation_data=val_ds,
callbacks=[callback])
Epoch 1/80 74/74 [==============================] - 38s 469ms/step - loss: 2.0206 - accuracy: 0.4534 - val_loss: 2.5109 - val_accuracy: 0.4310 Epoch 2/80 74/74 [==============================] - 35s 464ms/step - loss: 1.4229 - accuracy: 0.5568 - val_loss: 1.1077 - val_accuracy: 0.6031 Epoch 3/80 74/74 [==============================] - 35s 464ms/step - loss: 1.2648 - accuracy: 0.5956 - val_loss: 1.3544 - val_accuracy: 0.5826 Epoch 4/80 74/74 [==============================] - 35s 463ms/step - loss: 1.0763 - accuracy: 0.6415 - val_loss: 0.8185 - val_accuracy: 0.6899 Epoch 5/80 74/74 [==============================] - 35s 463ms/step - loss: 1.0171 - accuracy: 0.6607 - val_loss: 0.9566 - val_accuracy: 0.6644 Epoch 6/80 74/74 [==============================] - 35s 464ms/step - loss: 0.9734 - accuracy: 0.6611 - val_loss: 1.0071 - val_accuracy: 0.6644 Epoch 7/80 74/74 [==============================] - 35s 463ms/step - loss: 0.9270 - accuracy: 0.6858 - val_loss: 0.7377 - val_accuracy: 0.7036 Epoch 8/80 74/74 [==============================] - 35s 464ms/step - loss: 0.8417 - accuracy: 0.7033 - val_loss: 0.6614 - val_accuracy: 0.7445 Epoch 9/80 74/74 [==============================] - 34s 462ms/step - loss: 0.8066 - accuracy: 0.7114 - val_loss: 0.7229 - val_accuracy: 0.7291 Epoch 10/80 74/74 [==============================] - 34s 463ms/step - loss: 0.8105 - accuracy: 0.7114 - val_loss: 0.8800 - val_accuracy: 0.6934 Epoch 11/80 74/74 [==============================] - 34s 462ms/step - loss: 0.7526 - accuracy: 0.7305 - val_loss: 0.7667 - val_accuracy: 0.7274 Epoch 12/80 74/74 [==============================] - 35s 463ms/step - loss: 0.7365 - accuracy: 0.7437 - val_loss: 0.6912 - val_accuracy: 0.7445 Epoch 13/80 74/74 [==============================] - 35s 463ms/step - loss: 0.7325 - accuracy: 0.7335 - val_loss: 0.5892 - val_accuracy: 0.7871 Epoch 14/80 74/74 [==============================] - 34s 462ms/step - loss: 0.7110 - accuracy: 0.7441 - val_loss: 0.7786 - val_accuracy: 0.7036 Epoch 15/80 74/74 [==============================] - 34s 463ms/step - loss: 0.6913 - accuracy: 0.7476 - val_loss: 0.7168 - val_accuracy: 0.7462 Epoch 16/80 74/74 [==============================] - 34s 462ms/step - loss: 0.6759 - accuracy: 0.7565 - val_loss: 0.6973 - val_accuracy: 0.7479 Epoch 17/80 74/74 [==============================] - 35s 467ms/step - loss: 0.6650 - accuracy: 0.7612 - val_loss: 0.6009 - val_accuracy: 0.7888 Epoch 18/80 74/74 [==============================] - 35s 466ms/step - loss: 0.6584 - accuracy: 0.7607 - val_loss: 0.7154 - val_accuracy: 0.7598 Epoch 19/80 74/74 [==============================] - 35s 463ms/step - loss: 0.6326 - accuracy: 0.7782 - val_loss: 0.6790 - val_accuracy: 0.7751 Epoch 20/80 74/74 [==============================] - 35s 463ms/step - loss: 0.6059 - accuracy: 0.7786 - val_loss: 0.5421 - val_accuracy: 0.8041 Epoch 21/80 74/74 [==============================] - 35s 464ms/step - loss: 0.6082 - accuracy: 0.7795 - val_loss: 0.5861 - val_accuracy: 0.7785 Epoch 22/80 74/74 [==============================] - 35s 463ms/step - loss: 0.6017 - accuracy: 0.7769 - val_loss: 0.4950 - val_accuracy: 0.8126 Epoch 23/80 74/74 [==============================] - 35s 463ms/step - loss: 0.5798 - accuracy: 0.7867 - val_loss: 0.5994 - val_accuracy: 0.7666 Epoch 24/80 74/74 [==============================] - 35s 464ms/step - loss: 0.5846 - accuracy: 0.7820 - val_loss: 0.6202 - val_accuracy: 0.7666 Epoch 25/80 74/74 [==============================] - 35s 464ms/step - loss: 0.5749 - accuracy: 0.7859 - val_loss: 0.5482 - val_accuracy: 0.7836 Epoch 26/80 74/74 [==============================] - 35s 464ms/step - loss: 0.5405 - accuracy: 0.8037 - val_loss: 0.5649 - val_accuracy: 0.7836 Epoch 27/80 74/74 [==============================] - 35s 465ms/step - loss: 0.5723 - accuracy: 0.7961 - val_loss: 0.5683 - val_accuracy: 0.7905 Epoch 28/80 74/74 [==============================] - 35s 465ms/step - loss: 0.5322 - accuracy: 0.8118 - val_loss: 0.5604 - val_accuracy: 0.7836 Epoch 29/80 74/74 [==============================] - 35s 465ms/step - loss: 0.5373 - accuracy: 0.8054 - val_loss: 0.5751 - val_accuracy: 0.7973 Epoch 30/80 74/74 [==============================] - 35s 468ms/step - loss: 0.5539 - accuracy: 0.7999 - val_loss: 0.5139 - val_accuracy: 0.8092 Epoch 31/80 74/74 [==============================] - 35s 472ms/step - loss: 0.5313 - accuracy: 0.7978 - val_loss: 0.5690 - val_accuracy: 0.7853 Epoch 32/80 74/74 [==============================] - 35s 470ms/step - loss: 0.5071 - accuracy: 0.8110 - val_loss: 0.5958 - val_accuracy: 0.7871
# Visualization of the learning curves
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.ylim([0.0, 2.0])
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend(['train', 'valid'])
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.ylim([0.5, 1.0])
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(['train', 'valid'])
<matplotlib.legend.Legend at 0x257800d99a0>
net.save("models/B3D2DropAFine3.keras")
None of the modification resulted in better performances of the model.
Most of the literature on flower recognition with CNN (Y Liu, 2016, I Gogul, 2017,
T Nguyen) cites background as one of the biggest problem in flower classification. This is because flowers, because of their environment, tend to have complex background, and that complexity can hurt the performances of a classification model.
Even if literature cites different segmentation methods to resolve the issue, we are going to utilize a rather "simple" (for what regards application) method: Segment Anything a Kirillov, 2023. More specifically, we are going to use LANG segment anything, an open-source project that combines the power of instance segmentation and text prompts to generate masks for specific objects in images. In this way, segmenting our images will be as easy as running the model specifying a prompt like "flower".
# Download the model
%pip install -U git+https://github.com/luca-medeiros/lang-segment-anything.git
Collecting git+https://github.com/luca-medeiros/lang-segment-anything.git Cloning https://github.com/luca-medeiros/lang-segment-anything.git to /tmp/pip-req-build-pxs8esfi Running command git clone --filter=blob:none --quiet https://github.com/luca-medeiros/lang-segment-anything.git /tmp/pip-req-build-pxs8esfi Resolved https://github.com/luca-medeiros/lang-segment-anything.git to commit f4ca2960a97cb73aff2c459a9d0f06c7674452e4 Installing build dependencies ... done Getting requirements to build wheel ... done Preparing metadata (pyproject.toml) ... done Collecting groundingdino@ git+https://github.com/IDEA-Research/GroundingDINO.git (from lang-sam==0.1.0) Cloning https://github.com/IDEA-Research/GroundingDINO.git to /tmp/pip-install-2nsrj_78/groundingdino_0e63f605efad4244af80591a5f5bfad1 Running command git clone --filter=blob:none --quiet https://github.com/IDEA-Research/GroundingDINO.git /tmp/pip-install-2nsrj_78/groundingdino_0e63f605efad4244af80591a5f5bfad1 Resolved https://github.com/IDEA-Research/GroundingDINO.git to commit c023468fafeb0933d06aa8ba49d96089ce9a6af3 Preparing metadata (setup.py) ... done Collecting segment-anything@ git+https://github.com/facebookresearch/segment-anything.git (from lang-sam==0.1.0) Cloning https://github.com/facebookresearch/segment-anything.git to /tmp/pip-install-2nsrj_78/segment-anything_e44e8a45738a46b0a62d55f146b89e8b Running command git clone --filter=blob:none --quiet https://github.com/facebookresearch/segment-anything.git /tmp/pip-install-2nsrj_78/segment-anything_e44e8a45738a46b0a62d55f146b89e8b Resolved https://github.com/facebookresearch/segment-anything.git to commit 6fdee8f2727f4506cfbbe553e23b895e27956588 Preparing metadata (setup.py) ... done Collecting Pillow==9.3.0 (from lang-sam==0.1.0) Downloading Pillow-9.3.0-cp310-cp310-manylinux_2_28_x86_64.whl (3.3 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.3/3.3 MB 32.8 MB/s eta 0:00:00 Collecting gradio<4.0.0,>=3.24.1 (from lang-sam==0.1.0) Downloading gradio-3.50.2-py3-none-any.whl (20.3 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 20.3/20.3 MB 65.2 MB/s eta 0:00:00 Collecting huggingface-hub<0.17.0,>=0.16.4 (from lang-sam==0.1.0) Downloading huggingface_hub-0.16.4-py3-none-any.whl (268 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 268.8/268.8 kB 37.1 MB/s eta 0:00:00 Collecting lightning<3.0.0,>=2.0.1 (from lang-sam==0.1.0) Downloading lightning-2.2.1-py3-none-any.whl (2.1 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.1/2.1 MB 66.0 MB/s eta 0:00:00 Requirement already satisfied: numpy<2.0.0,>=1.24.2 in /usr/local/lib/python3.10/dist-packages (from lang-sam==0.1.0) (1.25.2) Requirement already satisfied: opencv_python<5.0.0.0,>=4.7.0.72 in /usr/local/lib/python3.10/dist-packages (from lang-sam==0.1.0) (4.8.0.76) Requirement already satisfied: transformers<5.0.0,>=4.27.4 in /usr/local/lib/python3.10/dist-packages (from lang-sam==0.1.0) (4.38.2) Collecting aiofiles<24.0,>=22.0 (from gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) Downloading aiofiles-23.2.1-py3-none-any.whl (15 kB) Requirement already satisfied: altair<6.0,>=4.2.0 in /usr/local/lib/python3.10/dist-packages (from gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (4.2.2) Collecting fastapi (from gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) Downloading fastapi-0.110.0-py3-none-any.whl (92 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 92.1/92.1 kB 15.3 MB/s eta 0:00:00 Collecting ffmpy (from gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) Downloading ffmpy-0.3.2.tar.gz (5.5 kB) Preparing metadata (setup.py) ... done Collecting gradio-client==0.6.1 (from gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) Downloading gradio_client-0.6.1-py3-none-any.whl (299 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 299.2/299.2 kB 36.9 MB/s eta 0:00:00 Collecting httpx (from gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) Downloading httpx-0.27.0-py3-none-any.whl (75 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 75.6/75.6 kB 13.6 MB/s eta 0:00:00 Requirement already satisfied: importlib-resources<7.0,>=1.3 in /usr/local/lib/python3.10/dist-packages (from gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (6.3.0) Requirement already satisfied: jinja2<4.0 in /usr/local/lib/python3.10/dist-packages (from gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (3.1.3) Requirement already satisfied: markupsafe~=2.0 in /usr/local/lib/python3.10/dist-packages (from gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (2.1.5) Requirement already satisfied: matplotlib~=3.0 in /usr/local/lib/python3.10/dist-packages (from gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (3.7.1) Collecting orjson~=3.0 (from gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) Downloading orjson-3.9.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (138 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 138.5/138.5 kB 21.4 MB/s eta 0:00:00 Requirement already satisfied: packaging in /usr/local/lib/python3.10/dist-packages (from gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (24.0) Requirement already satisfied: pandas<3.0,>=1.0 in /usr/local/lib/python3.10/dist-packages (from gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (1.5.3) Requirement already satisfied: pydantic!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,<3.0.0,>=1.7.4 in /usr/local/lib/python3.10/dist-packages (from gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (2.6.4) Collecting pydub (from gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) Downloading pydub-0.25.1-py2.py3-none-any.whl (32 kB) Collecting python-multipart (from gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) Downloading python_multipart-0.0.9-py3-none-any.whl (22 kB) Requirement already satisfied: pyyaml<7.0,>=5.0 in /usr/local/lib/python3.10/dist-packages (from gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (6.0.1) Requirement already satisfied: requests~=2.0 in /usr/local/lib/python3.10/dist-packages (from gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (2.31.0) Collecting semantic-version~=2.0 (from gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) Downloading semantic_version-2.10.0-py2.py3-none-any.whl (15 kB) Requirement already satisfied: typing-extensions~=4.0 in /usr/local/lib/python3.10/dist-packages (from gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (4.10.0) Collecting uvicorn>=0.14.0 (from gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) Downloading uvicorn-0.29.0-py3-none-any.whl (60 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 60.8/60.8 kB 10.6 MB/s eta 0:00:00 Collecting websockets<12.0,>=10.0 (from gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) Downloading websockets-11.0.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (129 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 129.9/129.9 kB 17.5 MB/s eta 0:00:00 Requirement already satisfied: fsspec in /usr/local/lib/python3.10/dist-packages (from gradio-client==0.6.1->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (2023.6.0) Requirement already satisfied: filelock in /usr/local/lib/python3.10/dist-packages (from huggingface-hub<0.17.0,>=0.16.4->lang-sam==0.1.0) (3.13.1) Requirement already satisfied: tqdm>=4.42.1 in /usr/local/lib/python3.10/dist-packages (from huggingface-hub<0.17.0,>=0.16.4->lang-sam==0.1.0) (4.66.2) Collecting lightning-utilities<2.0,>=0.8.0 (from lightning<3.0.0,>=2.0.1->lang-sam==0.1.0) Downloading lightning_utilities-0.11.0-py3-none-any.whl (25 kB) Requirement already satisfied: torch<4.0,>=1.13.0 in /usr/local/lib/python3.10/dist-packages (from lightning<3.0.0,>=2.0.1->lang-sam==0.1.0) (2.2.1+cu121) Collecting torchmetrics<3.0,>=0.7.0 (from lightning<3.0.0,>=2.0.1->lang-sam==0.1.0) Downloading torchmetrics-1.3.2-py3-none-any.whl (841 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 841.5/841.5 kB 54.0 MB/s eta 0:00:00 Collecting pytorch-lightning (from lightning<3.0.0,>=2.0.1->lang-sam==0.1.0) Downloading pytorch_lightning-2.2.1-py3-none-any.whl (801 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 801.6/801.6 kB 50.1 MB/s eta 0:00:00 INFO: pip is looking at multiple versions of transformers to determine which version is compatible with other requirements. This could take a while. Collecting transformers<5.0.0,>=4.27.4 (from lang-sam==0.1.0) Downloading transformers-4.39.0-py3-none-any.whl (8.8 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 8.8/8.8 MB 95.6 MB/s eta 0:00:00 Downloading transformers-4.38.1-py3-none-any.whl (8.5 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 8.5/8.5 MB 107.4 MB/s eta 0:00:00 Downloading transformers-4.38.0-py3-none-any.whl (8.5 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 8.5/8.5 MB 98.2 MB/s eta 0:00:00 Downloading transformers-4.37.2-py3-none-any.whl (8.4 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 8.4/8.4 MB 101.7 MB/s eta 0:00:00 Downloading transformers-4.37.1-py3-none-any.whl (8.4 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 8.4/8.4 MB 108.1 MB/s eta 0:00:00 Downloading transformers-4.37.0-py3-none-any.whl (8.4 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 8.4/8.4 MB 99.2 MB/s eta 0:00:00 Downloading transformers-4.36.2-py3-none-any.whl (8.2 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 8.2/8.2 MB 102.3 MB/s eta 0:00:00 INFO: pip is looking at multiple versions of transformers to determine which version is compatible with other requirements. This could take a while. Downloading transformers-4.36.1-py3-none-any.whl (8.3 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 8.3/8.3 MB 97.4 MB/s eta 0:00:00 Downloading transformers-4.36.0-py3-none-any.whl (8.2 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 8.2/8.2 MB 25.5 MB/s eta 0:00:00 Downloading transformers-4.35.2-py3-none-any.whl (7.9 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 7.9/7.9 MB 109.2 MB/s eta 0:00:00 Requirement already satisfied: regex!=2019.12.17 in /usr/local/lib/python3.10/dist-packages (from transformers<5.0.0,>=4.27.4->lang-sam==0.1.0) (2023.12.25) Requirement already satisfied: tokenizers<0.19,>=0.14 in /usr/local/lib/python3.10/dist-packages (from transformers<5.0.0,>=4.27.4->lang-sam==0.1.0) (0.15.2) Requirement already satisfied: safetensors>=0.3.1 in /usr/local/lib/python3.10/dist-packages (from transformers<5.0.0,>=4.27.4->lang-sam==0.1.0) (0.4.2) Requirement already satisfied: torchvision in /usr/local/lib/python3.10/dist-packages (from groundingdino@ git+https://github.com/IDEA-Research/GroundingDINO.git->lang-sam==0.1.0) (0.17.1+cu121) Collecting addict (from groundingdino@ git+https://github.com/IDEA-Research/GroundingDINO.git->lang-sam==0.1.0) Downloading addict-2.4.0-py3-none-any.whl (3.8 kB) Collecting yapf (from groundingdino@ git+https://github.com/IDEA-Research/GroundingDINO.git->lang-sam==0.1.0) Downloading yapf-0.40.2-py3-none-any.whl (254 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 254.7/254.7 kB 35.0 MB/s eta 0:00:00 Collecting timm (from groundingdino@ git+https://github.com/IDEA-Research/GroundingDINO.git->lang-sam==0.1.0) Downloading timm-0.9.16-py3-none-any.whl (2.2 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.2/2.2 MB 89.2 MB/s eta 0:00:00 Collecting supervision (from groundingdino@ git+https://github.com/IDEA-Research/GroundingDINO.git->lang-sam==0.1.0) Downloading supervision-0.19.0-py3-none-any.whl (97 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 97.1/97.1 kB 16.2 MB/s eta 0:00:00 Requirement already satisfied: pycocotools in /usr/local/lib/python3.10/dist-packages (from groundingdino@ git+https://github.com/IDEA-Research/GroundingDINO.git->lang-sam==0.1.0) (2.0.7) Requirement already satisfied: entrypoints in /usr/local/lib/python3.10/dist-packages (from altair<6.0,>=4.2.0->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (0.4) Requirement already satisfied: jsonschema>=3.0 in /usr/local/lib/python3.10/dist-packages (from altair<6.0,>=4.2.0->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (4.19.2) Requirement already satisfied: toolz in /usr/local/lib/python3.10/dist-packages (from altair<6.0,>=4.2.0->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (0.12.1) Requirement already satisfied: aiohttp!=4.0.0a0,!=4.0.0a1 in /usr/local/lib/python3.10/dist-packages (from fsspec->gradio-client==0.6.1->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (3.9.3) Requirement already satisfied: setuptools in /usr/local/lib/python3.10/dist-packages (from lightning-utilities<2.0,>=0.8.0->lightning<3.0.0,>=2.0.1->lang-sam==0.1.0) (67.7.2) Requirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib~=3.0->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (1.2.0) Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.10/dist-packages (from matplotlib~=3.0->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (0.12.1) Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib~=3.0->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (4.49.0) Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib~=3.0->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (1.4.5) Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib~=3.0->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (3.1.2) Requirement already satisfied: python-dateutil>=2.7 in /usr/local/lib/python3.10/dist-packages (from matplotlib~=3.0->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (2.8.2) Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.10/dist-packages (from pandas<3.0,>=1.0->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (2023.4) Requirement already satisfied: annotated-types>=0.4.0 in /usr/local/lib/python3.10/dist-packages (from pydantic!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,<3.0.0,>=1.7.4->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (0.6.0) Requirement already satisfied: pydantic-core==2.16.3 in /usr/local/lib/python3.10/dist-packages (from pydantic!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,<3.0.0,>=1.7.4->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (2.16.3) Requirement already satisfied: charset-normalizer<4,>=2 in /usr/local/lib/python3.10/dist-packages (from requests~=2.0->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (3.3.2) Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.10/dist-packages (from requests~=2.0->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (3.6) Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/lib/python3.10/dist-packages (from requests~=2.0->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (2.0.7) Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.10/dist-packages (from requests~=2.0->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (2024.2.2) Requirement already satisfied: sympy in /usr/local/lib/python3.10/dist-packages (from torch<4.0,>=1.13.0->lightning<3.0.0,>=2.0.1->lang-sam==0.1.0) (1.12) Requirement already satisfied: networkx in /usr/local/lib/python3.10/dist-packages (from torch<4.0,>=1.13.0->lightning<3.0.0,>=2.0.1->lang-sam==0.1.0) (3.2.1) Collecting nvidia-cuda-nvrtc-cu12==12.1.105 (from torch<4.0,>=1.13.0->lightning<3.0.0,>=2.0.1->lang-sam==0.1.0) Downloading nvidia_cuda_nvrtc_cu12-12.1.105-py3-none-manylinux1_x86_64.whl (23.7 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 23.7/23.7 MB 60.3 MB/s eta 0:00:00 Collecting nvidia-cuda-runtime-cu12==12.1.105 (from torch<4.0,>=1.13.0->lightning<3.0.0,>=2.0.1->lang-sam==0.1.0) Downloading nvidia_cuda_runtime_cu12-12.1.105-py3-none-manylinux1_x86_64.whl (823 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 823.6/823.6 kB 68.5 MB/s eta 0:00:00 Collecting nvidia-cuda-cupti-cu12==12.1.105 (from torch<4.0,>=1.13.0->lightning<3.0.0,>=2.0.1->lang-sam==0.1.0) Downloading nvidia_cuda_cupti_cu12-12.1.105-py3-none-manylinux1_x86_64.whl (14.1 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 14.1/14.1 MB 90.3 MB/s eta 0:00:00 Collecting nvidia-cudnn-cu12==8.9.2.26 (from torch<4.0,>=1.13.0->lightning<3.0.0,>=2.0.1->lang-sam==0.1.0) Downloading nvidia_cudnn_cu12-8.9.2.26-py3-none-manylinux1_x86_64.whl (731.7 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 731.7/731.7 MB 2.4 MB/s eta 0:00:00 Collecting nvidia-cublas-cu12==12.1.3.1 (from torch<4.0,>=1.13.0->lightning<3.0.0,>=2.0.1->lang-sam==0.1.0) Downloading nvidia_cublas_cu12-12.1.3.1-py3-none-manylinux1_x86_64.whl (410.6 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 410.6/410.6 MB 1.3 MB/s eta 0:00:00 Collecting nvidia-cufft-cu12==11.0.2.54 (from torch<4.0,>=1.13.0->lightning<3.0.0,>=2.0.1->lang-sam==0.1.0) Downloading nvidia_cufft_cu12-11.0.2.54-py3-none-manylinux1_x86_64.whl (121.6 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 121.6/121.6 MB 8.3 MB/s eta 0:00:00 Collecting nvidia-curand-cu12==10.3.2.106 (from torch<4.0,>=1.13.0->lightning<3.0.0,>=2.0.1->lang-sam==0.1.0) Downloading nvidia_curand_cu12-10.3.2.106-py3-none-manylinux1_x86_64.whl (56.5 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 56.5/56.5 MB 9.0 MB/s eta 0:00:00 Collecting nvidia-cusolver-cu12==11.4.5.107 (from torch<4.0,>=1.13.0->lightning<3.0.0,>=2.0.1->lang-sam==0.1.0) Downloading nvidia_cusolver_cu12-11.4.5.107-py3-none-manylinux1_x86_64.whl (124.2 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 124.2/124.2 MB 8.2 MB/s eta 0:00:00 Collecting nvidia-cusparse-cu12==12.1.0.106 (from torch<4.0,>=1.13.0->lightning<3.0.0,>=2.0.1->lang-sam==0.1.0) Downloading nvidia_cusparse_cu12-12.1.0.106-py3-none-manylinux1_x86_64.whl (196.0 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 196.0/196.0 MB 6.4 MB/s eta 0:00:00 Collecting nvidia-nccl-cu12==2.19.3 (from torch<4.0,>=1.13.0->lightning<3.0.0,>=2.0.1->lang-sam==0.1.0) Downloading nvidia_nccl_cu12-2.19.3-py3-none-manylinux1_x86_64.whl (166.0 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 166.0/166.0 MB 7.1 MB/s eta 0:00:00 Collecting nvidia-nvtx-cu12==12.1.105 (from torch<4.0,>=1.13.0->lightning<3.0.0,>=2.0.1->lang-sam==0.1.0) Downloading nvidia_nvtx_cu12-12.1.105-py3-none-manylinux1_x86_64.whl (99 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 99.1/99.1 kB 16.5 MB/s eta 0:00:00 Requirement already satisfied: triton==2.2.0 in /usr/local/lib/python3.10/dist-packages (from torch<4.0,>=1.13.0->lightning<3.0.0,>=2.0.1->lang-sam==0.1.0) (2.2.0) Collecting nvidia-nvjitlink-cu12 (from nvidia-cusolver-cu12==11.4.5.107->torch<4.0,>=1.13.0->lightning<3.0.0,>=2.0.1->lang-sam==0.1.0) Downloading nvidia_nvjitlink_cu12-12.4.99-py3-none-manylinux2014_x86_64.whl (21.1 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 21.1/21.1 MB 61.5 MB/s eta 0:00:00 Requirement already satisfied: click>=7.0 in /usr/local/lib/python3.10/dist-packages (from uvicorn>=0.14.0->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (8.1.7) Collecting h11>=0.8 (from uvicorn>=0.14.0->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) Downloading h11-0.14.0-py3-none-any.whl (58 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 58.3/58.3 kB 10.1 MB/s eta 0:00:00 Collecting starlette<0.37.0,>=0.36.3 (from fastapi->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) Downloading starlette-0.36.3-py3-none-any.whl (71 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 71.5/71.5 kB 11.2 MB/s eta 0:00:00 Requirement already satisfied: anyio in /usr/local/lib/python3.10/dist-packages (from httpx->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (3.7.1) Collecting httpcore==1.* (from httpx->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) Downloading httpcore-1.0.4-py3-none-any.whl (77 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 77.8/77.8 kB 12.4 MB/s eta 0:00:00 Requirement already satisfied: sniffio in /usr/local/lib/python3.10/dist-packages (from httpx->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (1.3.1) Requirement already satisfied: defusedxml<0.8.0,>=0.7.1 in /usr/local/lib/python3.10/dist-packages (from supervision->groundingdino@ git+https://github.com/IDEA-Research/GroundingDINO.git->lang-sam==0.1.0) (0.7.1) Requirement already satisfied: opencv-python-headless>=4.5.5.64 in /usr/local/lib/python3.10/dist-packages (from supervision->groundingdino@ git+https://github.com/IDEA-Research/GroundingDINO.git->lang-sam==0.1.0) (4.9.0.80) INFO: pip is looking at multiple versions of supervision to determine which version is compatible with other requirements. This could take a while. Collecting supervision (from groundingdino@ git+https://github.com/IDEA-Research/GroundingDINO.git->lang-sam==0.1.0) Downloading supervision-0.18.0-py3-none-any.whl (86 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 86.7/86.7 kB 5.0 MB/s eta 0:00:00 Requirement already satisfied: scipy<2.0.0,>=1.10.0 in /usr/local/lib/python3.10/dist-packages (from supervision->groundingdino@ git+https://github.com/IDEA-Research/GroundingDINO.git->lang-sam==0.1.0) (1.11.4) Requirement already satisfied: importlib-metadata>=6.6.0 in /usr/local/lib/python3.10/dist-packages (from yapf->groundingdino@ git+https://github.com/IDEA-Research/GroundingDINO.git->lang-sam==0.1.0) (7.0.2) Requirement already satisfied: platformdirs>=3.5.1 in /usr/local/lib/python3.10/dist-packages (from yapf->groundingdino@ git+https://github.com/IDEA-Research/GroundingDINO.git->lang-sam==0.1.0) (4.2.0) Requirement already satisfied: tomli>=2.0.1 in /usr/local/lib/python3.10/dist-packages (from yapf->groundingdino@ git+https://github.com/IDEA-Research/GroundingDINO.git->lang-sam==0.1.0) (2.0.1) Requirement already satisfied: aiosignal>=1.1.2 in /usr/local/lib/python3.10/dist-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec->gradio-client==0.6.1->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (1.3.1) Requirement already satisfied: attrs>=17.3.0 in /usr/local/lib/python3.10/dist-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec->gradio-client==0.6.1->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (23.2.0) Requirement already satisfied: frozenlist>=1.1.1 in /usr/local/lib/python3.10/dist-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec->gradio-client==0.6.1->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (1.4.1) Requirement already satisfied: multidict<7.0,>=4.5 in /usr/local/lib/python3.10/dist-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec->gradio-client==0.6.1->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (6.0.5) Requirement already satisfied: yarl<2.0,>=1.0 in /usr/local/lib/python3.10/dist-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec->gradio-client==0.6.1->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (1.9.4) Requirement already satisfied: async-timeout<5.0,>=4.0 in /usr/local/lib/python3.10/dist-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec->gradio-client==0.6.1->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (4.0.3) Requirement already satisfied: zipp>=0.5 in /usr/local/lib/python3.10/dist-packages (from importlib-metadata>=6.6.0->yapf->groundingdino@ git+https://github.com/IDEA-Research/GroundingDINO.git->lang-sam==0.1.0) (3.18.1) Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /usr/local/lib/python3.10/dist-packages (from jsonschema>=3.0->altair<6.0,>=4.2.0->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (2023.12.1) Requirement already satisfied: referencing>=0.28.4 in /usr/local/lib/python3.10/dist-packages (from jsonschema>=3.0->altair<6.0,>=4.2.0->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (0.33.0) Requirement already satisfied: rpds-py>=0.7.1 in /usr/local/lib/python3.10/dist-packages (from jsonschema>=3.0->altair<6.0,>=4.2.0->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (0.18.0) Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.10/dist-packages (from python-dateutil>=2.7->matplotlib~=3.0->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (1.16.0) Requirement already satisfied: exceptiongroup in /usr/local/lib/python3.10/dist-packages (from anyio->httpx->gradio<4.0.0,>=3.24.1->lang-sam==0.1.0) (1.2.0) Requirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.10/dist-packages (from sympy->torch<4.0,>=1.13.0->lightning<3.0.0,>=2.0.1->lang-sam==0.1.0) (1.3.0) Building wheels for collected packages: lang-sam, groundingdino, segment-anything, ffmpy Building wheel for lang-sam (pyproject.toml) ... done Created wheel for lang-sam: filename=lang_sam-0.1.0-py3-none-any.whl size=9855 sha256=0a65f63cbeff59ebc68491319d103eb32024413a1aec5015db0045a90315e452 Stored in directory: /tmp/pip-ephem-wheel-cache-btl4mu7o/wheels/c7/1d/cd/6f34f8ca4fbc01b7a1f522cf9c4654cbe4fcd4268069d6e739 Building wheel for groundingdino (setup.py) ... done Created wheel for groundingdino: filename=groundingdino-0.1.0-cp310-cp310-linux_x86_64.whl size=2852495 sha256=1286a243c85c716640f71f21ece0cdabae84202514dd2df14e3206c43a7c0d3c Stored in directory: /tmp/pip-ephem-wheel-cache-btl4mu7o/wheels/6b/06/d7/b57f601a4df56af41d262a5b1b496359b13c323bf5ef0434b2 Building wheel for segment-anything (setup.py) ... done Created wheel for segment-anything: filename=segment_anything-1.0-py3-none-any.whl size=36590 sha256=8468e1cfbe6fe77023721f284d69d4add42dc0024eb20607767fb7a6afa8d3e4 Stored in directory: /tmp/pip-ephem-wheel-cache-btl4mu7o/wheels/10/cf/59/9ccb2f0a1bcc81d4fbd0e501680b5d088d690c6cfbc02dc99d Building wheel for ffmpy (setup.py) ... done Created wheel for ffmpy: filename=ffmpy-0.3.2-py3-none-any.whl size=5584 sha256=a08b2c953f8fc6b1cecf285cc915f34f8bd031b82f59910cde2a7271dcce36c8 Stored in directory: /root/.cache/pip/wheels/bd/65/9a/671fc6dcde07d4418df0c592f8df512b26d7a0029c2a23dd81 Successfully built lang-sam groundingdino segment-anything ffmpy Installing collected packages: segment-anything, pydub, ffmpy, addict, websockets, semantic-version, python-multipart, Pillow, orjson, nvidia-nvtx-cu12, nvidia-nvjitlink-cu12, nvidia-nccl-cu12, nvidia-curand-cu12, nvidia-cufft-cu12, nvidia-cuda-runtime-cu12, nvidia-cuda-nvrtc-cu12, nvidia-cuda-cupti-cu12, nvidia-cublas-cu12, lightning-utilities, h11, aiofiles, yapf, uvicorn, starlette, nvidia-cusparse-cu12, nvidia-cudnn-cu12, huggingface-hub, httpcore, supervision, nvidia-cusolver-cu12, httpx, fastapi, transformers, gradio-client, torchmetrics, gradio, timm, pytorch-lightning, lightning, groundingdino, lang-sam Attempting uninstall: Pillow Found existing installation: Pillow 9.4.0 Uninstalling Pillow-9.4.0: Successfully uninstalled Pillow-9.4.0 Attempting uninstall: huggingface-hub Found existing installation: huggingface-hub 0.20.3 Uninstalling huggingface-hub-0.20.3: Successfully uninstalled huggingface-hub-0.20.3 Attempting uninstall: transformers Found existing installation: transformers 4.38.2 Uninstalling transformers-4.38.2: Successfully uninstalled transformers-4.38.2 Successfully installed Pillow-9.3.0 addict-2.4.0 aiofiles-23.2.1 fastapi-0.110.0 ffmpy-0.3.2 gradio-3.50.2 gradio-client-0.6.1 groundingdino-0.1.0 h11-0.14.0 httpcore-1.0.4 httpx-0.27.0 huggingface-hub-0.16.4 lang-sam-0.1.0 lightning-2.2.1 lightning-utilities-0.11.0 nvidia-cublas-cu12-12.1.3.1 nvidia-cuda-cupti-cu12-12.1.105 nvidia-cuda-nvrtc-cu12-12.1.105 nvidia-cuda-runtime-cu12-12.1.105 nvidia-cudnn-cu12-8.9.2.26 nvidia-cufft-cu12-11.0.2.54 nvidia-curand-cu12-10.3.2.106 nvidia-cusolver-cu12-11.4.5.107 nvidia-cusparse-cu12-12.1.0.106 nvidia-nccl-cu12-2.19.3 nvidia-nvjitlink-cu12-12.4.99 nvidia-nvtx-cu12-12.1.105 orjson-3.9.15 pydub-0.25.1 python-multipart-0.0.9 pytorch-lightning-2.2.1 segment-anything-1.0 semantic-version-2.10.0 starlette-0.36.3 supervision-0.18.0 timm-0.9.16 torchmetrics-1.3.2 transformers-4.35.2 uvicorn-0.29.0 websockets-11.0.3 yapf-0.40.2
from PIL import Image
from lang_sam import LangSAM
/usr/local/lib/python3.10/dist-packages/transformers/utils/generic.py:441: UserWarning: torch.utils._pytree._register_pytree_node is deprecated. Please use torch.utils._pytree.register_pytree_node instead. _torch_pytree._register_pytree_node( /usr/local/lib/python3.10/dist-packages/transformers/utils/generic.py:309: UserWarning: torch.utils._pytree._register_pytree_node is deprecated. Please use torch.utils._pytree.register_pytree_node instead. _torch_pytree._register_pytree_node(
img_path = train_path + 'dandelion/' + os.listdir(train_path + 'dandelion/')[1]
model = LangSAM()
image_pil = Image.open(img_path).convert("RGB")
# Define the text prompt
text_prompt = "flower"
masks, boxes, phrases, logits = model.predict(image_pil, text_prompt)
final text_encoder_type: bert-base-uncased Model loaded from /root/.cache/huggingface/hub/models--ShilongLiu--GroundingDINO/snapshots/a94c9b567a2a374598f05c584e96798a170c56fb/groundingdino_swinb_cogcoor.pth => _IncompatibleKeys(missing_keys=[], unexpected_keys=['label_enc.weight', 'bert.embeddings.position_ids'])
np.asarray(image_pil)
ndarray (228, 320, 3)
array([[[ 4, 24, 0], [ 5, 23, 0], [ 8, 23, 0], ..., [ 41, 71, 0], [ 44, 74, 0], [ 47, 78, 2]], [[ 4, 24, 0], [ 5, 23, 0], [ 8, 23, 0], ..., [ 44, 74, 0], [ 47, 78, 2], [ 49, 80, 2]], [[ 4, 24, 0], [ 5, 23, 0], [ 7, 22, 0], ..., [ 46, 77, 1], [ 48, 79, 1], [ 50, 81, 1]], ..., [[ 82, 108, 1], [ 69, 96, 0], [ 56, 86, 0], ..., [ 70, 93, 2], [ 74, 96, 0], [ 79, 101, 1]], [[ 83, 109, 2], [ 69, 96, 0], [ 54, 84, 0], ..., [ 65, 88, 0], [ 71, 92, 0], [ 80, 100, 3]], [[ 84, 110, 3], [ 68, 95, 0], [ 53, 83, 0], ..., [ 61, 83, 0], [ 69, 90, 0], [ 79, 98, 6]]], dtype=uint8)
np.asarray(image_pil)[int(boxes[0][1]):int(boxes[0][1])+int(boxes[0][3]), int(boxes[0][0]):int(boxes[0][0])+int(boxes[0][2])]
ndarray (201, 190, 3)
array([[[ 1, 20, 1], [ 1, 18, 0], [ 0, 17, 0], ..., [ 56, 86, 0], [ 59, 88, 0], [ 62, 91, 0]], [[ 0, 19, 0], [ 0, 19, 0], [ 0, 19, 0], ..., [ 58, 88, 0], [ 61, 90, 0], [ 64, 93, 0]], [[ 0, 19, 0], [ 0, 19, 0], [ 0, 19, 0], ..., [ 62, 93, 0], [ 66, 96, 0], [ 69, 99, 1]], ..., [[ 67, 97, 1], [ 60, 89, 0], [ 54, 82, 0], ..., [ 97, 114, 0], [ 98, 116, 0], [100, 118, 0]], [[ 67, 94, 0], [ 61, 87, 0], [ 53, 81, 0], ..., [ 93, 110, 0], [ 94, 111, 0], [ 97, 115, 0]], [[ 69, 96, 0], [ 57, 87, 1], [ 53, 81, 4], ..., [ 90, 105, 0], [ 91, 109, 1], [ 92, 110, 2]]], dtype=uint8)
img_path = train_path + 'dandelion/' + os.listdir(train_path + 'dandelion/')[2]
image_pil = Image.open(img_path).convert("RGB")
np.asarray(image_pil)
ndarray (241, 320, 3)
array([[[36, 45, 24], [35, 44, 23], [34, 44, 20], ..., [44, 54, 30], [44, 54, 30], [43, 53, 29]], [[35, 44, 23], [35, 44, 23], [34, 44, 20], ..., [44, 54, 30], [44, 54, 30], [43, 53, 29]], [[35, 43, 20], [35, 43, 20], [35, 43, 20], ..., [44, 54, 30], [43, 53, 29], [43, 53, 29]], ..., [[43, 60, 6], [48, 65, 10], [53, 71, 13], ..., [21, 29, 6], [21, 29, 6], [22, 30, 7]], [[46, 60, 7], [50, 64, 11], [53, 70, 15], ..., [20, 28, 7], [21, 29, 6], [21, 29, 6]], [[45, 59, 8], [49, 64, 9], [54, 70, 8], ..., [21, 29, 8], [20, 28, 7], [20, 28, 7]]], dtype=uint8)
masks, boxes, phrases, logits = model.predict(image_pil, text_prompt)
/usr/local/lib/python3.10/dist-packages/transformers/modeling_utils.py:907: FutureWarning: The `device` argument is deprecated and will be removed in v5 of Transformers. warnings.warn( /usr/local/lib/python3.10/dist-packages/torch/utils/checkpoint.py:460: UserWarning: torch.utils.checkpoint: please pass in use_reentrant=True or use_reentrant=False explicitly. The default value of use_reentrant will be updated to be False in the future. To maintain current behavior, pass use_reentrant=True. It is recommended that you use use_reentrant=False. Refer to docs for more details on the differences between the two variants. warnings.warn( /usr/local/lib/python3.10/dist-packages/torch/utils/checkpoint.py:90: UserWarning: None of the inputs have requires_grad=True. Gradients will be None warnings.warn(
np.asarray(image_pil)[int(boxes[0][1]):int(boxes[0][1])+int(boxes[0][3]), int(boxes[0][0]):int(boxes[0][0])+int(boxes[0][2])]
ndarray (206, 221, 3)
array([[[ 31, 41, 14], [ 31, 41, 14], [ 31, 41, 14], ..., [ 17, 26, 7], [ 17, 26, 7], [ 17, 26, 7]], [[ 31, 41, 14], [ 31, 41, 14], [ 31, 41, 14], ..., [ 16, 25, 6], [ 17, 26, 7], [ 17, 26, 7]], [[ 31, 41, 14], [ 31, 41, 14], [ 30, 40, 13], ..., [ 16, 25, 6], [ 16, 25, 6], [ 17, 26, 7]], ..., [[153, 145, 73], [142, 137, 69], [116, 115, 58], ..., [ 21, 29, 6], [ 21, 29, 6], [ 22, 30, 7]], [[150, 142, 70], [136, 131, 63], [109, 110, 50], ..., [ 20, 28, 7], [ 21, 29, 6], [ 21, 29, 6]], [[147, 141, 65], [131, 128, 57], [ 98, 102, 41], ..., [ 21, 29, 8], [ 20, 28, 7], [ 20, 28, 7]]], dtype=uint8)
Now, we apply the segmentation to all of our data
from tqdm import tqdm
import warnings
import os
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
import re
import random
warnings.filterwarnings("ignore")
classes = os.listdir(train_path)
classes
['dandelion', 'tulips', 'daisy', 'sunflowers', 'roses']
base_path = 'C:/Users/david/Desktop/DeepLearning/flower_photos/Train/'
save_path = 'C:/Users/david/Desktop/DeepLearning/flower_cropped/Train/'
for flower_class in classes:
img_list = os.listdir(base_path + flower_class)
already_saved = []
for el in os.listdir(save_path + flower_class):
# remove '.jpg'
el = ''.join(el.split('.')[:-1])
if el[-2:] == '_0':
already_saved.append(el[:-2] + '.jpg')
for img_path in tqdm(img_list):
if img_path in already_saved:
continue
image_pil = Image.open(base_path + flower_class + '/' + img_path).convert("RGB")
masks, boxes, phrases, logits = model.predict(image_pil, text_prompt)
for i in range(len(boxes)):
cropped_img = np.asarray(image_pil)[int(boxes[i][1]):int(boxes[i][1])+int(boxes[i][3]), int(boxes[i][0]):int(boxes[i][0])+int(boxes[i][2])]
final_img = Image.fromarray(cropped_img)
final_img.save(save_path + flower_class + '/' + ''.join(img_path.split('.')[:-1]) + '_' + str(i) + '.jpg')
100%|██████████| 701/701 [00:00<00:00, 1500.13it/s] 100%|██████████| 632/632 [05:19<00:00, 1.98it/s] 100%|██████████| 508/508 [00:00<00:00, 99710.16it/s] 100%|██████████| 561/561 [00:00<00:00, 77424.39it/s] 100%|██████████| 534/534 [00:18<00:00, 28.28it/s]
base_path = 'C:/Users/david/Desktop/DeepLearning/flower_photos/Test/'
save_path = 'C:/Users/david/Desktop/DeepLearning/flower_cropped/Test/'
for flower_class in classes:
img_list = os.listdir(base_path + flower_class)
already_saved = []
for el in os.listdir(save_path + flower_class):
# remove '.jpg'
el = ''.join(el.split('.')[:-1])
if el[-2:] == '_0':
already_saved.append(el[:-2] + '.jpg')
for img_path in tqdm(img_list):
if img_path in already_saved:
continue
image_pil = Image.open(base_path + flower_class + '/' + img_path).convert("RGB")
masks, boxes, phrases, logits = model.predict(image_pil, text_prompt)
for i in range(len(boxes)):
# There could be more than a flower in a image!
cropped_img = np.asarray(image_pil)[int(boxes[i][1]):int(boxes[i][1])+int(boxes[i][3]), int(boxes[i][0]):int(boxes[i][0])+int(boxes[i][2])]
final_img = Image.fromarray(cropped_img)
final_img.save(save_path + flower_class + '/' + ''.join(img_path.split('.')[:-1]) + '_' + str(i) + '.jpg')
100%|██████████| 197/197 [00:02<00:00, 93.82it/s] 100%|██████████| 167/167 [00:00<00:00, 119469.34it/s] 100%|██████████| 125/125 [00:00<00:00, 374224.13it/s] 100%|██████████| 138/138 [00:00<00:00, 289406.98it/s] 100%|██████████| 107/107 [00:01<00:00, 58.98it/s]
Let's check that there isn't anything strange with the pictures.
While segmenting the images, we noticed that some pciture have strange dimensions. Here is an example:
image_pil = Image.open(train_path + 'daisy/102841525_bd6628ae3c_16.jpg').convert("RGB")
# Display the image
plt.imshow(np.asarray(image_pil))
plt.axis('off') # Turn off axis
plt.show()
clas_diz['daisy']['102841525_bd6628ae3c_16.jpg']
(11, 165, 3)
To avoid that this type of images get into the training dataset, we are going to remove every image that has one dimension that is shorter than 15pixels (this is an arbitrary measure).
# Get the dimensions of all images in train set
clas_diz = {}
for clas in classes:
diz = {}
for img_path in tqdm(os.listdir(train_path + clas)):
image_pil = Image.open(train_path + clas + '/' + img_path).convert("RGB")
diz[img_path] = np.asarray(image_pil).shape
clas_diz[clas] = diz
100%|██████████| 2546/2546 [00:11<00:00, 220.33it/s] 100%|██████████| 1301/1301 [00:05<00:00, 225.42it/s] 100%|██████████| 1518/1518 [00:06<00:00, 219.03it/s] 100%|██████████| 2282/2282 [00:09<00:00, 232.48it/s] 100%|██████████| 3054/3054 [00:12<00:00, 235.73it/s]
test_path = base_path + 'Test/'
# Get the dimensions of all images in test set
clas_diz_test = {}
for clas in classes:
diz = {}
for img_path in tqdm(os.listdir(test_path + clas)):
image_pil = Image.open(test_path + clas + '/' + img_path).convert("RGB")
diz[img_path] = np.asarray(image_pil).shape
clas_diz_test[clas] = diz
100%|██████████| 699/699 [00:00<00:00, 2583.21it/s] 100%|██████████| 399/399 [00:00<00:00, 2328.88it/s] 100%|██████████| 263/263 [00:00<00:00, 2351.93it/s] 100%|██████████| 586/586 [00:00<00:00, 2340.42it/s] 100%|██████████| 688/688 [00:00<00:00, 2509.84it/s]
delete_diz = clas_diz.copy()
# Insert all of the training images with a dimension lower that 15px into the "delete_diz" dictionary
delete_diz = {}
for clas in classes:
delete_diz[clas] = []
for key, value in clas_diz[clas].items():
if value[0] <= 15 or value[1] <= 15:
delete_diz[clas].append(key)
# How many images are we going to delete from training set?
diz = {}
for clas in classes:
diz[clas] = len(delete_diz[clas])
diz
{'daisy': 69, 'dandelion': 26, 'roses': 14, 'sunflowers': 53, 'tulips': 68}
# Delete all the images in the "delete_diz" dictionary
for clas in classes:
for img_path in delete_diz[clas]:
os.remove(train_path + clas + '/' + img_path)
delete_diz = clas_diz_test.copy()
# Insert all of the test images with a dimension lower that 15px into the "delete_diz" dictionary
delete_diz = {}
for clas in classes:
delete_diz[clas] = []
for key, value in clas_diz_test[clas].items():
if value[0] <= 15 or value[1] <= 15:
delete_diz[clas].append(key)
# How many images are we going to delete from test set?
diz = {}
for clas in classes:
diz[clas] = len(delete_diz[clas])
diz
{'daisy': 17, 'dandelion': 7, 'roses': 2, 'sunflowers': 18, 'tulips': 17}
# Delete all the images in the "delete_diz" dictionary
for clas in classes:
for img_path in delete_diz[clas]:
os.remove(test_path + clas + '/' + img_path)
Since in each picture there can be more than one flower, the dimensinoality of the dataset have changed, let's check how much.
train_path = 'C:/Users/david/Desktop/DeepLearning/flower_cropped/Train/'
subD = os.listdir(train_path)
dizTrain = {}
# For each class subdirectory, insert in the dictionary dizTrain the number of element in that subdirectory
for dir in subD:
dizTrain[dir] = len(os.listdir(train_path + dir))
# Number of observations of each class in train set
dizTrain
{'daisy': 2477, 'dandelion': 1275, 'roses': 1504, 'sunflowers': 2229, 'tulips': 2986}
subD = os.listdir(test_path)
dizTest = {}
# For each class subdirectory, insert in the dictionary dizTrain the number of element in that subdirectory
for dir in subD:
dizTest[dir] = len(os.listdir(test_path + dir))
# Number of observations of each class in train set
dizTest
{'daisy': 682, 'dandelion': 392, 'roses': 261, 'sunflowers': 568, 'tulips': 671}
plt.bar(dizTrain.keys(), dizTrain.values(), color='b', alpha=0.5, label='Train')
plt.bar(dizTest.keys(), dizTest.values(), color='r', alpha=0.5, label='Test')
# Adding labels and title
plt.xlabel('N. of Observations')
plt.ylabel('Classes')
plt.title('N. of Observations per class')
plt.legend()
# Show plot
plt.show()
The segmentation increased the difference between the classes. We are firstly going to run the models with this data, then we are going to try balancing them.
For what regards the test set, we now have multiple cropped picture coming from the same original image. This could cause some problem in the evaluation of the model, since there would be some original image that appears more times then other in the test set (those with more flowers detected from the segmentation model).
To solve this issue we are going to build 3 different test sets, one with its own pro and cons:
test_path_balanced = base_path + 'TestBalanced/'
classes
['daisy', 'dandelion', 'roses', 'sunflowers', 'tulips']
# We are simply going to mantain only the first segmented image for each original picture
# That is, we are going to mantain all those images that end with "_0.jpg"
for clas in classes:
for img in os.listdir(test_path_balanced + clas):
if img[-6:] != '_0.jpg':
os.remove(test_path_balanced + clas + '/' + img)
# Check how many images for each class
subD = os.listdir(test_path_balanced)
dizTestB = {}
# For each class subdirectory, insert in the dictionary dizTrain the number of element in that subdirectory
for dir in subD:
dizTestB[dir] = len(os.listdir(test_path_balanced + dir))
dizTestB
{'daisy': 125, 'dandelion': 196, 'roses': 106, 'sunflowers': 138, 'tulips': 167}
# First test set (original)
base_path = 'C:/Users/david/Desktop/DeepLearning/flower_photos/'
test_ds = keras.preprocessing.image_dataset_from_directory(base_path +'Test',
image_size=(224,224),
batch_size=128,
label_mode='categorical',
shuffle=False,
seed=1)
# Second test set (segmented)
base_path = 'C:/Users/david/Desktop/DeepLearning/flower_cropped/'
test_ds_cropped = keras.preprocessing.image_dataset_from_directory(base_path +'Test',
image_size=(224,224),
batch_size=128,
label_mode='categorical',
shuffle=False,
seed=1)
# Third test set (segmented balanced)
test_ds_cropped_balanced = keras.preprocessing.image_dataset_from_directory(base_path +'TestBalanced',
image_size=(224,224),
batch_size=128,
label_mode='categorical',
shuffle=False,
seed=1)
Found 734 files belonging to 5 classes. Found 2574 files belonging to 5 classes. Found 732 files belonging to 5 classes.
Note: the 2 photo difference between original and segmented balanced is probably due to the fact that the segmentation model did not find any flower to segment in those two images, thus not producing any segmented image.
base_path = 'C:/Users/david/Desktop/DeepLearning/flower_cropped/'
train_ds = keras.preprocessing.image_dataset_from_directory(base_path + 'Train',
image_size=(224,224),
batch_size=32,
label_mode='categorical',
subset='training',
validation_split = 0.3,
shuffle=True,
seed=1)
val_ds = keras.preprocessing.image_dataset_from_directory(base_path + 'Train',
image_size=(224,224),
batch_size=32,
label_mode='categorical',
subset='validation',
validation_split = 0.3,
shuffle=True,
seed=1)
test_ds_cropped = keras.preprocessing.image_dataset_from_directory(base_path +'Test',
image_size=(224,224),
batch_size=128,
label_mode='categorical',
shuffle=False,
seed=1)
# Data loader with (slightly) larger images
train_ds_256 = keras.preprocessing.image_dataset_from_directory( base_path + 'Train',
image_size=(256,256),
batch_size=32,
label_mode='categorical',
subset='training',
validation_split = 0.3,
shuffle=True,
seed=1)
num_classes = 5
Found 10471 files belonging to 5 classes. Using 7330 files for training. Found 10471 files belonging to 5 classes. Using 3141 files for validation. Found 800 files belonging to 5 classes. Found 10471 files belonging to 5 classes. Using 7330 files for training.
train_ds_256.file_paths == train_ds.file_paths
True
We are firstly going to evaluate the performances of the first model of the two that achieved the best performances with the non-segmented images:
# Architecture definition of first model.
inputs = keras.Input((None,None,3))
x = inputs
x = keras.layers.RandomCrop(224, 224)(x)
x = keras.layers.RandomFlip(mode='horizontal')(x)
x = keras.layers.RandomContrast(0.25)(x)
x = keras.layers.Conv2D(32, 3, padding="same", kernel_regularizer=tf.keras.regularizers.l2(0.001))(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Conv2D(64, 3, padding="same", kernel_regularizer=tf.keras.regularizers.l2(0.001))(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Conv2D(128, 3, padding="same", kernel_regularizer=tf.keras.regularizers.l2(0.001))(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.GlobalMaxPooling2D()(x)
outputs = keras.layers.Dense(num_classes, activation="softmax", kernel_regularizer=tf.keras.regularizers.l2(0.001))(x)
net = keras.Model(inputs, outputs)
callback = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)
# Compile the model for training
net.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.RMSprop(learning_rate=0.0001),
metrics=['accuracy'])
# Model training (v4)
history = net.fit(train_ds_256,
epochs=80,
validation_data=val_ds,
callbacks = [callback])
Epoch 1/80 230/230 [==============================] - 25s 106ms/step - loss: 1.1631 - accuracy: 0.5985 - val_loss: 1.0932 - val_accuracy: 0.6339 Epoch 2/80 230/230 [==============================] - 24s 106ms/step - loss: 0.9748 - accuracy: 0.6779 - val_loss: 0.9130 - val_accuracy: 0.7007 Epoch 3/80 230/230 [==============================] - 24s 105ms/step - loss: 0.9172 - accuracy: 0.7064 - val_loss: 0.8685 - val_accuracy: 0.7176 Epoch 4/80 230/230 [==============================] - 24s 102ms/step - loss: 0.8637 - accuracy: 0.7252 - val_loss: 0.8345 - val_accuracy: 0.7278 Epoch 5/80 230/230 [==============================] - 23s 102ms/step - loss: 0.8293 - accuracy: 0.7412 - val_loss: 0.8290 - val_accuracy: 0.7297 Epoch 6/80 230/230 [==============================] - 24s 102ms/step - loss: 0.8073 - accuracy: 0.7486 - val_loss: 0.8244 - val_accuracy: 0.7396 Epoch 7/80 230/230 [==============================] - 24s 102ms/step - loss: 0.7812 - accuracy: 0.7607 - val_loss: 0.7926 - val_accuracy: 0.7482 Epoch 8/80 230/230 [==============================] - 24s 104ms/step - loss: 0.7557 - accuracy: 0.7640 - val_loss: 0.7653 - val_accuracy: 0.7705 Epoch 9/80 230/230 [==============================] - 28s 123ms/step - loss: 0.7419 - accuracy: 0.7720 - val_loss: 0.7541 - val_accuracy: 0.7593 Epoch 10/80 230/230 [==============================] - 31s 133ms/step - loss: 0.7297 - accuracy: 0.7782 - val_loss: 0.7339 - val_accuracy: 0.7752 Epoch 11/80 230/230 [==============================] - 34s 149ms/step - loss: 0.7135 - accuracy: 0.7847 - val_loss: 0.7539 - val_accuracy: 0.7539 Epoch 12/80 230/230 [==============================] - 38s 163ms/step - loss: 0.7104 - accuracy: 0.7844 - val_loss: 0.7312 - val_accuracy: 0.7752 Epoch 13/80 230/230 [==============================] - 41s 177ms/step - loss: 0.6818 - accuracy: 0.7967 - val_loss: 0.7220 - val_accuracy: 0.7784 Epoch 14/80 230/230 [==============================] - 41s 177ms/step - loss: 0.6823 - accuracy: 0.7973 - val_loss: 0.7351 - val_accuracy: 0.7685 Epoch 15/80 230/230 [==============================] - 43s 185ms/step - loss: 0.6724 - accuracy: 0.8080 - val_loss: 0.6969 - val_accuracy: 0.7985 Epoch 16/80 230/230 [==============================] - 44s 192ms/step - loss: 0.6659 - accuracy: 0.8029 - val_loss: 0.6942 - val_accuracy: 0.7905 Epoch 17/80 230/230 [==============================] - 46s 199ms/step - loss: 0.6416 - accuracy: 0.8135 - val_loss: 0.6795 - val_accuracy: 0.8013 Epoch 18/80 230/230 [==============================] - 48s 207ms/step - loss: 0.6406 - accuracy: 0.8104 - val_loss: 0.6849 - val_accuracy: 0.7918 Epoch 19/80 230/230 [==============================] - 48s 210ms/step - loss: 0.6350 - accuracy: 0.8192 - val_loss: 0.6805 - val_accuracy: 0.7931 Epoch 20/80 230/230 [==============================] - 49s 214ms/step - loss: 0.6273 - accuracy: 0.8183 - val_loss: 0.7068 - val_accuracy: 0.7937 Epoch 21/80 230/230 [==============================] - 50s 216ms/step - loss: 0.6212 - accuracy: 0.8232 - val_loss: 0.7084 - val_accuracy: 0.7784 Epoch 22/80 230/230 [==============================] - 51s 223ms/step - loss: 0.6167 - accuracy: 0.8186 - val_loss: 0.6969 - val_accuracy: 0.7822 Epoch 23/80 230/230 [==============================] - 53s 231ms/step - loss: 0.6101 - accuracy: 0.8247 - val_loss: 0.6690 - val_accuracy: 0.8042 Epoch 24/80 230/230 [==============================] - 54s 235ms/step - loss: 0.5970 - accuracy: 0.8303 - val_loss: 0.7248 - val_accuracy: 0.7720 Epoch 25/80 230/230 [==============================] - 55s 240ms/step - loss: 0.5948 - accuracy: 0.8274 - val_loss: 0.6384 - val_accuracy: 0.8192 Epoch 26/80 230/230 [==============================] - 56s 242ms/step - loss: 0.5900 - accuracy: 0.8292 - val_loss: 0.6724 - val_accuracy: 0.7943 Epoch 27/80 230/230 [==============================] - 56s 241ms/step - loss: 0.5828 - accuracy: 0.8334 - val_loss: 0.6306 - val_accuracy: 0.8201 Epoch 28/80 230/230 [==============================] - 54s 234ms/step - loss: 0.5790 - accuracy: 0.8344 - val_loss: 0.6290 - val_accuracy: 0.8147 Epoch 29/80 230/230 [==============================] - 54s 233ms/step - loss: 0.5747 - accuracy: 0.8408 - val_loss: 0.6589 - val_accuracy: 0.8010 Epoch 30/80 230/230 [==============================] - 54s 233ms/step - loss: 0.5661 - accuracy: 0.8431 - val_loss: 0.6278 - val_accuracy: 0.8118 Epoch 31/80 230/230 [==============================] - 54s 232ms/step - loss: 0.5591 - accuracy: 0.8437 - val_loss: 0.6197 - val_accuracy: 0.8208 Epoch 32/80 230/230 [==============================] - 53s 231ms/step - loss: 0.5521 - accuracy: 0.8512 - val_loss: 0.6221 - val_accuracy: 0.8182 Epoch 33/80 230/230 [==============================] - 52s 228ms/step - loss: 0.5552 - accuracy: 0.8495 - val_loss: 0.6406 - val_accuracy: 0.8036 Epoch 34/80 230/230 [==============================] - 52s 228ms/step - loss: 0.5483 - accuracy: 0.8491 - val_loss: 0.6090 - val_accuracy: 0.8208 Epoch 35/80 230/230 [==============================] - 52s 227ms/step - loss: 0.5419 - accuracy: 0.8447 - val_loss: 0.6025 - val_accuracy: 0.8239 Epoch 36/80 230/230 [==============================] - 52s 227ms/step - loss: 0.5392 - accuracy: 0.8506 - val_loss: 0.5911 - val_accuracy: 0.8325 Epoch 37/80 230/230 [==============================] - 52s 227ms/step - loss: 0.5330 - accuracy: 0.8562 - val_loss: 0.6345 - val_accuracy: 0.8179 Epoch 38/80 230/230 [==============================] - 52s 227ms/step - loss: 0.5281 - accuracy: 0.8569 - val_loss: 0.6234 - val_accuracy: 0.8080 Epoch 39/80 230/230 [==============================] - 52s 227ms/step - loss: 0.5174 - accuracy: 0.8587 - val_loss: 0.5965 - val_accuracy: 0.8290 Epoch 40/80 230/230 [==============================] - 52s 227ms/step - loss: 0.5208 - accuracy: 0.8621 - val_loss: 0.5910 - val_accuracy: 0.8262 Epoch 41/80 230/230 [==============================] - 52s 228ms/step - loss: 0.5139 - accuracy: 0.8610 - val_loss: 0.6059 - val_accuracy: 0.8182 Epoch 42/80 230/230 [==============================] - 52s 227ms/step - loss: 0.5116 - accuracy: 0.8658 - val_loss: 0.6542 - val_accuracy: 0.7959 Epoch 43/80 230/230 [==============================] - 52s 228ms/step - loss: 0.5117 - accuracy: 0.8628 - val_loss: 0.6079 - val_accuracy: 0.8236 Epoch 44/80 230/230 [==============================] - 53s 232ms/step - loss: 0.4973 - accuracy: 0.8651 - val_loss: 0.5914 - val_accuracy: 0.8287 Epoch 45/80 230/230 [==============================] - 56s 245ms/step - loss: 0.4982 - accuracy: 0.8685 - val_loss: 0.6124 - val_accuracy: 0.8233 Epoch 46/80 230/230 [==============================] - 56s 243ms/step - loss: 0.4962 - accuracy: 0.8674 - val_loss: 0.5708 - val_accuracy: 0.8376 Epoch 47/80 230/230 [==============================] - 53s 230ms/step - loss: 0.4900 - accuracy: 0.8715 - val_loss: 0.6228 - val_accuracy: 0.8093 Epoch 48/80 230/230 [==============================] - 53s 230ms/step - loss: 0.4934 - accuracy: 0.8716 - val_loss: 0.6341 - val_accuracy: 0.7972 Epoch 49/80 230/230 [==============================] - 53s 229ms/step - loss: 0.4859 - accuracy: 0.8688 - val_loss: 0.5926 - val_accuracy: 0.8246 Epoch 50/80 230/230 [==============================] - 53s 229ms/step - loss: 0.4862 - accuracy: 0.8683 - val_loss: 0.5629 - val_accuracy: 0.8395 Epoch 51/80 230/230 [==============================] - 53s 229ms/step - loss: 0.4804 - accuracy: 0.8693 - val_loss: 0.5846 - val_accuracy: 0.8211 Epoch 52/80 230/230 [==============================] - 53s 231ms/step - loss: 0.4735 - accuracy: 0.8774 - val_loss: 0.5777 - val_accuracy: 0.8325 Epoch 53/80 230/230 [==============================] - 53s 231ms/step - loss: 0.4720 - accuracy: 0.8744 - val_loss: 0.6090 - val_accuracy: 0.8230 Epoch 54/80 230/230 [==============================] - 53s 231ms/step - loss: 0.4688 - accuracy: 0.8827 - val_loss: 0.6113 - val_accuracy: 0.8166 Epoch 55/80 230/230 [==============================] - 53s 229ms/step - loss: 0.4638 - accuracy: 0.8799 - val_loss: 0.5730 - val_accuracy: 0.8399 Epoch 56/80 230/230 [==============================] - 53s 230ms/step - loss: 0.4571 - accuracy: 0.8850 - val_loss: 0.5575 - val_accuracy: 0.8399 Epoch 57/80 230/230 [==============================] - 53s 229ms/step - loss: 0.4554 - accuracy: 0.8823 - val_loss: 0.5588 - val_accuracy: 0.8360 Epoch 58/80 230/230 [==============================] - 53s 229ms/step - loss: 0.4548 - accuracy: 0.8835 - val_loss: 0.5928 - val_accuracy: 0.8233 Epoch 59/80 230/230 [==============================] - 53s 229ms/step - loss: 0.4486 - accuracy: 0.8843 - val_loss: 0.5451 - val_accuracy: 0.8469 Epoch 60/80 230/230 [==============================] - 53s 230ms/step - loss: 0.4565 - accuracy: 0.8842 - val_loss: 0.5837 - val_accuracy: 0.8399 Epoch 61/80 230/230 [==============================] - 53s 230ms/step - loss: 0.4557 - accuracy: 0.8760 - val_loss: 0.5691 - val_accuracy: 0.8313 Epoch 62/80 230/230 [==============================] - 53s 231ms/step - loss: 0.4421 - accuracy: 0.8903 - val_loss: 0.5564 - val_accuracy: 0.8408 Epoch 63/80 230/230 [==============================] - 53s 232ms/step - loss: 0.4423 - accuracy: 0.8857 - val_loss: 0.5421 - val_accuracy: 0.8456 Epoch 64/80 230/230 [==============================] - 53s 232ms/step - loss: 0.4374 - accuracy: 0.8864 - val_loss: 0.5935 - val_accuracy: 0.8198 Epoch 65/80 230/230 [==============================] - 53s 230ms/step - loss: 0.4400 - accuracy: 0.8887 - val_loss: 0.5959 - val_accuracy: 0.8246 Epoch 66/80 230/230 [==============================] - 53s 230ms/step - loss: 0.4430 - accuracy: 0.8877 - val_loss: 0.5677 - val_accuracy: 0.8303 Epoch 67/80 230/230 [==============================] - 53s 229ms/step - loss: 0.4288 - accuracy: 0.8936 - val_loss: 0.5464 - val_accuracy: 0.8367 Epoch 68/80 230/230 [==============================] - 54s 235ms/step - loss: 0.4208 - accuracy: 0.8985 - val_loss: 0.5321 - val_accuracy: 0.8415 Epoch 69/80 230/230 [==============================] - 54s 232ms/step - loss: 0.4255 - accuracy: 0.8922 - val_loss: 0.5450 - val_accuracy: 0.8459 Epoch 70/80 230/230 [==============================] - 53s 229ms/step - loss: 0.4206 - accuracy: 0.8930 - val_loss: 0.5328 - val_accuracy: 0.8465 Epoch 71/80 230/230 [==============================] - 53s 229ms/step - loss: 0.4281 - accuracy: 0.8880 - val_loss: 0.5358 - val_accuracy: 0.8408 Epoch 72/80 230/230 [==============================] - 53s 230ms/step - loss: 0.4193 - accuracy: 0.8958 - val_loss: 0.6141 - val_accuracy: 0.8144 Epoch 73/80 230/230 [==============================] - 53s 229ms/step - loss: 0.4175 - accuracy: 0.8940 - val_loss: 0.5481 - val_accuracy: 0.8405 Epoch 74/80 230/230 [==============================] - 53s 229ms/step - loss: 0.4099 - accuracy: 0.8984 - val_loss: 0.5456 - val_accuracy: 0.8376 Epoch 75/80 230/230 [==============================] - 53s 229ms/step - loss: 0.4117 - accuracy: 0.8981 - val_loss: 0.5445 - val_accuracy: 0.8408 Epoch 76/80 230/230 [==============================] - 53s 230ms/step - loss: 0.4063 - accuracy: 0.9004 - val_loss: 0.5835 - val_accuracy: 0.8319 Epoch 77/80 230/230 [==============================] - 53s 230ms/step - loss: 0.4071 - accuracy: 0.8990 - val_loss: 0.5553 - val_accuracy: 0.8408 Epoch 78/80 230/230 [==============================] - 53s 229ms/step - loss: 0.3980 - accuracy: 0.9048 - val_loss: 0.5361 - val_accuracy: 0.8459
# Visualization of the learning curves
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.ylim([0.0, 2.0])
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend(['train', 'valid'])
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.ylim([0.5, 1.0])
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(['train', 'valid'])
<matplotlib.legend.Legend at 0x1c689c5aac0>
net.save('models/Segmented1RMS.keras')
# Evaluate on the 3 test dataset:
net = keras.models.load_model("models/Segmented1RMS.keras")
net.evaluate(test_ds)
net.evaluate(test_ds_cropped)
net.evaluate(test_ds_cropped_balanced)
6/6 [==============================] - 5s 475ms/step - loss: 0.7436 - accuracy: 0.7956 21/21 [==============================] - 4s 179ms/step - loss: 0.6731 - accuracy: 0.8085 6/6 [==============================] - 2s 446ms/step - loss: 0.6117 - accuracy: 0.8333
[0.6117007732391357, 0.8333333134651184]
None of the three accuracy resulted to be higher than the test accuracy we achieved with the model with unsegmented data (83.65%).
The second model between the two best built with the unsegmented data:
# Architecture definition
inputs = keras.Input((None,None,3))
x = inputs
x = keras.layers.RandomCrop(224, 224)(x)
x = keras.layers.RandomFlip(mode='horizontal')(x)
x = keras.layers.RandomContrast(0.25)(x)
x = keras.layers.Conv2D(64, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.Conv2D(128, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.Conv2D(256, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.GlobalMaxPooling2D()(x)
outputs = keras.layers.Dense(1024, activation="softmax")(x)
x = keras.layers.Dropout(0.2)(x)
outputs = keras.layers.Dense(512, activation="softmax")(x)
outputs = keras.layers.Dense(num_classes, activation="softmax")(x)
net = keras.Model(inputs, outputs)
callback = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)
lr_schedule = keras.optimizers.schedules.InverseTimeDecay(
initial_learning_rate = 0.0005,
decay_steps = 65,
decay_rate = 0.08)
optimizer = keras.optimizers.Adam(learning_rate=lr_schedule)
net.compile(loss=keras.losses.categorical_crossentropy,
optimizer=optimizer,
metrics=['accuracy'])
# Model training
history = net.fit(train_ds_256,
epochs=80,
validation_data=val_ds,
callbacks=[callback])
Epoch 1/80 230/230 [==============================] - 56s 216ms/step - loss: 1.6041 - accuracy: 0.5068 - val_loss: 1.0993 - val_accuracy: 0.6100 Epoch 2/80 230/230 [==============================] - 68s 296ms/step - loss: 1.1423 - accuracy: 0.5954 - val_loss: 0.9347 - val_accuracy: 0.6348 Epoch 3/80 230/230 [==============================] - 111s 481ms/step - loss: 1.0418 - accuracy: 0.6224 - val_loss: 0.7013 - val_accuracy: 0.7294 Epoch 4/80 230/230 [==============================] - 118s 513ms/step - loss: 0.9432 - accuracy: 0.6508 - val_loss: 0.6684 - val_accuracy: 0.7421 Epoch 5/80 230/230 [==============================] - 118s 515ms/step - loss: 0.9024 - accuracy: 0.6660 - val_loss: 0.6577 - val_accuracy: 0.7510 Epoch 6/80 230/230 [==============================] - 119s 516ms/step - loss: 0.8664 - accuracy: 0.6726 - val_loss: 0.6362 - val_accuracy: 0.7622 Epoch 7/80 230/230 [==============================] - 118s 514ms/step - loss: 0.8267 - accuracy: 0.6913 - val_loss: 0.6272 - val_accuracy: 0.7574 Epoch 8/80 230/230 [==============================] - 113s 491ms/step - loss: 0.8182 - accuracy: 0.6963 - val_loss: 0.6504 - val_accuracy: 0.7463 Epoch 9/80 230/230 [==============================] - 110s 477ms/step - loss: 0.8076 - accuracy: 0.6956 - val_loss: 0.6295 - val_accuracy: 0.7625 Epoch 10/80 230/230 [==============================] - 109s 473ms/step - loss: 0.7818 - accuracy: 0.7074 - val_loss: 0.5929 - val_accuracy: 0.7810 Epoch 11/80 230/230 [==============================] - 107s 467ms/step - loss: 0.7640 - accuracy: 0.7117 - val_loss: 0.6208 - val_accuracy: 0.7638 Epoch 12/80 230/230 [==============================] - 108s 471ms/step - loss: 0.7643 - accuracy: 0.7132 - val_loss: 0.5929 - val_accuracy: 0.7765 Epoch 13/80 230/230 [==============================] - 106s 462ms/step - loss: 0.7347 - accuracy: 0.7233 - val_loss: 0.5983 - val_accuracy: 0.7803 Epoch 14/80 230/230 [==============================] - 105s 456ms/step - loss: 0.7364 - accuracy: 0.7239 - val_loss: 0.5549 - val_accuracy: 0.7956 Epoch 15/80 230/230 [==============================] - 105s 457ms/step - loss: 0.7230 - accuracy: 0.7302 - val_loss: 0.5607 - val_accuracy: 0.7950 Epoch 16/80 230/230 [==============================] - 107s 467ms/step - loss: 0.6955 - accuracy: 0.7352 - val_loss: 0.5567 - val_accuracy: 0.7991 Epoch 17/80 230/230 [==============================] - 106s 460ms/step - loss: 0.7070 - accuracy: 0.7351 - val_loss: 0.5535 - val_accuracy: 0.7959 Epoch 18/80 230/230 [==============================] - 105s 456ms/step - loss: 0.7050 - accuracy: 0.7300 - val_loss: 0.5349 - val_accuracy: 0.8039 Epoch 19/80 230/230 [==============================] - 103s 448ms/step - loss: 0.6865 - accuracy: 0.7431 - val_loss: 0.5383 - val_accuracy: 0.8090 Epoch 20/80 230/230 [==============================] - 104s 451ms/step - loss: 0.6795 - accuracy: 0.7400 - val_loss: 0.5268 - val_accuracy: 0.8109 Epoch 21/80 230/230 [==============================] - 107s 467ms/step - loss: 0.6812 - accuracy: 0.7367 - val_loss: 0.5604 - val_accuracy: 0.7934 Epoch 22/80 230/230 [==============================] - 105s 458ms/step - loss: 0.6568 - accuracy: 0.7543 - val_loss: 0.5588 - val_accuracy: 0.7947 Epoch 23/80 230/230 [==============================] - 108s 468ms/step - loss: 0.6432 - accuracy: 0.7529 - val_loss: 0.5541 - val_accuracy: 0.7857 Epoch 24/80 230/230 [==============================] - 107s 465ms/step - loss: 0.6574 - accuracy: 0.7553 - val_loss: 0.5142 - val_accuracy: 0.8150 Epoch 25/80 230/230 [==============================] - 118s 513ms/step - loss: 0.6631 - accuracy: 0.7479 - val_loss: 0.5148 - val_accuracy: 0.8153 Epoch 26/80 230/230 [==============================] - 118s 514ms/step - loss: 0.6404 - accuracy: 0.7536 - val_loss: 0.5091 - val_accuracy: 0.8169 Epoch 27/80 230/230 [==============================] - 118s 514ms/step - loss: 0.6502 - accuracy: 0.7538 - val_loss: 0.5572 - val_accuracy: 0.7911 Epoch 28/80 230/230 [==============================] - 118s 515ms/step - loss: 0.6407 - accuracy: 0.7587 - val_loss: 0.5154 - val_accuracy: 0.8153 Epoch 29/80 230/230 [==============================] - 119s 515ms/step - loss: 0.6318 - accuracy: 0.7539 - val_loss: 0.5168 - val_accuracy: 0.8109 Epoch 30/80 230/230 [==============================] - 119s 515ms/step - loss: 0.6258 - accuracy: 0.7600 - val_loss: 0.5265 - val_accuracy: 0.8083 Epoch 31/80 230/230 [==============================] - 119s 515ms/step - loss: 0.6236 - accuracy: 0.7683 - val_loss: 0.5033 - val_accuracy: 0.8153 Epoch 32/80 230/230 [==============================] - 119s 516ms/step - loss: 0.6162 - accuracy: 0.7663 - val_loss: 0.5001 - val_accuracy: 0.8201 Epoch 33/80 230/230 [==============================] - 119s 516ms/step - loss: 0.6100 - accuracy: 0.7681 - val_loss: 0.5017 - val_accuracy: 0.8192 Epoch 34/80 230/230 [==============================] - 119s 516ms/step - loss: 0.6108 - accuracy: 0.7644 - val_loss: 0.4933 - val_accuracy: 0.8220 Epoch 35/80 230/230 [==============================] - 119s 516ms/step - loss: 0.6154 - accuracy: 0.7681 - val_loss: 0.4927 - val_accuracy: 0.8268 Epoch 36/80 230/230 [==============================] - 119s 516ms/step - loss: 0.6190 - accuracy: 0.7666 - val_loss: 0.4992 - val_accuracy: 0.8255 Epoch 37/80 230/230 [==============================] - 119s 516ms/step - loss: 0.5945 - accuracy: 0.7759 - val_loss: 0.4868 - val_accuracy: 0.8246 Epoch 38/80 230/230 [==============================] - 119s 517ms/step - loss: 0.6008 - accuracy: 0.7722 - val_loss: 0.4893 - val_accuracy: 0.8262 Epoch 39/80 230/230 [==============================] - 120s 519ms/step - loss: 0.6066 - accuracy: 0.7694 - val_loss: 0.4934 - val_accuracy: 0.8255 Epoch 40/80 230/230 [==============================] - 119s 516ms/step - loss: 0.6041 - accuracy: 0.7739 - val_loss: 0.4841 - val_accuracy: 0.8281 Epoch 41/80 230/230 [==============================] - 119s 516ms/step - loss: 0.5981 - accuracy: 0.7677 - val_loss: 0.4804 - val_accuracy: 0.8309 Epoch 42/80 230/230 [==============================] - 119s 516ms/step - loss: 0.6073 - accuracy: 0.7696 - val_loss: 0.4815 - val_accuracy: 0.8281 Epoch 43/80 230/230 [==============================] - 119s 516ms/step - loss: 0.5979 - accuracy: 0.7731 - val_loss: 0.4856 - val_accuracy: 0.8297 Epoch 44/80 230/230 [==============================] - 119s 517ms/step - loss: 0.5800 - accuracy: 0.7802 - val_loss: 0.4882 - val_accuracy: 0.8262 Epoch 45/80 230/230 [==============================] - 119s 516ms/step - loss: 0.5925 - accuracy: 0.7756 - val_loss: 0.4739 - val_accuracy: 0.8313 Epoch 46/80 230/230 [==============================] - 119s 515ms/step - loss: 0.5855 - accuracy: 0.7761 - val_loss: 0.4711 - val_accuracy: 0.8303 Epoch 47/80 230/230 [==============================] - 119s 516ms/step - loss: 0.5814 - accuracy: 0.7790 - val_loss: 0.4785 - val_accuracy: 0.8306 Epoch 48/80 230/230 [==============================] - 119s 518ms/step - loss: 0.5863 - accuracy: 0.7779 - val_loss: 0.4771 - val_accuracy: 0.8287 Epoch 49/80 230/230 [==============================] - 119s 516ms/step - loss: 0.5689 - accuracy: 0.7898 - val_loss: 0.4743 - val_accuracy: 0.8281 Epoch 50/80 230/230 [==============================] - 118s 515ms/step - loss: 0.5885 - accuracy: 0.7759 - val_loss: 0.4901 - val_accuracy: 0.8271 Epoch 51/80 230/230 [==============================] - 118s 514ms/step - loss: 0.5836 - accuracy: 0.7737 - val_loss: 0.4759 - val_accuracy: 0.8303 Epoch 52/80 230/230 [==============================] - 118s 515ms/step - loss: 0.5725 - accuracy: 0.7861 - val_loss: 0.4689 - val_accuracy: 0.8316 Epoch 53/80 230/230 [==============================] - 118s 515ms/step - loss: 0.5855 - accuracy: 0.7827 - val_loss: 0.4786 - val_accuracy: 0.8278 Epoch 54/80 230/230 [==============================] - 119s 519ms/step - loss: 0.5769 - accuracy: 0.7819 - val_loss: 0.4645 - val_accuracy: 0.8332 Epoch 55/80 230/230 [==============================] - 123s 533ms/step - loss: 0.5565 - accuracy: 0.7941 - val_loss: 0.4703 - val_accuracy: 0.8294 Epoch 56/80 230/230 [==============================] - 122s 529ms/step - loss: 0.5632 - accuracy: 0.7873 - val_loss: 0.4996 - val_accuracy: 0.8179 Epoch 57/80 230/230 [==============================] - 121s 527ms/step - loss: 0.5678 - accuracy: 0.7839 - val_loss: 0.4698 - val_accuracy: 0.8325 Epoch 58/80 230/230 [==============================] - 123s 536ms/step - loss: 0.5632 - accuracy: 0.7877 - val_loss: 0.4773 - val_accuracy: 0.8300 Epoch 59/80 230/230 [==============================] - 122s 530ms/step - loss: 0.5626 - accuracy: 0.7864 - val_loss: 0.4686 - val_accuracy: 0.8344 Epoch 60/80 230/230 [==============================] - 121s 524ms/step - loss: 0.5515 - accuracy: 0.7909 - val_loss: 0.4634 - val_accuracy: 0.8392 Epoch 61/80 230/230 [==============================] - 120s 523ms/step - loss: 0.5598 - accuracy: 0.7855 - val_loss: 0.4741 - val_accuracy: 0.8297 Epoch 62/80 230/230 [==============================] - 122s 528ms/step - loss: 0.5647 - accuracy: 0.7881 - val_loss: 0.4608 - val_accuracy: 0.8364 Epoch 63/80 230/230 [==============================] - 121s 523ms/step - loss: 0.5552 - accuracy: 0.7917 - val_loss: 0.4656 - val_accuracy: 0.8341 Epoch 64/80 230/230 [==============================] - 122s 531ms/step - loss: 0.5576 - accuracy: 0.7920 - val_loss: 0.4615 - val_accuracy: 0.8341 Epoch 65/80 230/230 [==============================] - 122s 531ms/step - loss: 0.5563 - accuracy: 0.7926 - val_loss: 0.4753 - val_accuracy: 0.8297 Epoch 66/80 230/230 [==============================] - 123s 535ms/step - loss: 0.5555 - accuracy: 0.7899 - val_loss: 0.4627 - val_accuracy: 0.8348 Epoch 67/80 230/230 [==============================] - 124s 540ms/step - loss: 0.5649 - accuracy: 0.7866 - val_loss: 0.4673 - val_accuracy: 0.8306 Epoch 68/80 230/230 [==============================] - 122s 531ms/step - loss: 0.5572 - accuracy: 0.7905 - val_loss: 0.4634 - val_accuracy: 0.8367 Epoch 69/80 230/230 [==============================] - 119s 517ms/step - loss: 0.5520 - accuracy: 0.7903 - val_loss: 0.4665 - val_accuracy: 0.8287 Epoch 70/80 230/230 [==============================] - 119s 517ms/step - loss: 0.5542 - accuracy: 0.7874 - val_loss: 0.4608 - val_accuracy: 0.8313 Epoch 71/80 230/230 [==============================] - 119s 516ms/step - loss: 0.5486 - accuracy: 0.7929 - val_loss: 0.4679 - val_accuracy: 0.8335 Epoch 72/80 230/230 [==============================] - 119s 519ms/step - loss: 0.5297 - accuracy: 0.8022 - val_loss: 0.4627 - val_accuracy: 0.8325 Epoch 73/80 230/230 [==============================] - 119s 517ms/step - loss: 0.5444 - accuracy: 0.7896 - val_loss: 0.4620 - val_accuracy: 0.8338 Epoch 74/80 230/230 [==============================] - 119s 516ms/step - loss: 0.5504 - accuracy: 0.7920 - val_loss: 0.4603 - val_accuracy: 0.8338 Epoch 75/80 230/230 [==============================] - 119s 516ms/step - loss: 0.5317 - accuracy: 0.8010 - val_loss: 0.4742 - val_accuracy: 0.8262 Epoch 76/80 230/230 [==============================] - 119s 516ms/step - loss: 0.5329 - accuracy: 0.7954 - val_loss: 0.4629 - val_accuracy: 0.8322 Epoch 77/80 230/230 [==============================] - 119s 516ms/step - loss: 0.5353 - accuracy: 0.7974 - val_loss: 0.4688 - val_accuracy: 0.8309 Epoch 78/80 230/230 [==============================] - 119s 516ms/step - loss: 0.5404 - accuracy: 0.7995 - val_loss: 0.4588 - val_accuracy: 0.8348 Epoch 79/80 230/230 [==============================] - 119s 516ms/step - loss: 0.5370 - accuracy: 0.8011 - val_loss: 0.4520 - val_accuracy: 0.8367 Epoch 80/80 230/230 [==============================] - 119s 516ms/step - loss: 0.5424 - accuracy: 0.7926 - val_loss: 0.4679 - val_accuracy: 0.8290
# Visualization of the learning curves
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.ylim([0.0, 2.0])
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend(['train', 'valid'])
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.ylim([0.5, 1.0])
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(['train', 'valid'])
<matplotlib.legend.Legend at 0x1c694485ee0>
net.save('models/Segmented2RMS.keras')
net.evaluate(test_ds)
6/6 [==============================] - 55s 8s/step - loss: 0.5306 - accuracy: 0.8120
[0.5306099057197571, 0.8119891285896301]
net.evaluate(test_ds_cropped)
21/21 [==============================] - 158s 8s/step - loss: 0.5544 - accuracy: 0.8108
[0.5543912053108215, 0.810800313949585]
net.evaluate(test_ds_cropped_balanced)
6/6 [==============================] - 43s 7s/step - loss: 0.4482 - accuracy: 0.8470
[0.44818899035453796, 0.8469945192337036]
None of the three accuracy resulted to be higher than the test accuracy we achieved with the model with unsegmented data (84.74%).
Since the dropout rates we set for the model with unsegmented data seems to be excessive now, we are going to retry this same architecture on the segmented data, but changing the DropOut rates. In particular, we are going to remove the Dropout Layer from the last 1024 Dense layer.
# Architecture definition
inputs = keras.Input((None,None,3))
x = inputs
x = keras.layers.RandomCrop(224, 224)(x)
x = keras.layers.RandomFlip(mode='horizontal')(x)
x = keras.layers.RandomContrast(0.25)(x)
x = keras.layers.Conv2D(64, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.Conv2D(128, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.Conv2D(256, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.GlobalMaxPooling2D()(x)
outputs = keras.layers.Dense(1024, activation="softmax")(x)
outputs = keras.layers.Dense(512, activation="softmax")(x)
outputs = keras.layers.Dense(num_classes, activation="softmax")(x)
net = keras.Model(inputs, outputs)
early_stopping = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)
checkpoint_filepath = "/Checkpoint"
checkpoint_callback = tf.keras.callbacks.ModelCheckpoint(
filepath=checkpoint_filepath,
monitor='val_accuracy',
mode='max')
lr_schedule = keras.optimizers.schedules.InverseTimeDecay(
initial_learning_rate = 0.0005,
decay_steps = 65,
decay_rate = 0.08)
optimizer = keras.optimizers.Adam(learning_rate=lr_schedule)
net.compile(loss=keras.losses.categorical_crossentropy,
optimizer=optimizer,
metrics=['accuracy'])
# Model training
history = net.fit(train_ds_256,
epochs=80,
validation_data=val_ds,
callbacks=[early_stopping, checkpoint_callback])
Epoch 1/80 230/230 [==============================] - 2443s 10s/step - loss: 1.0213 - accuracy: 0.6191 - val_loss: 0.8483 - val_accuracy: 0.6600 Epoch 2/80 230/230 [==============================] - 55s 234ms/step - loss: 0.7569 - accuracy: 0.7001 - val_loss: 0.7210 - val_accuracy: 0.7240 Epoch 3/80 230/230 [==============================] - 54s 233ms/step - loss: 0.6879 - accuracy: 0.7334 - val_loss: 0.7451 - val_accuracy: 0.7131 Epoch 4/80 230/230 [==============================] - 54s 231ms/step - loss: 0.6418 - accuracy: 0.7536 - val_loss: 0.6038 - val_accuracy: 0.7787 Epoch 5/80 230/230 [==============================] - 61s 262ms/step - loss: 0.6056 - accuracy: 0.7685 - val_loss: 0.5804 - val_accuracy: 0.7880 Epoch 6/80 230/230 [==============================] - 54s 232ms/step - loss: 0.5775 - accuracy: 0.7808 - val_loss: 0.5654 - val_accuracy: 0.7921 Epoch 7/80 230/230 [==============================] - 54s 233ms/step - loss: 0.5518 - accuracy: 0.7936 - val_loss: 0.5746 - val_accuracy: 0.7838 Epoch 8/80 230/230 [==============================] - 54s 230ms/step - loss: 0.5334 - accuracy: 0.7992 - val_loss: 0.5435 - val_accuracy: 0.8010 Epoch 9/80 230/230 [==============================] - 56s 238ms/step - loss: 0.5182 - accuracy: 0.8094 - val_loss: 0.5254 - val_accuracy: 0.8077 Epoch 10/80 230/230 [==============================] - 55s 234ms/step - loss: 0.5018 - accuracy: 0.8131 - val_loss: 0.5462 - val_accuracy: 0.7975 Epoch 11/80 230/230 [==============================] - 64s 277ms/step - loss: 0.4989 - accuracy: 0.8117 - val_loss: 0.5082 - val_accuracy: 0.8147 Epoch 12/80 230/230 [==============================] - 55s 232ms/step - loss: 0.4804 - accuracy: 0.8199 - val_loss: 0.5100 - val_accuracy: 0.8115 Epoch 13/80 230/230 [==============================] - 56s 237ms/step - loss: 0.4629 - accuracy: 0.8306 - val_loss: 0.4820 - val_accuracy: 0.8309 Epoch 14/80 230/230 [==============================] - 54s 230ms/step - loss: 0.4645 - accuracy: 0.8295 - val_loss: 0.5031 - val_accuracy: 0.8214 Epoch 15/80 230/230 [==============================] - 54s 232ms/step - loss: 0.4578 - accuracy: 0.8273 - val_loss: 0.4641 - val_accuracy: 0.8278 Epoch 16/80 230/230 [==============================] - 54s 233ms/step - loss: 0.4417 - accuracy: 0.8371 - val_loss: 0.4723 - val_accuracy: 0.8249 Epoch 17/80 230/230 [==============================] - 55s 234ms/step - loss: 0.4313 - accuracy: 0.8441 - val_loss: 0.4518 - val_accuracy: 0.8399 Epoch 18/80 230/230 [==============================] - 54s 229ms/step - loss: 0.4214 - accuracy: 0.8456 - val_loss: 0.4462 - val_accuracy: 0.8437 Epoch 19/80 230/230 [==============================] - 54s 232ms/step - loss: 0.4164 - accuracy: 0.8457 - val_loss: 0.4571 - val_accuracy: 0.8344 Epoch 20/80 230/230 [==============================] - 64s 275ms/step - loss: 0.4128 - accuracy: 0.8480 - val_loss: 0.4536 - val_accuracy: 0.8437 Epoch 21/80 230/230 [==============================] - 54s 228ms/step - loss: 0.4069 - accuracy: 0.8509 - val_loss: 0.4428 - val_accuracy: 0.8472 Epoch 22/80 230/230 [==============================] - 55s 235ms/step - loss: 0.4034 - accuracy: 0.8523 - val_loss: 0.4329 - val_accuracy: 0.8462 Epoch 23/80 230/230 [==============================] - 54s 231ms/step - loss: 0.3960 - accuracy: 0.8596 - val_loss: 0.4359 - val_accuracy: 0.8440 Epoch 24/80 230/230 [==============================] - 54s 232ms/step - loss: 0.3859 - accuracy: 0.8602 - val_loss: 0.4339 - val_accuracy: 0.8450 Epoch 25/80 230/230 [==============================] - 55s 236ms/step - loss: 0.3830 - accuracy: 0.8633 - val_loss: 0.4282 - val_accuracy: 0.8529 Epoch 26/80 230/230 [==============================] - 53s 228ms/step - loss: 0.3842 - accuracy: 0.8632 - val_loss: 0.4330 - val_accuracy: 0.8459 Epoch 27/80 230/230 [==============================] - 54s 231ms/step - loss: 0.3871 - accuracy: 0.8585 - val_loss: 0.4272 - val_accuracy: 0.8548 Epoch 28/80 230/230 [==============================] - 55s 234ms/step - loss: 0.3771 - accuracy: 0.8636 - val_loss: 0.4202 - val_accuracy: 0.8539 Epoch 29/80 230/230 [==============================] - 54s 228ms/step - loss: 0.3686 - accuracy: 0.8670 - val_loss: 0.4194 - val_accuracy: 0.8520 Epoch 30/80 230/230 [==============================] - 54s 233ms/step - loss: 0.3677 - accuracy: 0.8692 - val_loss: 0.4242 - val_accuracy: 0.8532 Epoch 31/80 230/230 [==============================] - 55s 235ms/step - loss: 0.3601 - accuracy: 0.8750 - val_loss: 0.4156 - val_accuracy: 0.8539 Epoch 32/80 230/230 [==============================] - 54s 232ms/step - loss: 0.3586 - accuracy: 0.8723 - val_loss: 0.4142 - val_accuracy: 0.8574 Epoch 33/80 230/230 [==============================] - 55s 236ms/step - loss: 0.3551 - accuracy: 0.8716 - val_loss: 0.4036 - val_accuracy: 0.8583 Epoch 34/80 230/230 [==============================] - 55s 233ms/step - loss: 0.3503 - accuracy: 0.8778 - val_loss: 0.4066 - val_accuracy: 0.8564 Epoch 35/80 230/230 [==============================] - 56s 241ms/step - loss: 0.3546 - accuracy: 0.8760 - val_loss: 0.4143 - val_accuracy: 0.8586 Epoch 36/80 230/230 [==============================] - 64s 277ms/step - loss: 0.3534 - accuracy: 0.8746 - val_loss: 0.4034 - val_accuracy: 0.8548 Epoch 37/80 230/230 [==============================] - 55s 235ms/step - loss: 0.3464 - accuracy: 0.8763 - val_loss: 0.3965 - val_accuracy: 0.8606 Epoch 38/80 230/230 [==============================] - 55s 238ms/step - loss: 0.3457 - accuracy: 0.8774 - val_loss: 0.3990 - val_accuracy: 0.8618 Epoch 39/80 230/230 [==============================] - 67s 286ms/step - loss: 0.3363 - accuracy: 0.8823 - val_loss: 0.4006 - val_accuracy: 0.8602 Epoch 40/80 230/230 [==============================] - 55s 237ms/step - loss: 0.3439 - accuracy: 0.8820 - val_loss: 0.3954 - val_accuracy: 0.8609 Epoch 41/80 230/230 [==============================] - 55s 237ms/step - loss: 0.3421 - accuracy: 0.8771 - val_loss: 0.3945 - val_accuracy: 0.8621 Epoch 42/80 230/230 [==============================] - 56s 237ms/step - loss: 0.3320 - accuracy: 0.8857 - val_loss: 0.3975 - val_accuracy: 0.8628 Epoch 43/80 230/230 [==============================] - 56s 239ms/step - loss: 0.3292 - accuracy: 0.8888 - val_loss: 0.4002 - val_accuracy: 0.8618 Epoch 44/80 230/230 [==============================] - 55s 236ms/step - loss: 0.3361 - accuracy: 0.8855 - val_loss: 0.3931 - val_accuracy: 0.8641 Epoch 45/80 230/230 [==============================] - 65s 279ms/step - loss: 0.3306 - accuracy: 0.8879 - val_loss: 0.3926 - val_accuracy: 0.8647 Epoch 46/80 230/230 [==============================] - 65s 281ms/step - loss: 0.3211 - accuracy: 0.8920 - val_loss: 0.3963 - val_accuracy: 0.8618 Epoch 47/80 230/230 [==============================] - 55s 237ms/step - loss: 0.3278 - accuracy: 0.8872 - val_loss: 0.3970 - val_accuracy: 0.8644 Epoch 48/80 230/230 [==============================] - 55s 236ms/step - loss: 0.3223 - accuracy: 0.8883 - val_loss: 0.3863 - val_accuracy: 0.8672 Epoch 49/80 230/230 [==============================] - 55s 234ms/step - loss: 0.3258 - accuracy: 0.8874 - val_loss: 0.3906 - val_accuracy: 0.8656 Epoch 50/80 230/230 [==============================] - 56s 237ms/step - loss: 0.3166 - accuracy: 0.8917 - val_loss: 0.3929 - val_accuracy: 0.8656 Epoch 51/80 230/230 [==============================] - 57s 240ms/step - loss: 0.3183 - accuracy: 0.8873 - val_loss: 0.3953 - val_accuracy: 0.8631 Epoch 52/80 230/230 [==============================] - 56s 238ms/step - loss: 0.3218 - accuracy: 0.8883 - val_loss: 0.3910 - val_accuracy: 0.8612 Epoch 53/80 230/230 [==============================] - 55s 237ms/step - loss: 0.3184 - accuracy: 0.8895 - val_loss: 0.3859 - val_accuracy: 0.8676 Epoch 54/80 230/230 [==============================] - 56s 239ms/step - loss: 0.3118 - accuracy: 0.8948 - val_loss: 0.3811 - val_accuracy: 0.8663 Epoch 55/80 230/230 [==============================] - 56s 240ms/step - loss: 0.3092 - accuracy: 0.8958 - val_loss: 0.3858 - val_accuracy: 0.8679 Epoch 56/80 230/230 [==============================] - 65s 278ms/step - loss: 0.3084 - accuracy: 0.8929 - val_loss: 0.3877 - val_accuracy: 0.8679 Epoch 57/80 230/230 [==============================] - 56s 240ms/step - loss: 0.3064 - accuracy: 0.8960 - val_loss: 0.3829 - val_accuracy: 0.8666 Epoch 58/80 230/230 [==============================] - 56s 239ms/step - loss: 0.3096 - accuracy: 0.8941 - val_loss: 0.3850 - val_accuracy: 0.8663 Epoch 59/80 230/230 [==============================] - 56s 237ms/step - loss: 0.3048 - accuracy: 0.8932 - val_loss: 0.3829 - val_accuracy: 0.8666 Epoch 60/80 230/230 [==============================] - 55s 237ms/step - loss: 0.2992 - accuracy: 0.8989 - val_loss: 0.3810 - val_accuracy: 0.8621 Epoch 61/80 230/230 [==============================] - 55s 235ms/step - loss: 0.3045 - accuracy: 0.8917 - val_loss: 0.3851 - val_accuracy: 0.8631 Epoch 62/80 230/230 [==============================] - 55s 234ms/step - loss: 0.3091 - accuracy: 0.8950 - val_loss: 0.3736 - val_accuracy: 0.8691 Epoch 63/80 230/230 [==============================] - 55s 236ms/step - loss: 0.3066 - accuracy: 0.8965 - val_loss: 0.3774 - val_accuracy: 0.8663 Epoch 64/80 230/230 [==============================] - 55s 235ms/step - loss: 0.2984 - accuracy: 0.9004 - val_loss: 0.3787 - val_accuracy: 0.8676 Epoch 65/80 230/230 [==============================] - 56s 238ms/step - loss: 0.2922 - accuracy: 0.9011 - val_loss: 0.3764 - val_accuracy: 0.8669 Epoch 66/80 230/230 [==============================] - 57s 245ms/step - loss: 0.2937 - accuracy: 0.9031 - val_loss: 0.3818 - val_accuracy: 0.8663 Epoch 67/80 230/230 [==============================] - 56s 240ms/step - loss: 0.2943 - accuracy: 0.9004 - val_loss: 0.3749 - val_accuracy: 0.8679 Epoch 68/80 230/230 [==============================] - 65s 280ms/step - loss: 0.2994 - accuracy: 0.8958 - val_loss: 0.3784 - val_accuracy: 0.8672 Epoch 69/80 230/230 [==============================] - 66s 284ms/step - loss: 0.2965 - accuracy: 0.8963 - val_loss: 0.3809 - val_accuracy: 0.8704 Epoch 70/80 230/230 [==============================] - 66s 282ms/step - loss: 0.2937 - accuracy: 0.8975 - val_loss: 0.3752 - val_accuracy: 0.8707 Epoch 71/80 230/230 [==============================] - 56s 239ms/step - loss: 0.2846 - accuracy: 0.9042 - val_loss: 0.3768 - val_accuracy: 0.8695 Epoch 72/80 230/230 [==============================] - 57s 241ms/step - loss: 0.2934 - accuracy: 0.8996 - val_loss: 0.3750 - val_accuracy: 0.8720
# Visualization of the learning curves
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.ylim([0.0, 2.0])
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend(['train', 'valid'])
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.ylim([0.5, 1.0])
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(['train', 'valid'])
<matplotlib.legend.Legend at 0x7cd4d813b130>
net.save('models/Segmented3.keras')
net.evaluate(test_ds)
6/6 [==============================] - 214s 37s/step - loss: 0.5025 - accuracy: 0.8256
[0.5025416612625122, 0.8256130814552307]
net.evaluate(test_ds_cropped)
21/21 [==============================] - 696s 33s/step - loss: 0.5081 - accuracy: 0.8302
[0.508144736289978, 0.8302253484725952]
net.evaluate(test_ds_cropped_balanced)
6/6 [==============================] - 165s 27s/step - loss: 0.4214 - accuracy: 0.8484
[0.4213521182537079, 0.8483606576919556]
The accuracy achieved on the test set is notably lower than the accuracy achieved in the validation set, this could be signed of overfitting. The only train accuracy that appears to be higher than the one achieved in the original model (84.74%) is the one achieved in the balanced and segmented test set (84.84%). This could signal better performances on the model if applied to data that is already segmented. Though, the gap is not big.
As we said before, the classes in this segmented dataset are unbalanced, we are going to leave dandelion to 1275, and subset every other flower class. Subsetting is not easy, since we have to make sure that each original image is in the subset.
# Original dimensions of classes
diz = {}
for clas in classes:
diz[clas] = len(os.listdir(train_path + clas))
diz
{'daisy': 2477, 'dandelion': 1275, 'roses': 1504, 'sunflowers': 2229, 'tulips': 2986}
subsets = {}
for clas in classes:
lst = []
listdir = os.listdir(train_path + clas)
if clas == 'dandelion':
subsets[clas] = listdir
continue
uniques = []
for img_path in listdir:
# Search for the unique images
unique = re.findall(r'(.*)_\d+.jpg', img_path)[0]
uniques.append(unique)
uniques = set(uniques)
for unique in uniques:
batch = []
for img_path in listdir:
if unique in img_path:
batch.append(img_path)
# Prendine uno a caso da batch
random_element = random.choice(batch)
# Aggiungilo a lst
lst.append(random_element)
# Rimuovilo da listdir
listdir.remove(random_element)
# Ora siamo sicuri di avere un alemenento per ciascuna foto, prendiamo gli altri casualmenti da quelli rimasti in listdir
lst = lst + random.sample(listdir, 1275 - len(lst))
# Save it in the dictionary
subsets[clas] = lst
diz = {}
for clas in classes:
diz[clas] = len(subsets[clas])
diz
{'daisy': 1275, 'dandelion': 1275, 'roses': 1275, 'sunflowers': 1275, 'tulips': 1275}
train_balanced_path = 'C:/Users/david/Desktop/DeepLearning/flower_cropped/TrainBalanced/'
# Remove files that are not in the dictionary
for clas in classes:
for img in os.listdir(train_balanced_path + clas):
if img not in subsets[clas]:
os.remove(train_balanced_path + clas + '/' + img)
base_path = 'C:/Users/david/Desktop/DeepLearning/flower_cropped/'
train_ds = keras.preprocessing.image_dataset_from_directory(base_path + 'TrainBalanced',
image_size=(224,224),
batch_size=32,
label_mode='categorical',
subset='training',
validation_split = 0.3,
shuffle=True,
seed=1)
val_ds = keras.preprocessing.image_dataset_from_directory(base_path + 'TrainBalanced',
image_size=(224,224),
batch_size=32,
label_mode='categorical',
subset='validation',
validation_split = 0.3,
shuffle=True,
seed=1)
# Data loader with (slightly) larger images
train_ds_256 = keras.preprocessing.image_dataset_from_directory(base_path + 'TrainBalanced',
image_size=(256,256),
batch_size=32,
label_mode='categorical',
subset='training',
validation_split = 0.3,
shuffle=True,
seed=1)
num_classes = 5
Found 6375 files belonging to 5 classes. Using 4463 files for training. Found 6375 files belonging to 5 classes. Using 1912 files for validation. Found 6375 files belonging to 5 classes. Using 4463 files for training.
Testing the performances of the first of the two best models:
# Architecture definition
inputs = keras.Input((None,None,3))
x = inputs
x = keras.layers.RandomCrop(224, 224)(x)
x = keras.layers.RandomFlip(mode='horizontal')(x)
x = keras.layers.RandomContrast(0.25)(x)
x = keras.layers.Conv2D(32, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Conv2D(64, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.Conv2D(128, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.Dropout(0.2)(x)
x = keras.layers.GlobalMaxPooling2D()(x)
outputs = keras.layers.Dense(num_classes, activation="softmax")(x)
net = keras.Model(inputs, outputs)
callback = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)
lr_schedule = keras.optimizers.schedules.InverseTimeDecay(
initial_learning_rate = 0.0005,
decay_steps = 65,
decay_rate = 0.08)
optimizer = keras.optimizers.Adam(learning_rate=lr_schedule)
net.compile(loss=keras.losses.categorical_crossentropy,
optimizer=optimizer,
metrics=['accuracy'])
# Model training
history = net.fit(train_ds_256,
epochs=80,
validation_data=val_ds,
callbacks=[callback])
Epoch 1/80 140/140 [==============================] - 21s 117ms/step - loss: 1.2473 - accuracy: 0.5326 - val_loss: 1.0856 - val_accuracy: 0.5502 Epoch 2/80 140/140 [==============================] - 15s 107ms/step - loss: 0.8820 - accuracy: 0.6511 - val_loss: 0.8454 - val_accuracy: 0.6606 Epoch 3/80 140/140 [==============================] - 15s 109ms/step - loss: 0.8228 - accuracy: 0.6758 - val_loss: 0.8069 - val_accuracy: 0.6668 Epoch 4/80 140/140 [==============================] - 15s 106ms/step - loss: 0.7680 - accuracy: 0.6998 - val_loss: 0.7246 - val_accuracy: 0.7171 Epoch 5/80 140/140 [==============================] - 15s 107ms/step - loss: 0.7417 - accuracy: 0.7150 - val_loss: 0.7215 - val_accuracy: 0.7265 Epoch 6/80 140/140 [==============================] - 15s 108ms/step - loss: 0.7069 - accuracy: 0.7242 - val_loss: 0.7217 - val_accuracy: 0.7176 Epoch 7/80 140/140 [==============================] - 15s 109ms/step - loss: 0.6682 - accuracy: 0.7464 - val_loss: 0.7310 - val_accuracy: 0.7113 Epoch 8/80 140/140 [==============================] - 15s 107ms/step - loss: 0.6528 - accuracy: 0.7475 - val_loss: 0.6889 - val_accuracy: 0.7395 Epoch 9/80 140/140 [==============================] - 16s 111ms/step - loss: 0.6388 - accuracy: 0.7560 - val_loss: 0.6740 - val_accuracy: 0.7395 Epoch 10/80 140/140 [==============================] - 15s 107ms/step - loss: 0.6217 - accuracy: 0.7643 - val_loss: 0.6499 - val_accuracy: 0.7563 Epoch 11/80 140/140 [==============================] - 17s 118ms/step - loss: 0.6197 - accuracy: 0.7683 - val_loss: 0.6418 - val_accuracy: 0.7641 Epoch 12/80 140/140 [==============================] - 19s 136ms/step - loss: 0.6162 - accuracy: 0.7659 - val_loss: 0.6204 - val_accuracy: 0.7845 Epoch 13/80 140/140 [==============================] - 20s 146ms/step - loss: 0.5863 - accuracy: 0.7777 - val_loss: 0.6329 - val_accuracy: 0.7683 Epoch 14/80 140/140 [==============================] - 22s 157ms/step - loss: 0.5957 - accuracy: 0.7688 - val_loss: 0.6246 - val_accuracy: 0.7657 Epoch 15/80 140/140 [==============================] - 23s 165ms/step - loss: 0.5853 - accuracy: 0.7737 - val_loss: 0.6050 - val_accuracy: 0.7793 Epoch 16/80 140/140 [==============================] - 26s 187ms/step - loss: 0.5674 - accuracy: 0.7883 - val_loss: 0.6299 - val_accuracy: 0.7641 Epoch 17/80 140/140 [==============================] - 27s 190ms/step - loss: 0.5560 - accuracy: 0.7968 - val_loss: 0.6052 - val_accuracy: 0.7756 Epoch 18/80 140/140 [==============================] - 28s 199ms/step - loss: 0.5577 - accuracy: 0.7887 - val_loss: 0.5946 - val_accuracy: 0.7803 Epoch 19/80 140/140 [==============================] - 30s 213ms/step - loss: 0.5493 - accuracy: 0.7948 - val_loss: 0.5928 - val_accuracy: 0.7819 Epoch 20/80 140/140 [==============================] - 30s 215ms/step - loss: 0.5356 - accuracy: 0.8039 - val_loss: 0.5859 - val_accuracy: 0.7871 Epoch 21/80 140/140 [==============================] - 29s 207ms/step - loss: 0.5387 - accuracy: 0.7965 - val_loss: 0.6131 - val_accuracy: 0.7730 Epoch 22/80 140/140 [==============================] - 31s 225ms/step - loss: 0.5266 - accuracy: 0.8082 - val_loss: 0.5709 - val_accuracy: 0.8007 Epoch 23/80 140/140 [==============================] - 30s 218ms/step - loss: 0.5322 - accuracy: 0.8066 - val_loss: 0.5909 - val_accuracy: 0.7887 Epoch 24/80 140/140 [==============================] - 32s 231ms/step - loss: 0.5252 - accuracy: 0.7997 - val_loss: 0.5752 - val_accuracy: 0.7903 Epoch 25/80 140/140 [==============================] - 33s 238ms/step - loss: 0.5207 - accuracy: 0.8111 - val_loss: 0.5753 - val_accuracy: 0.7924 Epoch 26/80 140/140 [==============================] - 34s 247ms/step - loss: 0.5274 - accuracy: 0.8004 - val_loss: 0.5750 - val_accuracy: 0.7861 Epoch 27/80 140/140 [==============================] - 34s 244ms/step - loss: 0.5046 - accuracy: 0.8136 - val_loss: 0.5592 - val_accuracy: 0.7976 Epoch 28/80 140/140 [==============================] - 35s 246ms/step - loss: 0.5087 - accuracy: 0.8151 - val_loss: 0.5679 - val_accuracy: 0.7945 Epoch 29/80 140/140 [==============================] - 35s 249ms/step - loss: 0.4979 - accuracy: 0.8156 - val_loss: 0.5527 - val_accuracy: 0.7997 Epoch 30/80 140/140 [==============================] - 35s 247ms/step - loss: 0.4941 - accuracy: 0.8205 - val_loss: 0.5591 - val_accuracy: 0.7945 Epoch 31/80 140/140 [==============================] - 34s 246ms/step - loss: 0.4890 - accuracy: 0.8219 - val_loss: 0.5582 - val_accuracy: 0.7960 Epoch 32/80 140/140 [==============================] - 35s 249ms/step - loss: 0.4902 - accuracy: 0.8196 - val_loss: 0.5575 - val_accuracy: 0.7986 Epoch 33/80 140/140 [==============================] - 36s 253ms/step - loss: 0.4903 - accuracy: 0.8201 - val_loss: 0.5571 - val_accuracy: 0.7939 Epoch 34/80 140/140 [==============================] - 35s 250ms/step - loss: 0.4706 - accuracy: 0.8286 - val_loss: 0.5544 - val_accuracy: 0.8007 Epoch 35/80 140/140 [==============================] - 35s 249ms/step - loss: 0.4836 - accuracy: 0.8230 - val_loss: 0.5398 - val_accuracy: 0.8070 Epoch 36/80 140/140 [==============================] - 35s 250ms/step - loss: 0.4824 - accuracy: 0.8263 - val_loss: 0.5833 - val_accuracy: 0.7856 Epoch 37/80 140/140 [==============================] - 35s 250ms/step - loss: 0.4672 - accuracy: 0.8241 - val_loss: 0.5485 - val_accuracy: 0.8002 Epoch 38/80 140/140 [==============================] - 35s 249ms/step - loss: 0.4781 - accuracy: 0.8259 - val_loss: 0.5311 - val_accuracy: 0.8143 Epoch 39/80 140/140 [==============================] - 35s 249ms/step - loss: 0.4722 - accuracy: 0.8288 - val_loss: 0.5307 - val_accuracy: 0.8180 Epoch 40/80 140/140 [==============================] - 35s 247ms/step - loss: 0.4668 - accuracy: 0.8286 - val_loss: 0.5376 - val_accuracy: 0.8075 Epoch 41/80 140/140 [==============================] - 35s 248ms/step - loss: 0.4708 - accuracy: 0.8243 - val_loss: 0.5433 - val_accuracy: 0.8033 Epoch 42/80 140/140 [==============================] - 35s 248ms/step - loss: 0.4632 - accuracy: 0.8322 - val_loss: 0.5352 - val_accuracy: 0.8049 Epoch 43/80 140/140 [==============================] - 35s 249ms/step - loss: 0.4626 - accuracy: 0.8281 - val_loss: 0.5432 - val_accuracy: 0.8018 Epoch 44/80 140/140 [==============================] - 35s 249ms/step - loss: 0.4505 - accuracy: 0.8367 - val_loss: 0.5401 - val_accuracy: 0.7997 Epoch 45/80 140/140 [==============================] - 35s 250ms/step - loss: 0.4517 - accuracy: 0.8342 - val_loss: 0.5316 - val_accuracy: 0.8075 Epoch 46/80 140/140 [==============================] - 35s 249ms/step - loss: 0.4584 - accuracy: 0.8373 - val_loss: 0.5352 - val_accuracy: 0.8065 Epoch 47/80 140/140 [==============================] - 35s 250ms/step - loss: 0.4510 - accuracy: 0.8418 - val_loss: 0.5389 - val_accuracy: 0.8007 Epoch 48/80 140/140 [==============================] - 35s 249ms/step - loss: 0.4500 - accuracy: 0.8328 - val_loss: 0.5227 - val_accuracy: 0.8133 Epoch 49/80 140/140 [==============================] - 35s 247ms/step - loss: 0.4443 - accuracy: 0.8371 - val_loss: 0.5237 - val_accuracy: 0.8143 Epoch 50/80 140/140 [==============================] - 35s 246ms/step - loss: 0.4430 - accuracy: 0.8387 - val_loss: 0.5316 - val_accuracy: 0.8081 Epoch 51/80 140/140 [==============================] - 35s 246ms/step - loss: 0.4400 - accuracy: 0.8391 - val_loss: 0.5249 - val_accuracy: 0.8091 Epoch 52/80 140/140 [==============================] - 35s 248ms/step - loss: 0.4346 - accuracy: 0.8423 - val_loss: 0.5230 - val_accuracy: 0.8138 Epoch 53/80 140/140 [==============================] - 35s 250ms/step - loss: 0.4465 - accuracy: 0.8369 - val_loss: 0.5289 - val_accuracy: 0.8081 Epoch 54/80 140/140 [==============================] - 35s 249ms/step - loss: 0.4337 - accuracy: 0.8402 - val_loss: 0.5231 - val_accuracy: 0.8075 Epoch 55/80 140/140 [==============================] - 35s 249ms/step - loss: 0.4175 - accuracy: 0.8481 - val_loss: 0.5398 - val_accuracy: 0.8060 Epoch 56/80 140/140 [==============================] - 35s 249ms/step - loss: 0.4301 - accuracy: 0.8465 - val_loss: 0.5253 - val_accuracy: 0.8096 Epoch 57/80 140/140 [==============================] - 35s 250ms/step - loss: 0.4246 - accuracy: 0.8526 - val_loss: 0.5297 - val_accuracy: 0.8096 Epoch 58/80 140/140 [==============================] - 35s 248ms/step - loss: 0.4330 - accuracy: 0.8427 - val_loss: 0.5247 - val_accuracy: 0.8101
# Visualization of the learning curves
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.ylim([0.0, 2.0])
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend(['train', 'valid'])
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.ylim([0.5, 1.0])
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(['train', 'valid'])
<matplotlib.legend.Legend at 0x2b080699460>
net.save('models/BalancedSegmentv1.keras')
net = keras.models.load_model("models/BalancedSegmentv1.keras")
net.evaluate(test_ds)
net.evaluate(test_ds_cropped)
net.evaluate(test_ds_cropped_balanced)
6/6 [==============================] - 9s 531ms/step - loss: 0.5800 - accuracy: 0.8038 21/21 [==============================] - 4s 187ms/step - loss: 0.6111 - accuracy: 0.7848 6/6 [==============================] - 3s 594ms/step - loss: 0.4968 - accuracy: 0.8279
[0.49677494168281555, 0.8278688788414001]
None of the three accuracy resulted to be higher than the test accuracy we achieved with the model with unsegmented data (83.65%). Also, the balancing of the dataset did not seem to increase the accuracy either, since the accuracy on all three of the test datasets decreased.
Testing the performances of the second of the two best models:
# Architecture definition
inputs = keras.Input((None,None,3))
x = inputs
x = keras.layers.RandomCrop(224, 224)(x)
x = keras.layers.RandomFlip(mode='horizontal')(x)
x = keras.layers.RandomContrast(0.25)(x)
x = keras.layers.Conv2D(64, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.Conv2D(128, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.Conv2D(256, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.GlobalMaxPooling2D()(x)
outputs = keras.layers.Dense(1024, activation="softmax")(x)
x = keras.layers.Dropout(0.2)(x)
outputs = keras.layers.Dense(512, activation="softmax")(x)
outputs = keras.layers.Dense(num_classes, activation="softmax")(x)
net = keras.Model(inputs, outputs)
callback = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)
lr_schedule = keras.optimizers.schedules.InverseTimeDecay(
initial_learning_rate = 0.0005,
decay_steps = 65,
decay_rate = 0.08)
optimizer = keras.optimizers.Adam(learning_rate=lr_schedule)
net.compile(loss=keras.losses.categorical_crossentropy,
optimizer=optimizer,
metrics=['accuracy'])
# Model training
history = net.fit(train_ds_256,
epochs=80,
validation_data=val_ds,
callbacks=[callback])
Epoch 1/80 140/140 [==============================] - 90s 641ms/step - loss: 1.7278 - accuracy: 0.4613 - val_loss: 1.2653 - val_accuracy: 0.5335 Epoch 2/80 140/140 [==============================] - 75s 538ms/step - loss: 1.2755 - accuracy: 0.5548 - val_loss: 0.9264 - val_accuracy: 0.6245 Epoch 3/80 140/140 [==============================] - 76s 539ms/step - loss: 1.1573 - accuracy: 0.5772 - val_loss: 0.8170 - val_accuracy: 0.6768 Epoch 4/80 140/140 [==============================] - 75s 539ms/step - loss: 1.0786 - accuracy: 0.6034 - val_loss: 0.7736 - val_accuracy: 0.6967 Epoch 5/80 140/140 [==============================] - 75s 539ms/step - loss: 1.0173 - accuracy: 0.6278 - val_loss: 0.7631 - val_accuracy: 0.6987 Epoch 6/80 140/140 [==============================] - 75s 538ms/step - loss: 0.9650 - accuracy: 0.6366 - val_loss: 0.7770 - val_accuracy: 0.6878 Epoch 7/80 140/140 [==============================] - 75s 539ms/step - loss: 0.9596 - accuracy: 0.6361 - val_loss: 0.7392 - val_accuracy: 0.7212 Epoch 8/80 140/140 [==============================] - 75s 537ms/step - loss: 0.9110 - accuracy: 0.6596 - val_loss: 0.7036 - val_accuracy: 0.7306 Epoch 9/80 140/140 [==============================] - 75s 538ms/step - loss: 0.8890 - accuracy: 0.6628 - val_loss: 0.6969 - val_accuracy: 0.7442 Epoch 10/80 140/140 [==============================] - 75s 538ms/step - loss: 0.8666 - accuracy: 0.6711 - val_loss: 0.6588 - val_accuracy: 0.7516 Epoch 11/80 140/140 [==============================] - 75s 539ms/step - loss: 0.8601 - accuracy: 0.6836 - val_loss: 0.6706 - val_accuracy: 0.7432 Epoch 12/80 140/140 [==============================] - 75s 538ms/step - loss: 0.8458 - accuracy: 0.6717 - val_loss: 0.6459 - val_accuracy: 0.7531 Epoch 13/80 140/140 [==============================] - 75s 538ms/step - loss: 0.8221 - accuracy: 0.6892 - val_loss: 0.6402 - val_accuracy: 0.7568 Epoch 14/80 140/140 [==============================] - 75s 538ms/step - loss: 0.8132 - accuracy: 0.6906 - val_loss: 0.6231 - val_accuracy: 0.7652 Epoch 15/80 140/140 [==============================] - 75s 539ms/step - loss: 0.7865 - accuracy: 0.6944 - val_loss: 0.6335 - val_accuracy: 0.7636 Epoch 16/80 140/140 [==============================] - 76s 539ms/step - loss: 0.7923 - accuracy: 0.7031 - val_loss: 0.6196 - val_accuracy: 0.7688 Epoch 17/80 140/140 [==============================] - 75s 538ms/step - loss: 0.7765 - accuracy: 0.6944 - val_loss: 0.6088 - val_accuracy: 0.7720 Epoch 18/80 140/140 [==============================] - 75s 538ms/step - loss: 0.7583 - accuracy: 0.7105 - val_loss: 0.5969 - val_accuracy: 0.7788 Epoch 19/80 140/140 [==============================] - 75s 539ms/step - loss: 0.7458 - accuracy: 0.7170 - val_loss: 0.6255 - val_accuracy: 0.7542 Epoch 20/80 140/140 [==============================] - 75s 536ms/step - loss: 0.7293 - accuracy: 0.7244 - val_loss: 0.5878 - val_accuracy: 0.7819 Epoch 21/80 140/140 [==============================] - 75s 538ms/step - loss: 0.7479 - accuracy: 0.7119 - val_loss: 0.6028 - val_accuracy: 0.7641 Epoch 22/80 140/140 [==============================] - 76s 539ms/step - loss: 0.7432 - accuracy: 0.7177 - val_loss: 0.5969 - val_accuracy: 0.7793 Epoch 23/80 140/140 [==============================] - 75s 539ms/step - loss: 0.7283 - accuracy: 0.7206 - val_loss: 0.5793 - val_accuracy: 0.7882 Epoch 24/80 140/140 [==============================] - 76s 540ms/step - loss: 0.7182 - accuracy: 0.7246 - val_loss: 0.5805 - val_accuracy: 0.7892 Epoch 25/80 140/140 [==============================] - 75s 538ms/step - loss: 0.7285 - accuracy: 0.7231 - val_loss: 0.6001 - val_accuracy: 0.7767 Epoch 26/80 140/140 [==============================] - 75s 539ms/step - loss: 0.7201 - accuracy: 0.7255 - val_loss: 0.5754 - val_accuracy: 0.7882 Epoch 27/80 140/140 [==============================] - 75s 538ms/step - loss: 0.7016 - accuracy: 0.7320 - val_loss: 0.5711 - val_accuracy: 0.7924 Epoch 28/80 140/140 [==============================] - 75s 538ms/step - loss: 0.7142 - accuracy: 0.7240 - val_loss: 0.5714 - val_accuracy: 0.7908 Epoch 29/80 140/140 [==============================] - 75s 538ms/step - loss: 0.6914 - accuracy: 0.7367 - val_loss: 0.5645 - val_accuracy: 0.8013 Epoch 30/80 140/140 [==============================] - 75s 537ms/step - loss: 0.6865 - accuracy: 0.7372 - val_loss: 0.5685 - val_accuracy: 0.7986 Epoch 31/80 140/140 [==============================] - 76s 540ms/step - loss: 0.6951 - accuracy: 0.7309 - val_loss: 0.5738 - val_accuracy: 0.7918 Epoch 32/80 140/140 [==============================] - 75s 537ms/step - loss: 0.6711 - accuracy: 0.7421 - val_loss: 0.5701 - val_accuracy: 0.7908 Epoch 33/80 140/140 [==============================] - 76s 540ms/step - loss: 0.6861 - accuracy: 0.7378 - val_loss: 0.5542 - val_accuracy: 0.8060 Epoch 34/80 140/140 [==============================] - 75s 539ms/step - loss: 0.6760 - accuracy: 0.7417 - val_loss: 0.5545 - val_accuracy: 0.7992 Epoch 35/80 140/140 [==============================] - 75s 539ms/step - loss: 0.6761 - accuracy: 0.7477 - val_loss: 0.5520 - val_accuracy: 0.7997 Epoch 36/80 140/140 [==============================] - 75s 538ms/step - loss: 0.6519 - accuracy: 0.7533 - val_loss: 0.5486 - val_accuracy: 0.8117 Epoch 37/80 140/140 [==============================] - 75s 538ms/step - loss: 0.6613 - accuracy: 0.7365 - val_loss: 0.5604 - val_accuracy: 0.7960 Epoch 38/80 140/140 [==============================] - 75s 538ms/step - loss: 0.6465 - accuracy: 0.7546 - val_loss: 0.5815 - val_accuracy: 0.7688 Epoch 39/80 140/140 [==============================] - 75s 538ms/step - loss: 0.6497 - accuracy: 0.7600 - val_loss: 0.5436 - val_accuracy: 0.8060 Epoch 40/80 140/140 [==============================] - 76s 540ms/step - loss: 0.6622 - accuracy: 0.7428 - val_loss: 0.5481 - val_accuracy: 0.8013 Epoch 41/80 140/140 [==============================] - 76s 540ms/step - loss: 0.6389 - accuracy: 0.7555 - val_loss: 0.5436 - val_accuracy: 0.8060 Epoch 42/80 140/140 [==============================] - 75s 539ms/step - loss: 0.6458 - accuracy: 0.7522 - val_loss: 0.5505 - val_accuracy: 0.8044 Epoch 43/80 140/140 [==============================] - 75s 538ms/step - loss: 0.6440 - accuracy: 0.7531 - val_loss: 0.5482 - val_accuracy: 0.8023 Epoch 44/80 140/140 [==============================] - 75s 536ms/step - loss: 0.6437 - accuracy: 0.7490 - val_loss: 0.5409 - val_accuracy: 0.8049 Epoch 45/80 140/140 [==============================] - 75s 537ms/step - loss: 0.6391 - accuracy: 0.7582 - val_loss: 0.5435 - val_accuracy: 0.8070 Epoch 46/80 140/140 [==============================] - 76s 540ms/step - loss: 0.6191 - accuracy: 0.7571 - val_loss: 0.5336 - val_accuracy: 0.8075 Epoch 47/80 140/140 [==============================] - 75s 539ms/step - loss: 0.6371 - accuracy: 0.7582 - val_loss: 0.5327 - val_accuracy: 0.8122 Epoch 48/80 140/140 [==============================] - 75s 539ms/step - loss: 0.6399 - accuracy: 0.7544 - val_loss: 0.5356 - val_accuracy: 0.8096 Epoch 49/80 140/140 [==============================] - 75s 539ms/step - loss: 0.6301 - accuracy: 0.7598 - val_loss: 0.5462 - val_accuracy: 0.7992 Epoch 50/80 140/140 [==============================] - 75s 539ms/step - loss: 0.6273 - accuracy: 0.7580 - val_loss: 0.5275 - val_accuracy: 0.8180 Epoch 51/80 140/140 [==============================] - 75s 538ms/step - loss: 0.6334 - accuracy: 0.7582 - val_loss: 0.5384 - val_accuracy: 0.8023 Epoch 52/80 140/140 [==============================] - 75s 536ms/step - loss: 0.6291 - accuracy: 0.7614 - val_loss: 0.5494 - val_accuracy: 0.8033 Epoch 53/80 140/140 [==============================] - 75s 537ms/step - loss: 0.6279 - accuracy: 0.7571 - val_loss: 0.5318 - val_accuracy: 0.8128 Epoch 54/80 140/140 [==============================] - 76s 539ms/step - loss: 0.6192 - accuracy: 0.7638 - val_loss: 0.5276 - val_accuracy: 0.8112 Epoch 55/80 140/140 [==============================] - 75s 538ms/step - loss: 0.6010 - accuracy: 0.7676 - val_loss: 0.5367 - val_accuracy: 0.8013 Epoch 56/80 140/140 [==============================] - 75s 536ms/step - loss: 0.6222 - accuracy: 0.7627 - val_loss: 0.5242 - val_accuracy: 0.8143 Epoch 57/80 140/140 [==============================] - 75s 536ms/step - loss: 0.6012 - accuracy: 0.7667 - val_loss: 0.5250 - val_accuracy: 0.8149 Epoch 58/80 140/140 [==============================] - 75s 536ms/step - loss: 0.6040 - accuracy: 0.7694 - val_loss: 0.5273 - val_accuracy: 0.8159 Epoch 59/80 140/140 [==============================] - 75s 537ms/step - loss: 0.5878 - accuracy: 0.7746 - val_loss: 0.5214 - val_accuracy: 0.8149 Epoch 60/80 140/140 [==============================] - 76s 540ms/step - loss: 0.6040 - accuracy: 0.7692 - val_loss: 0.5295 - val_accuracy: 0.8096 Epoch 61/80 140/140 [==============================] - 76s 544ms/step - loss: 0.5974 - accuracy: 0.7661 - val_loss: 0.5164 - val_accuracy: 0.8196 Epoch 62/80 140/140 [==============================] - 76s 539ms/step - loss: 0.5932 - accuracy: 0.7724 - val_loss: 0.5133 - val_accuracy: 0.8164 Epoch 63/80 140/140 [==============================] - 75s 536ms/step - loss: 0.6027 - accuracy: 0.7744 - val_loss: 0.5145 - val_accuracy: 0.8164 Epoch 64/80 140/140 [==============================] - 75s 536ms/step - loss: 0.6014 - accuracy: 0.7694 - val_loss: 0.5131 - val_accuracy: 0.8154 Epoch 65/80 140/140 [==============================] - 75s 536ms/step - loss: 0.5940 - accuracy: 0.7656 - val_loss: 0.5167 - val_accuracy: 0.8206 Epoch 66/80 140/140 [==============================] - 75s 536ms/step - loss: 0.5947 - accuracy: 0.7688 - val_loss: 0.5224 - val_accuracy: 0.8154 Epoch 67/80 140/140 [==============================] - 75s 536ms/step - loss: 0.5984 - accuracy: 0.7739 - val_loss: 0.5115 - val_accuracy: 0.8196 Epoch 68/80 140/140 [==============================] - 75s 536ms/step - loss: 0.6151 - accuracy: 0.7681 - val_loss: 0.5171 - val_accuracy: 0.8138 Epoch 69/80 140/140 [==============================] - 75s 536ms/step - loss: 0.5884 - accuracy: 0.7730 - val_loss: 0.5230 - val_accuracy: 0.8133 Epoch 70/80 140/140 [==============================] - 75s 536ms/step - loss: 0.5795 - accuracy: 0.7782 - val_loss: 0.5145 - val_accuracy: 0.8133 Epoch 71/80 140/140 [==============================] - 75s 536ms/step - loss: 0.5954 - accuracy: 0.7717 - val_loss: 0.5092 - val_accuracy: 0.8227 Epoch 72/80 140/140 [==============================] - 75s 536ms/step - loss: 0.5931 - accuracy: 0.7712 - val_loss: 0.5077 - val_accuracy: 0.8206 Epoch 73/80 140/140 [==============================] - 75s 536ms/step - loss: 0.5912 - accuracy: 0.7831 - val_loss: 0.5080 - val_accuracy: 0.8196 Epoch 74/80 140/140 [==============================] - 75s 536ms/step - loss: 0.5912 - accuracy: 0.7739 - val_loss: 0.5093 - val_accuracy: 0.8201 Epoch 75/80 140/140 [==============================] - 75s 536ms/step - loss: 0.5838 - accuracy: 0.7730 - val_loss: 0.5137 - val_accuracy: 0.8169 Epoch 76/80 140/140 [==============================] - 75s 536ms/step - loss: 0.5849 - accuracy: 0.7813 - val_loss: 0.5097 - val_accuracy: 0.8201 Epoch 77/80 140/140 [==============================] - 75s 536ms/step - loss: 0.5692 - accuracy: 0.7818 - val_loss: 0.5087 - val_accuracy: 0.8169 Epoch 78/80 140/140 [==============================] - 75s 536ms/step - loss: 0.5733 - accuracy: 0.7793 - val_loss: 0.5071 - val_accuracy: 0.8190 Epoch 79/80 140/140 [==============================] - 75s 536ms/step - loss: 0.5783 - accuracy: 0.7824 - val_loss: 0.5133 - val_accuracy: 0.8169 Epoch 80/80 140/140 [==============================] - 76s 540ms/step - loss: 0.5673 - accuracy: 0.7820 - val_loss: 0.5008 - val_accuracy: 0.8290
# Visualization of the learning curves
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.ylim([0.0, 2.0])
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend(['train', 'valid'])
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.ylim([0.5, 1.0])
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(['train', 'valid'])
<matplotlib.legend.Legend at 0x2b10ed0e7f0>
net.save('models/BalancedSegmented2.keras')
net.evaluate(test_ds)
6/6 [==============================] - 78s 12s/step - loss: 0.5201 - accuracy: 0.8106
[0.5200757384300232, 0.8106266856193542]
net.evaluate(test_ds_cropped)
21/21 [==============================] - 147s 7s/step - loss: 0.5853 - accuracy: 0.8046
[0.5853006839752197, 0.8045843243598938]
net.evaluate(test_ds_cropped_balanced)
6/6 [==============================] - 42s 7s/step - loss: 0.4550 - accuracy: 0.8320
[0.4550371766090393, 0.8319672346115112]
None of the three accuracy resulted to be higher than the test accuracy we achieved with the same model applied to unsegmented data (84.74%). Also, the balancing of the dataset did not seem to increase the performance of the model, since the performances decreased on all the test sets.
As we did with the unbalanced data, since the dropout rates we set for the model with unsegmented data seems to be excessive now, we are going to retry this same architecture on the segmented and balanced data data, but changing the DropOut rates. In particular, we are going to remove the Dropout Layer from the last 1024 Dense layer.
# Architecture definition
inputs = keras.Input((None,None,3))
x = inputs
x = keras.layers.RandomCrop(224, 224)(x)
x = keras.layers.RandomFlip(mode='horizontal')(x)
x = keras.layers.RandomContrast(0.25)(x)
x = keras.layers.Conv2D(64, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.Conv2D(128, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.MaxPooling2D(3, strides=3, padding="same")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.Conv2D(256, 3, padding="same")(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Activation("relu")(x)
x = keras.layers.Dropout(0.1)(x)
x = keras.layers.GlobalMaxPooling2D()(x)
outputs = keras.layers.Dense(1024, activation="softmax")(x)
outputs = keras.layers.Dense(512, activation="softmax")(x)
outputs = keras.layers.Dense(num_classes, activation="softmax")(x)
net = keras.Model(inputs, outputs)
early_stopping = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)
checkpoint_filepath = "/content/gdrive/MyDrive/Deep Learning Project/Checkpoint3"
checkpoint_callback = tf.keras.callbacks.ModelCheckpoint(
filepath=checkpoint_filepath,
monitor='val_accuracy',
mode='max')
lr_schedule = keras.optimizers.schedules.InverseTimeDecay(
initial_learning_rate = 0.0005,
decay_steps = 65,
decay_rate = 0.08)
optimizer = keras.optimizers.Adam(learning_rate=lr_schedule)
net.compile(loss=keras.losses.categorical_crossentropy,
optimizer=optimizer,
metrics=['accuracy'])
# Model training
history = net.fit(train_ds_256,
epochs=80,
validation_data=val_ds,
callbacks=[early_stopping, checkpoint_callback])
Epoch 1/80 140/140 [==============================] - 2457s 17s/step - loss: 1.3198 - accuracy: 0.5337 - val_loss: 0.9736 - val_accuracy: 0.5816 Epoch 2/80 140/140 [==============================] - 35s 247ms/step - loss: 0.8740 - accuracy: 0.6561 - val_loss: 0.7808 - val_accuracy: 0.7040 Epoch 3/80 140/140 [==============================] - 35s 243ms/step - loss: 0.8116 - accuracy: 0.6812 - val_loss: 0.7205 - val_accuracy: 0.7385 Epoch 4/80 140/140 [==============================] - 35s 242ms/step - loss: 0.7513 - accuracy: 0.7022 - val_loss: 0.8024 - val_accuracy: 0.6888 Epoch 5/80 140/140 [==============================] - 36s 247ms/step - loss: 0.7038 - accuracy: 0.7213 - val_loss: 0.7024 - val_accuracy: 0.7327 Epoch 6/80 140/140 [==============================] - 34s 239ms/step - loss: 0.6835 - accuracy: 0.7363 - val_loss: 0.6768 - val_accuracy: 0.7453 Epoch 7/80 140/140 [==============================] - 34s 238ms/step - loss: 0.6472 - accuracy: 0.7479 - val_loss: 0.7409 - val_accuracy: 0.7055 Epoch 8/80 140/140 [==============================] - 36s 250ms/step - loss: 0.6269 - accuracy: 0.7582 - val_loss: 0.6507 - val_accuracy: 0.7547 Epoch 9/80 140/140 [==============================] - 39s 270ms/step - loss: 0.5944 - accuracy: 0.7735 - val_loss: 0.6200 - val_accuracy: 0.7720 Epoch 10/80 140/140 [==============================] - 35s 240ms/step - loss: 0.5818 - accuracy: 0.7797 - val_loss: 0.6247 - val_accuracy: 0.7542 Epoch 11/80 140/140 [==============================] - 38s 268ms/step - loss: 0.5774 - accuracy: 0.7847 - val_loss: 0.5907 - val_accuracy: 0.7777 Epoch 12/80 140/140 [==============================] - 38s 269ms/step - loss: 0.5567 - accuracy: 0.7941 - val_loss: 0.5902 - val_accuracy: 0.7835 Epoch 13/80 140/140 [==============================] - 35s 241ms/step - loss: 0.5406 - accuracy: 0.7952 - val_loss: 0.5719 - val_accuracy: 0.7955 Epoch 14/80 140/140 [==============================] - 35s 243ms/step - loss: 0.5269 - accuracy: 0.8082 - val_loss: 0.5745 - val_accuracy: 0.7856 Epoch 15/80 140/140 [==============================] - 34s 234ms/step - loss: 0.5236 - accuracy: 0.8006 - val_loss: 0.5540 - val_accuracy: 0.7981 Epoch 16/80 140/140 [==============================] - 34s 238ms/step - loss: 0.5130 - accuracy: 0.8055 - val_loss: 0.5636 - val_accuracy: 0.7929 Epoch 17/80 140/140 [==============================] - 35s 242ms/step - loss: 0.4895 - accuracy: 0.8232 - val_loss: 0.5840 - val_accuracy: 0.7772 Epoch 18/80 140/140 [==============================] - 34s 235ms/step - loss: 0.4902 - accuracy: 0.8140 - val_loss: 0.5485 - val_accuracy: 0.8054 Epoch 19/80 140/140 [==============================] - 36s 249ms/step - loss: 0.4817 - accuracy: 0.8255 - val_loss: 0.5405 - val_accuracy: 0.8091 Epoch 20/80 140/140 [==============================] - 38s 267ms/step - loss: 0.4732 - accuracy: 0.8241 - val_loss: 0.5420 - val_accuracy: 0.8070 Epoch 21/80 140/140 [==============================] - 35s 244ms/step - loss: 0.4615 - accuracy: 0.8295 - val_loss: 0.5348 - val_accuracy: 0.8070 Epoch 22/80 140/140 [==============================] - 36s 249ms/step - loss: 0.4496 - accuracy: 0.8326 - val_loss: 0.5191 - val_accuracy: 0.8122 Epoch 23/80 140/140 [==============================] - 35s 245ms/step - loss: 0.4553 - accuracy: 0.8380 - val_loss: 0.5549 - val_accuracy: 0.7882 Epoch 24/80 140/140 [==============================] - 35s 242ms/step - loss: 0.4366 - accuracy: 0.8402 - val_loss: 0.5289 - val_accuracy: 0.8112 Epoch 25/80 140/140 [==============================] - 36s 251ms/step - loss: 0.4471 - accuracy: 0.8335 - val_loss: 0.5254 - val_accuracy: 0.8054 Epoch 26/80 140/140 [==============================] - 34s 238ms/step - loss: 0.4370 - accuracy: 0.8411 - val_loss: 0.5119 - val_accuracy: 0.8154 Epoch 27/80 140/140 [==============================] - 36s 246ms/step - loss: 0.4259 - accuracy: 0.8461 - val_loss: 0.5027 - val_accuracy: 0.8243 Epoch 28/80 140/140 [==============================] - 37s 262ms/step - loss: 0.4207 - accuracy: 0.8463 - val_loss: 0.5160 - val_accuracy: 0.8190 Epoch 29/80 140/140 [==============================] - 35s 241ms/step - loss: 0.4140 - accuracy: 0.8537 - val_loss: 0.4951 - val_accuracy: 0.8217 Epoch 30/80 140/140 [==============================] - 34s 240ms/step - loss: 0.4168 - accuracy: 0.8505 - val_loss: 0.5036 - val_accuracy: 0.8217 Epoch 31/80 140/140 [==============================] - 36s 251ms/step - loss: 0.3959 - accuracy: 0.8606 - val_loss: 0.4913 - val_accuracy: 0.8248 Epoch 32/80 140/140 [==============================] - 35s 246ms/step - loss: 0.3975 - accuracy: 0.8532 - val_loss: 0.4975 - val_accuracy: 0.8237 Epoch 33/80 140/140 [==============================] - 36s 248ms/step - loss: 0.3939 - accuracy: 0.8624 - val_loss: 0.4931 - val_accuracy: 0.8285 Epoch 34/80 140/140 [==============================] - 35s 243ms/step - loss: 0.3915 - accuracy: 0.8597 - val_loss: 0.4893 - val_accuracy: 0.8222 Epoch 35/80 140/140 [==============================] - 36s 245ms/step - loss: 0.3895 - accuracy: 0.8584 - val_loss: 0.5034 - val_accuracy: 0.8154 Epoch 36/80 140/140 [==============================] - 36s 250ms/step - loss: 0.3789 - accuracy: 0.8687 - val_loss: 0.5203 - val_accuracy: 0.8075 Epoch 37/80 140/140 [==============================] - 34s 240ms/step - loss: 0.3770 - accuracy: 0.8669 - val_loss: 0.4891 - val_accuracy: 0.8253 Epoch 38/80 140/140 [==============================] - 36s 247ms/step - loss: 0.3764 - accuracy: 0.8644 - val_loss: 0.4931 - val_accuracy: 0.8232 Epoch 39/80 140/140 [==============================] - 35s 243ms/step - loss: 0.3739 - accuracy: 0.8671 - val_loss: 0.4883 - val_accuracy: 0.8248 Epoch 40/80 140/140 [==============================] - 34s 238ms/step - loss: 0.3686 - accuracy: 0.8707 - val_loss: 0.5011 - val_accuracy: 0.8222 Epoch 41/80 140/140 [==============================] - 34s 239ms/step - loss: 0.3616 - accuracy: 0.8750 - val_loss: 0.4890 - val_accuracy: 0.8300 Epoch 42/80 140/140 [==============================] - 35s 244ms/step - loss: 0.3577 - accuracy: 0.8721 - val_loss: 0.4674 - val_accuracy: 0.8332 Epoch 43/80 140/140 [==============================] - 35s 241ms/step - loss: 0.3538 - accuracy: 0.8792 - val_loss: 0.4744 - val_accuracy: 0.8321 Epoch 44/80 140/140 [==============================] - 35s 244ms/step - loss: 0.3509 - accuracy: 0.8806 - val_loss: 0.4856 - val_accuracy: 0.8285 Epoch 45/80 140/140 [==============================] - 36s 250ms/step - loss: 0.3555 - accuracy: 0.8754 - val_loss: 0.4881 - val_accuracy: 0.8227 Epoch 46/80 140/140 [==============================] - 36s 249ms/step - loss: 0.3502 - accuracy: 0.8790 - val_loss: 0.4835 - val_accuracy: 0.8358 Epoch 47/80 140/140 [==============================] - 34s 240ms/step - loss: 0.3463 - accuracy: 0.8806 - val_loss: 0.4675 - val_accuracy: 0.8410 Epoch 48/80 140/140 [==============================] - 36s 249ms/step - loss: 0.3389 - accuracy: 0.8806 - val_loss: 0.4813 - val_accuracy: 0.8373 Epoch 49/80 140/140 [==============================] - 34s 237ms/step - loss: 0.3465 - accuracy: 0.8808 - val_loss: 0.4679 - val_accuracy: 0.8415 Epoch 50/80 140/140 [==============================] - 39s 269ms/step - loss: 0.3481 - accuracy: 0.8752 - val_loss: 0.4673 - val_accuracy: 0.8394 Epoch 51/80 140/140 [==============================] - 36s 250ms/step - loss: 0.3343 - accuracy: 0.8844 - val_loss: 0.4704 - val_accuracy: 0.8347 Epoch 52/80 140/140 [==============================] - 36s 252ms/step - loss: 0.3380 - accuracy: 0.8848 - val_loss: 0.4633 - val_accuracy: 0.8426 Epoch 53/80 140/140 [==============================] - 36s 245ms/step - loss: 0.3380 - accuracy: 0.8886 - val_loss: 0.4747 - val_accuracy: 0.8353 Epoch 54/80 140/140 [==============================] - 36s 247ms/step - loss: 0.3327 - accuracy: 0.8866 - val_loss: 0.4745 - val_accuracy: 0.8353 Epoch 55/80 140/140 [==============================] - 38s 269ms/step - loss: 0.3261 - accuracy: 0.8884 - val_loss: 0.4759 - val_accuracy: 0.8332 Epoch 56/80 140/140 [==============================] - 38s 269ms/step - loss: 0.3206 - accuracy: 0.8976 - val_loss: 0.4724 - val_accuracy: 0.8358 Epoch 57/80 140/140 [==============================] - 35s 243ms/step - loss: 0.3198 - accuracy: 0.8940 - val_loss: 0.4770 - val_accuracy: 0.8337 Epoch 58/80 140/140 [==============================] - 36s 245ms/step - loss: 0.3214 - accuracy: 0.8893 - val_loss: 0.4731 - val_accuracy: 0.8373 Epoch 59/80 140/140 [==============================] - 35s 243ms/step - loss: 0.3189 - accuracy: 0.8884 - val_loss: 0.4661 - val_accuracy: 0.8452 Epoch 60/80 140/140 [==============================] - 34s 240ms/step - loss: 0.3181 - accuracy: 0.8978 - val_loss: 0.4677 - val_accuracy: 0.8337 Epoch 61/80 140/140 [==============================] - 36s 252ms/step - loss: 0.3250 - accuracy: 0.8882 - val_loss: 0.4635 - val_accuracy: 0.8379 Epoch 62/80 140/140 [==============================] - 34s 239ms/step - loss: 0.3121 - accuracy: 0.8942 - val_loss: 0.4678 - val_accuracy: 0.8368
# Visualization of the learning curves
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.ylim([0.0, 2.0])
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend(['train', 'valid'])
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.ylim([0.5, 1.0])
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(['train', 'valid'])
<matplotlib.legend.Legend at 0x7a82c46f8340>
net.save("/content/gdrive/MyDrive/Deep Learning Project/Segmentedv5.keras")
net.evaluate(test_ds)
6/6 [==============================] - 372s 64s/step - loss: 0.5476 - accuracy: 0.8079
[0.5475756525993347, 0.807901918888092]
net.evaluate(test_ds_cropped)
21/21 [==============================] - 1202s 57s/step - loss: 0.5768 - accuracy: 0.8108
[0.5767860412597656, 0.810800313949585]
net.evaluate(test_ds_cropped_balanced)
6/6 [==============================] - 302s 50s/step - loss: 0.4618 - accuracy: 0.8306
[0.4618443548679352, 0.8306010961532593]
None of the three accuracy resulted to be higher than the test accuracy we achieved with the same model applied to unsegmented data (84.74%). Also, the balancing of the dataset did not seem to increase the performance of the model, since the performances decreased on all the test sets.
The model that achieved the best performances remains the one we trained on the unsegmented data. Neither segmentation nor balancing the dataset were able to increase the performances on the test set.