Why my IoU keep decrease in training with tensorflow / keras? - tensorflow

I'm training an U-net like model for semantic segmentation but the IoU keep decrease epochs after epochs.
This is my IoU and IoU loss function. My input and output mask is an numpy array with dtype=np.bool so I casted it to float32 for calculate the IoU.
I don't know what is the problem? My metrics function or my model. I really need someone help me on this.
def iou(y_true, y_pred):
y_true = tf.keras.backend.flatten(y_true)
y_pred = tf.keras.backend.flatten(y_pred)
y_true_f = tf.cast(y_true, tf.float32)
y_pred_f = tf.cast(y_pred, tf.float32)
intersection = tf.keras.backend.sum(y_true_f * y_pred_f)
union = tf.keras.backend.sum(y_true_f) + tf.keras.backend.sum(y_pred_f) - intersection
return (intersection + 1e-7) / (union + 1e-7)
def iou_loss(y_true, y_pred):
return 1.0 - iou(y_true, y_pred)
# Compile model
metrics = [iou_loss, iou, 'accuracy']
model.compile(optimizer=Adam(learning_rate), loss=iou, metrics=[metrics], run_eagerly=True)
This is my training results
Epoch 2/100
34/34 [==============================] - 3s 89ms/step - loss: 0.0186 - iou_loss: 0.9814 - iou: 0.0186 - accuracy: 0.9022 - val_loss: 0.0358 - val_iou_loss: 0.9647 - val_iou: 0.0353 - val_accuracy: 0.9460
Epoch 00002: val_loss improved from 0.03619 to 0.03579, saving model to /content/gdrive/MyDrive/model_ccnet_iris.h5
Epoch 3/100
34/34 [==============================] - 3s 89ms/step - loss: 0.0158 - iou_loss: 0.9843 - iou: 0.0157 - accuracy: 0.8972 - val_loss: 0.0352 - val_iou_loss: 0.9652 - val_iou: 0.0348 - val_accuracy: 0.9071
Epoch 00003: val_loss improved from 0.03579 to 0.03525, saving model to /content/gdrive/MyDrive/model_ccnet_iris.h5
Epoch 4/100
34/34 [==============================] - 3s 88ms/step - loss: 0.0132 - iou_loss: 0.9868 - iou: 0.0132 - accuracy: 0.8910 - val_loss: 0.0348 - val_iou_loss: 0.9656 - val_iou: 0.0344 - val_accuracy: 0.8690
Epoch 00004: val_loss improved from 0.03525 to 0.03485, saving model to /content/gdrive/MyDrive/model_ccnet_iris.h5
Epoch 5/100
34/34 [==============================] - 3s 87ms/step - loss: 0.0112 - iou_loss: 0.9888 - iou: 0.0112 - accuracy: 0.8842 - val_loss: 0.0345 - val_iou_loss: 0.9659 - val_iou: 0.0341 - val_accuracy: 0.8411
Epoch 00005: val_loss improved from 0.03485 to 0.03455, saving model to /content/gdrive/MyDrive/model_ccnet_iris.h5
Epoch 6/100
34/34 [==============================] - 3s 85ms/step - loss: 0.0096 - iou_loss: 0.9904 - iou: 0.0096 - accuracy: 0.8740 - val_loss: 0.0343 - val_iou_loss: 0.9662 - val_iou: 0.0338 - val_accuracy: 0.8216

The function of an optimizer is to minimize the loss function
You set IoU as the loss function, that is why it is decreasing.

Related

Validation loss not changing in Resnet

So I have data like in the shape of (25000, 178, 178, 3) where I have 25000 samples and each have 3 different color channel(not the RGB one), where I have around 21k samples with label 0 and rest 4k as label 1. Here's one of my sample data:
array([[[[1.79844797e-01, 1.73587397e-01, 1.73587397e-01, ...,
4.84393053e-02, 5.15680127e-02, 5.46967126e-02],
[1.76716089e-01, 1.79844797e-01, 1.82973504e-01, ...,
5.15680127e-02, 5.31323589e-02, 5.15680127e-02],
[1.81409150e-01, 1.86102197e-01, 1.81409150e-01, ...,
5.15680127e-02, 5.31323589e-02, 5.15680127e-02]]],
[[[2.51065755e+00, 2.53197193e+00, 2.53197193e+00, ...,
1.88543844e+00, 1.89964795e+00, 1.90675282e+00],
[2.51776242e+00, 2.52486706e+00, 2.53197193e+00, ...,
1.89964795e+00, 1.90675282e+00, 1.90675282e+00],
[2.53197193e+00, 2.51776242e+00, 2.52486706e+00, ...,
1.91385746e+00, 1.90675282e+00, 1.90675282e+00]]],
[[[7.13270283e+00, 7.11016369e+00, 7.13270283e+00, ...,
4.85625362e+00, 4.90133190e+00, 4.94641018e+00],
[7.08762503e+00, 7.08762503e+00, 7.08762503e+00, ...,
4.92387104e+00, 4.96894932e+00, 4.96894932e+00],
[7.08762503e+00, 7.08762503e+00, 7.06508589e+00, ...,
4.99148846e+00, 4.96894932e+00, 4.96894932e+00]]],
dtype=float32)
Now firstly I'm trying to normalize by color channel. As each color channel is completely different so I'm normalizing by color channel as follows, dara_array is my whole dataset:
def nan(index):
data_array[:, :, :, index] = (data_array[:, :, :, index] - np.min(data_array[:, :, :, index]))/(np.max(data_array[:, :, :, index]) - np.min(data_array[:, :, : ,index]))
Splitting for training, validation and testing:
rand_indices = np.random.permutation(len(data))
train_indices = rand_indices[0:19000]
valid_indices = rand_indices[19000:21000]
test_indices = rand_indices[21000:len(data)]
x_val = data_array[valid_indices, :]
y_val = EDR[[valid_indices]].astype('float')
x_train = data_array[train_indices, :]
y_train = EDR[[train_indices]].astype('float')
x_test = data_array[test_indices, :]
y_test = EDR[[test_indices]].astype('float')
Then I'm using Imagedatagenerator to fit the training data like this:
gen = ImageDataGenerator(
rotation_range=40,
zoom_range=0.2,
shear_range=0.2,
width_shift_range=0.2,
height_shift_range=0.2,
fill_mode='nearest',
horizontal_flip=True,
)
gen.fit(x_train)
Then I'm using RESNET to train the data as follows:
img_height,img_width = 178, 178
num_classes = 2
base_model = applications.resnet.ResNet101(weights= None, include_top=False, input_shape= (img_height,img_width,3))
x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dropout(0.7)(x)
predictions = Dense(1, activation= 'sigmoid')(x)
model = Model(inputs = base_model.input, outputs = predictions)
initial_learning_rate = 0.001
def lr_step_decay(epoch, lr):
drop_rate = 0.5
epochs_drop = 10.0
return initial_learning_rate * math.pow(drop_rate, math.floor(epoch/epochs_drop))
sgd = tf.keras.optimizers.SGD(lr = 0.001, momentum = 0.9, decay = 1e-6, nesterov=False)
opt_rms = optimizers.RMSprop(lr=0.001,decay=1e-6)
model.compile(loss = 'binary_crossentropy', optimizer = sgd, metrics = ['accuracy'])
history = model.fit_generator(gen.flow(x_train, y_train, batch_size = 64), 64, epochs = 30, verbose=1, validation_data=(x_val, y_val),
callbacks=[LearningRateScheduler(lr_step_decay)])
And here's how my model is training:
Epoch 1/30
64/64 [==============================] - 46s 713ms/step - loss: 0.5535 - accuracy: 0.8364 - val_loss: 6.0887 - val_accuracy: 0.8760 - lr: 0.0010
Epoch 2/30
64/64 [==============================] - 43s 671ms/step - loss: 0.4661 - accuracy: 0.8562 - val_loss: 0.6467 - val_accuracy: 0.8760 - lr: 0.0010
Epoch 3/30
64/64 [==============================] - 43s 673ms/step - loss: 0.4430 - accuracy: 0.8640 - val_loss: 0.4231 - val_accuracy: 0.8760 - lr: 0.0010
Epoch 4/30
64/64 [==============================] - 45s 699ms/step - loss: 0.4327 - accuracy: 0.8674 - val_loss: 0.3895 - val_accuracy: 0.8760 - lr: 0.0010
Epoch 5/30
64/64 [==============================] - 43s 677ms/step - loss: 0.4482 - accuracy: 0.8559 - val_loss: 0.3607 - val_accuracy: 0.8760 - lr: 0.0010
Epoch 6/30
64/64 [==============================] - 43s 678ms/step - loss: 0.3857 - accuracy: 0.8677 - val_loss: 0.4244 - val_accuracy: 0.8760 - lr: 0.0010
Epoch 7/30
64/64 [==============================] - 43s 677ms/step - loss: 0.4308 - accuracy: 0.8623 - val_loss: 0.4049 - val_accuracy: 0.8760 - lr: 0.0010
Epoch 8/30
64/64 [==============================] - 43s 677ms/step - loss: 0.3776 - accuracy: 0.8711 - val_loss: 0.3580 - val_accuracy: 0.8760 - lr: 0.0010
Epoch 9/30
64/64 [==============================] - 43s 677ms/step - loss: 0.4005 - accuracy: 0.8672 - val_loss: 0.3689 - val_accuracy: 0.8760 - lr: 0.0010
Epoch 10/30
64/64 [==============================] - 43s 676ms/step - loss: 0.3977 - accuracy: 0.8828 - val_loss: 0.3513 - val_accuracy: 0.8760 - lr: 0.0010
Epoch 11/30
64/64 [==============================] - 43s 675ms/step - loss: 0.4394 - accuracy: 0.8682 - val_loss: 0.3491 - val_accuracy: 0.8760 - lr: 5.0000e-04
Epoch 12/30
64/64 [==============================] - 43s 676ms/step - loss: 0.3702 - accuracy: 0.8779 - val_loss: 0.3676 - val_accuracy: 0.8760 - lr: 5.0000e-04
Epoch 13/30
64/64 [==============================] - 43s 678ms/step - loss: 0.3904 - accuracy: 0.8706 - val_loss: 0.3621 - val_accuracy: 0.8760 - lr: 5.0000e-04
Epoch 14/30
64/64 [==============================] - 43s 677ms/step - loss: 0.3579 - accuracy: 0.8765 - val_loss: 0.3483 - val_accuracy: 0.8760 - lr: 5.0000e-04
My validation accuracy is not changing at all, it's remaining constant. And probably it's predicting everything as 0 cause that'll be the exact accuracy of validation data if it predicts everything as 0 as per split(248 1's out of total 2k val record). Can someone tell me what I'm doing wrong here?
Sample plot of one file with 5 time dim(I'm just using 1 for training) and 1 channel from data:
Your observation is indeed correct : the network is not learning anything.
Ensure that your dataset is properly labelled + you feed your data correctly. At the same time, ask&answer the following question: is 178x178 a sufficient resolution for the "other" class that I am trying to detect? If you have already undergone those processes, proceed to the following suggestions.
I would try to start to decrease the learning rate to 0.0001 or 0.00001(although at this point the learning could converge too slowly).
At the same time could you remove the Dropout() altogether to see if your network at least is able to learn anything. At least at this point of investigation Dropout() is not needed, it actually hampers the learning due to the high dropout value used.

Binary vs Multiclass Classification using TPU

I am using an EfficientNetB7 and EfficientNetB0 model for training my dataset, and am facing a major anomaly.
EfficientNetB7 gave 96.4 percent accuracy with 40 epochs, lr_callback,4 nb_classes,imagenet weights.
GCS_DS_PATH = KaggleDatasets().get_gcs_path('plant-pathology-2020-fgvc7')
path='../input/plant-pathology-2020-fgvc7/'
train = pd.read_csv(path + 'train.csv')
test = pd.read_csv(path + 'test.csv')
sub = pd.read_csv(path + 'sample_submission.csv')
train_paths = train.image_id.apply(lambda x : GCS_DS_PATH + '/images/' + x + '.jpg').values
test_paths = test.image_id.apply(lambda x : GCS_DS_PATH + '/images/' + x + '.jpg').values
train_labels = train.loc[:,'healthy':].values.astype(int)
train_labels_healthy = train.loc[:,'healthy'].values.astype(int)
train_labels_multiple_diseases = train.loc[:,'multiple_diseases'].values.astype(int)
train_labels_rust = train.loc[:,'rust'].values.astype(int)
train_labels_scab = train.loc[:,'scab'].values.astype(int)
train_dataset = (
tf.data.Dataset
.from_tensor_slices((train_paths, train_labels))
.map(decode_image, num_parallel_calls=AUTO)
.map(data_augment, num_parallel_calls=AUTO)
.repeat()
.shuffle(512)
.batch(BATCH_SIZE)
.prefetch(AUTO)
)
train_dataset1 = (
tf.data.Dataset
.from_tensor_slices((train_paths, train_labels_healthy_one_hot))
.map(decode_image, num_parallel_calls=AUTO)
.map(data_augment, num_parallel_calls=AUTO)
.repeat()
.shuffle(512)
.batch(BATCH_SIZE)
.prefetch(AUTO)
)
nb_classes=4
def get_model():
base_model = efn.EfficientNetB7(weights='imagenet', include_top=False, pooling='avg', input_shape=(img_size, img_size, 3))
x = base_model.output
predictions = Dense(nb_classes, activation="softmax")(x)
return Model(inputs=base_model.input, outputs=predictions)
with strategy.scope():
model = get_model()
model.compile(optimizer='adam', loss='categorical_crossentropy',metrics=['accuracy'])
model.summary()
model.fit(
train_dataset,
steps_per_epoch=train_labels.shape[0] // BATCH_SIZE,
epochs=10
)
Output: Train for 28 steps
Epoch 1/10
28/28 [==============================] - 253s 9s/step - loss: 0.2862 - accuracy: 0.8951
Epoch 2/10
28/28 [==============================] - 15s 535ms/step - loss: 0.1453 - accuracy: 0.9520
Epoch 3/10
28/28 [==============================] - 34s 1s/step - loss: 0.1450 - accuracy: 0.9554
Epoch 4/10
28/28 [==============================] - 35s 1s/step - loss: 0.1271 - accuracy: 0.9587
Epoch 5/10
28/28 [==============================] - 35s 1s/step - loss: 0.0935 - accuracy: 0.9621
Epoch 6/10
28/28 [==============================] - 35s 1s/step - loss: 0.0951 - accuracy: 0.9621
Epoch 7/10
28/28 [==============================] - 35s 1s/step - loss: 0.0615 - accuracy: 0.9721
Epoch 8/10
28/28 [==============================] - 35s 1s/step - loss: 0.0674 - accuracy: 0.9833
Epoch 9/10
28/28 [==============================] - 35s 1s/step - loss: 0.0654 - accuracy: 0.9743
Epoch 10/10
28/28 [==============================] - 35s 1s/step - loss: 0.0435 - accuracy: 0.9821
So, I tried improving the accuracy by using 4 EfficientNetB0 models to predict the 4 classes independently, but the accuracy got stuck at 50 per cent. I tried varying the learning rate to see if it is stuck in a local minimum, but the accuracy is the same.
nb_classes=1
def get_model():
base_model = efn.EfficientNetB0(weights='imagenet', include_top=False, pooling='avg', input_shape=(img_size, img_size, 3))
x = base_model.output
predictions = Dense(nb_classes, activation="softmax")(x)
return Model(inputs=base_model.input, outputs=predictions)
adam = Adam(learning_rate=0.05) #Tried 0.0001,0.001,0.01,0.05
with strategy.scope():
model1 = get_model()
#print('1')
# model2 = get_model()
# print('2')
# model3 = get_model()
# print('3')
# model4 = get_model()
# print('4')
model1.compile(optimizer=adam, loss='binary_crossentropy',metrics=['accuracy'])
#model2.compile(optimizer='adam', loss='binary_crossentropy',metrics=['accuracy'])
#model3.compile(optimizer='adam', loss='binary_crossentropy',metrics=['accuracy'])
#model4.compile(optimizer='adam', loss='binary_crossentropy',metrics=['accuracy'])
model1.summary()
#model2.summary()
#model3.summary()
#model4.summary()
model1.fit(
train_dataset1,
steps_per_epoch=train_labels_rust.shape[0] // BATCH_SIZE,
epochs=10
)
Output: Train for 28 steps
Epoch 1/10
28/28 [==============================] - 77s 3s/step - loss: 7.6666 - accuracy: 0.5000
Epoch 2/10
28/28 [==============================] - 32s 1s/step - loss: 7.6666 - accuracy: 0.5000
Epoch 3/10
28/28 [==============================] - 33s 1s/step - loss: 7.6666 - accuracy: 0.5000
Epoch 4/10
28/28 [==============================] - 33s 1s/step - loss: 7.6666 - accuracy: 0.5000
Epoch 5/10
28/28 [==============================] - 33s 1s/step - loss: 7.6666 - accuracy: 0.5000
Epoch 6/10
28/28 [==============================] - 33s 1s/step - loss: 7.6666 - accuracy: 0.5000
Epoch 7/10
28/28 [==============================] - 33s 1s/step - loss: 7.6666 - accuracy: 0.5000
Epoch 8/10
28/28 [==============================] - 33s 1s/step - loss: 7.6666 - accuracy: 0.5000
Epoch 9/10
28/28 [==============================] - 33s 1s/step - loss: 7.6666 - accuracy: 0.5000
Epoch 10/10
28/28 [==============================] - 34s 1s/step - loss: 7.6666 - accuracy: 0.5000
I also tried other Neural Networks like ResNet50, but the accuracy remained stuck at 50 per cent. Can anyone please tell me where I am committing the mistake.
TO predict more than 2 classes use loss as 'categorical_crossentropy' or 'sparse_categorical_crossentropy' with activation as softmax

Fine tuning in CNN using Tensor Flow - 2.0

I am currently working defect classification problem in solar panel. It's a multi class classification problem. Currently its 3 class. I have done the coding part but my accuracy is very low. How to improve my accuracy?
Total training images - 900
Testing/validation - 300
Class - 3
My code is given below -
import tensorflow as tf
import keras_preprocessing
from keras_preprocessing import image
from keras_preprocessing.image import ImageDataGenerator
TRAINING_DIR = "/content/drive/My Drive/solar_images/solar_images/train/"
training_datagen = ImageDataGenerator(
rescale = 1./255,
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest')
VALIDATION_DIR = "/content/drive/My Drive/solar_images/solar_images/test/"
validation_datagen = ImageDataGenerator(rescale = 1./255)
train_generator = training_datagen.flow_from_directory(
TRAINING_DIR,
target_size=(150,150),
class_mode='categorical',
batch_size=64
)
validation_generator = validation_datagen.flow_from_directory(
VALIDATION_DIR,
target_size=(150,150),
class_mode='categorical',
batch_size=64
)
model = tf.keras.models.Sequential([
# Note the input shape is the desired size of the image 150x150 with 3 bytes color
# This is the first convolution
tf.keras.layers.Conv2D(64, (3,3), activation='relu', input_shape=(150, 150, 3)),
tf.keras.layers.MaxPooling2D(2, 2),
# The second convolution
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
# The third convolution
tf.keras.layers.Conv2D(128, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
# The fourth convolution
tf.keras.layers.Conv2D(128, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
# Flatten the results to feed into a DNN
tf.keras.layers.Flatten(),
tf.keras.layers.Dropout(0.5),
# 512 neuron hidden layer
tf.keras.layers.Dense(512, activation='relu'),
tf.keras.layers.Dense(3, activation='softmax')
])
model.summary()
model.compile(loss = 'categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy'])
batch_size=64
history = model.fit(train_generator,
epochs=20,
steps_per_epoch=int(894/batch_size),
validation_data = validation_generator,
verbose = 1,
validation_steps=int(289/batch_size))
model.save("solar_images_weight.h5")
My accuracy is -
Epoch 1/20
13/13 [==============================] - 1107s 85s/step - loss: 1.2893 - accuracy: 0.3470 - val_loss: 1.0926 - val_accuracy: 0.3594
Epoch 2/20
13/13 [==============================] - 1239s 95s/step - loss: 1.1037 - accuracy: 0.3566 - val_loss: 1.0954 - val_accuracy: 0.3125
Epoch 3/20
13/13 [==============================] - 1203s 93s/step - loss: 1.0964 - accuracy: 0.3904 - val_loss: 1.0841 - val_accuracy: 0.5625
Epoch 4/20
13/13 [==============================] - 1182s 91s/step - loss: 1.0980 - accuracy: 0.3750 - val_loss: 1.0894 - val_accuracy: 0.3633
Epoch 5/20
13/13 [==============================] - 1218s 94s/step - loss: 1.1086 - accuracy: 0.3386 - val_loss: 1.0874 - val_accuracy: 0.3125
Epoch 6/20
13/13 [==============================] - 1214s 93s/step - loss: 1.0953 - accuracy: 0.3257 - val_loss: 1.0763 - val_accuracy: 0.6094
Epoch 7/20
13/13 [==============================] - 1136s 87s/step - loss: 1.0851 - accuracy: 0.3831 - val_loss: 1.0754 - val_accuracy: 0.3164
Epoch 8/20
13/13 [==============================] - 1170s 90s/step - loss: 1.1005 - accuracy: 0.3940 - val_loss: 1.0545 - val_accuracy: 0.5039
Epoch 9/20
13/13 [==============================] - 1138s 88s/step - loss: 1.1294 - accuracy: 0.4337 - val_loss: 1.0130 - val_accuracy: 0.5703
Epoch 10/20
13/13 [==============================] - 1131s 87s/step - loss: 1.0250 - accuracy: 0.4531 - val_loss: 0.8911 - val_accuracy: 0.6055
Epoch 11/20
13/13 [==============================] - 1162s 89s/step - loss: 1.0243 - accuracy: 0.4735 - val_loss: 0.9160 - val_accuracy: 0.4727
Epoch 12/20
13/13 [==============================] - 1153s 89s/step - loss: 0.9978 - accuracy: 0.4783 - val_loss: 0.7754 - val_accuracy: 0.6406
Epoch 13/20
13/13 [==============================] - 1187s 91s/step - loss: 1.0080 - accuracy: 0.4687 - val_loss: 0.7701 - val_accuracy: 0.6602
Epoch 14/20
13/13 [==============================] - 1204s 93s/step - loss: 0.9851 - accuracy: 0.5048 - val_loss: 0.7450 - val_accuracy: 0.6367
Epoch 15/20
13/13 [==============================] - 1181s 91s/step - loss: 0.9699 - accuracy: 0.4892 - val_loss: 0.7409 - val_accuracy: 0.6289
Epoch 16/20
13/13 [==============================] - 1187s 91s/step - loss: 0.8884 - accuracy: 0.5241 - val_loss: 0.7169 - val_accuracy: 0.6133
Epoch 17/20
13/13 [==============================] - 1197s 92s/step - loss: 0.9372 - accuracy: 0.5084 - val_loss: 0.7464 - val_accuracy: 0.5859
Epoch 18/20
13/13 [==============================] - 1224s 94s/step - loss: 0.9230 - accuracy: 0.5229 - val_loss: 0.9198 - val_accuracy: 0.5156
Epoch 19/20
13/13 [==============================] - 1270s 98s/step - loss: 0.9161 - accuracy: 0.5192 - val_loss: 0.6785 - val_accuracy: 0.6289
Epoch 20/20
13/13 [==============================] - 1173s 90s/step - loss: 0.8728 - accuracy: 0.5193 - val_loss: 0.6674 - val_accuracy: 0.5781
Training and validation accuracy plot is given below -
You could use transfer learning. Using a pre-trained model such as mobilenet or inception to train on your dataset. This would significantly improve your accuracy.

Validation Loss Increases every iteration

Recently I have been trying to do multi-class classification. My datasets consist of 17 image categories. Previously I was using 3 conv layers and 2 hidden layers. It resulted my model overfitting with huge validation loss around 11.0++ and my validation accuracy was very low. So I decided to decrease the conv layers by 1 and hidden layer by 1. I also have removed dropout and it still have the same problem with the validation which still overfitting, even though my training accuracy and loss are getting better.
Here is my code for prepared datasets:
import cv2
import numpy as np
import os
import pickle
import random
CATEGORIES = ["apple_pie", "baklava", "caesar_salad","donuts",
"fried_calamari", "grilled_salmon", "hamburger",
"ice_cream", "lasagna", "macaroni_and_cheese", "nachos", "omelette","pizza",
"risotto", "steak", "tiramisu", "waffles"]
DATALOC = "D:/Foods/Datasets"
IMAGE_SIZE = 50
data_training = []
def create_data_training():
for category in CATEGORIES:
path = os.path.join(DATALOC, category)
class_num = CATEGORIES.index(category)
for image in os.listdir(path):
try:
image_array = cv2.imread(os.path.join(path,image), cv2.IMREAD_GRAYSCALE)
new_image_array = cv2.resize(image_array, (IMAGE_SIZE,IMAGE_SIZE))
data_training.append([new_image_array,class_num])
except Exception as exc:
pass
create_data_training()
random.shuffle(data_training)
X = []
y = []
for features, label in data_training:
X.append(features)
y.append(label)
X = np.array(X).reshape(-1, IMAGE_SIZE, IMAGE_SIZE, 1)
y = np.array(y)
pickle_out = open("X.pickle", "wb")
pickle.dump(X, pickle_out)
pickle_out.close()
pickle_out = open("y.pickle", "wb")
pickle.dump(y, pickle_out)
pickle_out.close()
pickle_in = open("X.pickle","rb")
X = pickle.load(pickle_in)
Here is the code of my model:
import pickle
import tensorflow as tf
import time
from tensorflow.keras.models import Sequential
from tensorflow.keras.callbacks import TensorBoard
from tensorflow.keras.layers import Activation, Conv2D, Dense, Dropout, Flatten, MaxPooling2D
NAME = "Foods-Model-{}".format(int(time.time()))
tensorboard = TensorBoard(log_dir='logs\{}'.format(NAME))
X = pickle.load(open("X.pickle","rb"))
y = pickle.load(open("y.pickle","rb"))
X = X/255.0
model = Sequential()
model.add(Conv2D(32,(3,3), input_shape = X.shape[1:]))
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size =(2,2)))
model.add(Conv2D(64,(3,3)))
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size =(2,2)))
model.add(Flatten())
model.add(Dense(128))
model.add(Activation("relu"))
model.add(Dense(17))
model.add(Activation('softmax'))
model.compile(loss = "sparse_categorical_crossentropy", optimizer = "adam", metrics = ['accuracy'])
model.fit(X, y, batch_size = 16, epochs = 20 , validation_split = 0.1, callbacks = [tensorboard])
The result of the trained model:
Train on 7650 samples, validate on 850 samples
Epoch 1/20
7650/7650 [==============================] - 242s 32ms/sample - loss: 2.7826 - accuracy: 0.1024 - val_loss: 2.7018 - val_accuracy: 0.1329
Epoch 2/20
7650/7650 [==============================] - 241s 31ms/sample - loss: 2.5673 - accuracy: 0.1876 - val_loss: 2.5597 - val_accuracy: 0.2059
Epoch 3/20
7650/7650 [==============================] - 234s 31ms/sample - loss: 2.3529 - accuracy: 0.2617 - val_loss: 2.5329 - val_accuracy: 0.2153
Epoch 4/20
7650/7650 [==============================] - 233s 30ms/sample - loss: 2.0707 - accuracy: 0.3510 - val_loss: 2.6628 - val_accuracy: 0.2059
Epoch 5/20
7650/7650 [==============================] - 231s 30ms/sample - loss: 1.6960 - accuracy: 0.4753 - val_loss: 2.8143 - val_accuracy: 0.2047
Epoch 6/20
7650/7650 [==============================] - 230s 30ms/sample - loss: 1.2336 - accuracy: 0.6247 - val_loss: 3.3130 - val_accuracy: 0.1929
Epoch 7/20
7650/7650 [==============================] - 233s 30ms/sample - loss: 0.7738 - accuracy: 0.7715 - val_loss: 3.9758 - val_accuracy: 0.1776
Epoch 8/20
7650/7650 [==============================] - 231s 30ms/sample - loss: 0.4271 - accuracy: 0.8827 - val_loss: 4.7325 - val_accuracy: 0.1882
Epoch 9/20
7650/7650 [==============================] - 233s 30ms/sample - loss: 0.2080 - accuracy: 0.9519 - val_loss: 5.7198 - val_accuracy: 0.1918
Epoch 10/20
7650/7650 [==============================] - 233s 30ms/sample - loss: 0.1402 - accuracy: 0.9668 - val_loss: 6.0608 - val_accuracy: 0.1835
Epoch 11/20
7650/7650 [==============================] - 236s 31ms/sample - loss: 0.0724 - accuracy: 0.9872 - val_loss: 6.7468 - val_accuracy: 0.1753
Epoch 12/20
7650/7650 [==============================] - 232s 30ms/sample - loss: 0.0549 - accuracy: 0.9895 - val_loss: 7.4844 - val_accuracy: 0.1718
Epoch 13/20
7650/7650 [==============================] - 229s 30ms/sample - loss: 0.1541 - accuracy: 0.9591 - val_loss: 7.3335 - val_accuracy: 0.1553
Epoch 14/20
7650/7650 [==============================] - 231s 30ms/sample - loss: 0.0477 - accuracy: 0.9905 - val_loss: 7.8453 - val_accuracy: 0.1729
Epoch 15/20
7650/7650 [==============================] - 233s 30ms/sample - loss: 0.0346 - accuracy: 0.9908 - val_loss: 8.1847 - val_accuracy: 0.1753
Epoch 16/20
7650/7650 [==============================] - 231s 30ms/sample - loss: 0.0657 - accuracy: 0.9833 - val_loss: 7.8582 - val_accuracy: 0.1624
Epoch 17/20
7650/7650 [==============================] - 233s 30ms/sample - loss: 0.0555 - accuracy: 0.9830 - val_loss: 8.2578 - val_accuracy: 0.1553
Epoch 18/20
7650/7650 [==============================] - 230s 30ms/sample - loss: 0.0423 - accuracy: 0.9892 - val_loss: 8.6970 - val_accuracy: 0.1694
Epoch 19/20
7650/7650 [==============================] - 236s 31ms/sample - loss: 0.0291 - accuracy: 0.9927 - val_loss: 8.5275 - val_accuracy: 0.1882
Epoch 20/20
7650/7650 [==============================] - 234s 31ms/sample - loss: 0.0443 - accuracy: 0.9873 - val_loss: 9.2703 - val_accuracy: 0.1812
Thank You for your time. Any help and suggestion will be really appreciated.
Your model suggests early over-fitting.
Get rid of the dense layer completely and use global pooling.
model = Sequential()
model.add(Conv2D(32,(3,3), input_shape = X.shape[1:]))
model.add(Activation("relu"))
model.add(Conv2D(64,(3,3)))
model.add(Activation("relu"))
model.add(Conv2D(128,(3,3)))
model.add(Activation("relu"))
model.add(GlobalAveragePooling2D())
model.add(Dense(17))
model.add(Activation('softmax'))
model.summary()
Use SpatialDropout2D after conv layers.
ref: https://www.tensorflow.org/api_docs/python/tf/keras/layers/SpatialDropout2D
Use early stopping to get a balanced model.
Your output suggests categorical_crossentropy as a better-fit loss.

Keras VGG16 low validation accuracy

I built a very simple Convolutional Neural Network using the pre-trained VGG16.
I am using the Pokemon generation one dataset containing 10.000 images belonging to 149 different classes. I manually split the dataset, 0.7 for training and 0.3 for validation in different directories.
The problem is that I am getting high accuracy but the validation accuracy is not very high.
In the code below, there is the best configuration found, using Adam optimizer with 0.0001 of learning rate.
Can someone suggest me how I can improve the performance and avoid overfitting?
Code:
import tensorflow as tf
import numpy as np
vgg_model = tf.keras.applications.VGG16(weights='imagenet', include_top=False, input_shape = (224,224,3))
vgg_model.trainable = False
model = tf.keras.models.Sequential()
model.add(vgg_model)
model.add(tf.keras.layers.Flatten(input_shape=vgg_model.output_shape[1:]))
model.add(tf.keras.layers.Dense(256, activation='relu'))
model.add(tf.keras.layers.Dense(149, activation='softmax'))
model.compile(optimizer=tf.keras.optimizers.Adam(lr=0.0001, decay=0.0001/100), loss='categorical_crossentropy', metrics=['accuracy'])
train= tf.keras.preprocessing.image.ImageDataGenerator(rescale=1./255, shear_range=0.2, zoom_range=0.2, horizontal_flip=True)
test= tf.keras.preprocessing.image.ImageDataGenerator(rescale=1./255)
training_set = train.flow_from_directory('datasets/generation/train', target_size=(224,224), class_mode = 'categorical')
val_set = train.flow_from_directory('datasets/generation/test', target_size=(224,224), class_mode = 'categorical')
history = model.fit_generator(training_set, steps_per_epoch = 64, epochs = 100, validation_data = val_set, validation_steps = 64)
Here is the output every 10 epochs:
Epoch 1/100
64/64 [====================] - 57s 891ms/step - loss: 4.8707 - acc: 0.0654 - val_loss: 4.7281 - val_acc: 0.0718
Epoch 10/100
64/64 [====================] - 53s 821ms/step - loss: 2.9540 - acc: 0.4141 - val_loss: 3.2206 - val_acc: 0.3447
Epoch 20/100
64/64 [====================] - 56s 869ms/step - loss: 1.9040 - acc: 0.6279 - val_loss: 2.6155 - val_acc: 0.4577
Epoch 30/100
64/64 [====================] - 50s 781ms/step - loss: 1.2899 - acc: 0.7658 - val_loss: 2.3345 - val_acc: 0.4897
Epoch 40/100
64/64 [====================] - 53s 832ms/step - loss: 1.0192 - acc: 0.8096 - val_loss: 2.1765 - val_acc: 0.5149
Epoch 50/100
64/64 [====================] - 55s 854ms/step - loss: 0.7948 - acc: 0.8672 - val_loss: 2.1082 - val_acc: 0.5359
Epoch 60/100
64/64 [====================] - 52s 816ms/step - loss: 0.5774 - acc: 0.9106 - val_loss: 2.0673 - val_acc: 0.5435
Epoch 70/100
64/64 [====================] - 52s 811ms/step - loss: 0.4383 - acc: 0.9385 - val_loss: 2.0499 - val_acc: 0.5454
Epoch 80/100
64/64 [====================] - 56s 881ms/step - loss: 0.3638 - acc: 0.9473 - val_loss: 1.9849 - val_acc: 0.5501
Epoch 90/100
64/64 [====================] - 55s 860ms/step - loss: 0.2860 - acc: 0.9609 - val_loss: 1.9564 - val_acc: 0.5531
Epoch 100/100
64/64 [====================] - 52s 815ms/step - loss: 0.2328 - acc: 0.9697 - val_loss: 2.0334 - val_acc: 0.5615
As i can see in your output above you are not overfitting yet but there is a huge spread between train and validation score. There are plenty of things you can try to improve you validation score.
You could add more training data (not always possible)
heavier augmentation
tta
and add dropout layers
add a dropout layer like this:
model.add(tf.keras.layers.Dense(256, activation='relu'))
model.add(tf.keras.layers.Dropout(0.5))
model.add(tf.keras.layers.Dense(149, activation='softmax'))