Home > database >  Test accuracy not increasing more than 45%
Test accuracy not increasing more than 45%

Time:04-03

Im trying to build a CONV2D network for image classification. I have generated my own dataset by scraping images for 9 classes airplanes, animals, birds, cars, flowers, people, ships, traffic_signs, trains. The images are of resolution 612 x 400 plus (400 varies between 430 and 480). I have resized the images to 100x100 for convenience of system resources. I have designed the network and training accuracy is more than 90% but the test accuracy isn't increasing more than 45%.

Any idea what im doing wrong?

  • Total images in each class - 500
  • Total images - 4479
  • resolution - 612 x 400plus (varies between 400 & 440).

Below is the code

import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import PIL
import tensorflow as tf
import pathlib
import requests
import urllib
import time

from bs4 import BeautifulSoup
from tensorflow import keras

from tensorflow.keras.models import *
from tensorflow.keras.layers import *
from keras.optimizers import *
from keras.losses import sparse_categorical_crossentropy

data_dir = pathlib.Path('D:/mixed images')
data_dir

len(list(data_dir.glob('*/*.jpg')))

# planes = list(data_dir.glob('airplanes/*.jpg'))

# PIL.Image.open(planes[10])

img_list = [list(data_dir.glob('airplanes/*')),
            list(data_dir.glob('animals/*')),
            list(data_dir.glob('birds/*')),
            list(data_dir.glob('cars/*')),
            list(data_dir.glob('flowers/*')),
            list(data_dir.glob('people/*')),
            list(data_dir.glob('ships/*')),
            list(data_dir.glob('traffic_signs/*')),
            list(data_dir.glob('trains/*'))]

obj_list = os.listdir(data_dir)

obj_img_dict = dict(zip(obj_list,img_list))

obj_label_dict = dict(zip(obj_list,[0,1,2,3,4,5,6,7,8]))
obj_label_dict

X = []
y = []

for image_name,images in obj_img_dict.items():
    for image in images:
        img = cv2.imread(str(image))
        resized_img = cv2.resize(img,(100,100))
        X.append(resized_img)
        y.append(obj_label_dict[image_name])

X = np.array(X)
y = np.array(y)

from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.3,random_state=42)

X_train_scaled = X_train/255
X_test_scaled = X_test/255

obj_classes = 9

model = keras.Sequential()
        
# building the convolution layers
model.add(keras.layers.Conv2D(32,(3,3),input_shape= (100,100,3),padding='same',activation='relu'))
model.add(keras.layers.MaxPooling2D(pool_size=(2,2)))
model.add(keras.layers.Conv2D(64,(3,3), padding='same',activation='relu'))
model.add(keras.layers.MaxPooling2D(pool_size=(2,2)))
model.add(keras.layers.Conv2D(128,(3,3), padding='same',activation='relu'))
model.add(keras.layers.MaxPooling2D(pool_size=(2,2)))
model.add(keras.layers.Conv2D(256,(3,3), padding='same',activation='relu'))
model.add(keras.layers.MaxPooling2D(pool_size=(2,2)))
model.add(keras.layers.Conv2D(512,(3,3), padding='same',activation='relu'))
model.add(keras.layers.MaxPooling2D(pool_size=(2,2)))
model.add(keras.layers.Flatten())
    
# building the dense layers
model.add(keras.layers.Dense(1024, activation='relu'))
model.add(Dropout(0.5))
model.add(keras.layers.Dense(512, activation='relu'))
model.add(Dropout(0.5))
model.add(keras.layers.Dense(256, activation='relu'))
# model.add(Dropout(0.6))
model.add(keras.layers.Dense(128, activation='relu'))
# model.add(Dropout(0.6))
model.add(keras.layers.Dense(64, activation='relu'))
model.add(keras.layers.Dense(obj_classes,activation='softmax'))

model.compile(loss='sparse_categorical_crossentropy',
              optimizer='adam', metrics=['accuracy'])


model.fit(X_train_scaled, y_train, batch_size=64,epochs=50, verbose=2)

model.evaluate(X_test_scaled,y_test)

CodePudding user response:

Try making the following modifications to the model:

  • reducing the number of parameters, in order not to under-fit
  • spreading the number of parameters from layer to layer as evenly as possible
  • using batch normalization between convolutions
  • using only 3 dense layers in the end
  • having a ratio of almost 50/50 in the number of parameters between convolutions and final dense layers

A good candidate model would be:

model = keras.Sequential()
# building the convolution layers
model.add(keras.layers.Conv2D(32,(3,3),input_shape= (100,100,3),padding='same',activation='relu'))
model.add(keras.layers.MaxPooling2D(pool_size=(2,2)))
model.add(keras.layers.BatchNormalization())
model.add(keras.layers.Conv2D(32,(3,3), padding='same',activation='relu'))
model.add(keras.layers.MaxPooling2D(pool_size=(2,2)))
model.add(keras.layers.BatchNormalization())
model.add(keras.layers.Conv2D(64,(3,3), padding='same',activation='relu'))
model.add(keras.layers.MaxPooling2D(pool_size=(2,2)))
model.add(keras.layers.BatchNormalization())
model.add(keras.layers.Conv2D(64,(3,3), padding='same',activation='relu'))
model.add(keras.layers.MaxPooling2D(pool_size=(2,2)))
model.add(keras.layers.BatchNormalization())
model.add(keras.layers.Conv2D(128,(3,3), padding='same',activation='relu'))
model.add(keras.layers.MaxPooling2D(pool_size=(2,2)))
model.add(keras.layers.BatchNormalization())
model.add(keras.layers.Flatten())
    
# building the dense layers
model.add(keras.layers.Dense(256, activation='relu'))
model.add(Dropout(0.5))
model.add(keras.layers.Dense(128, activation='relu'))
# model.add(Dropout(0.5)) # optional
model.add(keras.layers.Dense(64, activation='relu'))
model.add(keras.layers.Dense(obj_classes,activation='softmax'))

model.compile(loss='sparse_categorical_crossentropy',
              optimizer='adam', metrics=['accuracy'])
  • Related