1
$\begingroup$

I made an image classifier of 80 classes of handwritten numbers then I tested my model and it worked pretty fine, the only problem that I have now is the display of the correct names of these classes.
Dataset: 2 folders: [Train Folder===> 80 folders each has 110 images, Validation folder===> 80 folders each has 22 images]

Bellow the code I used for training, saving and testing my model:

from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras import backend as K


# dimensions of our images.
img_width, img_height = 251, 54
#img_width, img_height = 150, 33

train_data_dir = 'C:/Users/ADEM/Desktop/msi_youssef/PFE/test/numbers/data/train'
validation_data_dir = 'C:/Users/ADEM/Desktop/msi_youssef/PFE/test/numbers/data/valid'
nb_train_samples = 8800 #10435
nb_validation_samples = 1763 #2051
epochs = 30 #20 # how much time you want to train your model on the data
batch_size = 32 #16

if K.image_data_format() == 'channels_first':
    input_shape = (3, img_width, img_height)
else:
    input_shape = (img_width, img_height, 3)

model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=input_shape))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Conv2D(32, (3, 3)))
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(64))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(80)) #1
model.add(Activation('softmax')) #sigmoid

model.compile(loss='sparse_categorical_crossentropy',optimizer='rmsprop',metrics=['accuracy'])#categorical_crossentropy #binary_crossentropy

# this is the augmentation configuration we will use for training
train_datagen = ImageDataGenerator(
    rescale=1. / 255,
    shear_range=0.1,
    zoom_range=0.05,
    horizontal_flip=False)

# this is the augmentation configuration we will use for testing:
# only rescaling
test_datagen = ImageDataGenerator(rescale=1. / 255)

train_generator = train_datagen.flow_from_directory(
    train_data_dir,
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode='binary')

validation_generator = test_datagen.flow_from_directory(
    validation_data_dir,
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode='binary')

model.fit_generator(
    train_generator,
    steps_per_epoch=nb_train_samples // batch_size,
    epochs=epochs,
    validation_data=validation_generator,
    validation_steps=nb_validation_samples // batch_size)

model.save('testX_2.h5') #first_try  

last epoche resulat

Epoch 30/30
275/275 [==============================] - 38s 137ms/step - loss: 0.9406 - acc: 0.7562 - val_loss: 0.1268 - val_acc: 0.9688  

how I tested my model:

from keras.models import load_model
from keras.preprocessing import image
import matplotlib.pyplot as plt
import numpy as np
import os

#result = [10,7]

def load_image(img_path, show=False):

    img = image.load_img(img_path, target_size=(251, 54))

    img_tensor = image.img_to_array(img)                    
    img_tensor = np.expand_dims(img_tensor, axis=0)         
    img_tensor /= 255.                                      

    if show:
        plt.imshow(img_tensor[0])                           
        plt.axis('off')
        plt.show()

    return img_tensor


if __name__ == "__main__":

    # load model
    model = load_model('C:/Users/ADEM/Desktop/msi_youssef/PFE/other_shit/testX_2.h5')

    # image path
    img_path = 'C:/Users/ADEM/Desktop/msi_youssef/PFE/dataset/1.75/eeza.png'   


    # load a single image
    new_image = load_image(img_path)

    # check prediction
    pred = model.predict_classes(new_image)
    print(pred)

it gives me this result instead of given the name of folder:

[7] 
$\endgroup$

1 Answer 1

0
$\begingroup$

I get your problem, the point is that its correct what the model does, but you have to build a look-up table for its answer. Your ground-truth, looks somethink like that [0,0,0,0,1], a one-hot vector for example. You, the human know what this code stands for, for example cats. just like that you have to build an numpy array, listing the word-embeddings in the correct order and afterwards calling it like: class_names[prediction],prediction being your CNN-result ->[7].

To sum it up, the Dense-layer in the end is giving you with softmax-activation a propability desnity function P. You are using this in comparing it with your ground-truth desnity function q, and calculate the difference. You just use numbers, not words, so you have to write an interpretation of the models answeres, for example in form of a lookup-table.

An example could be like:

pred = model.predict_classes(new_image)
labels=np.array(["cats","dogs","cars","humans"])
print(labels[pred[0]])

-> >>> cats
$\endgroup$
2
  • $\begingroup$ if I Understand well, i need to make 80 classes by my self :o ? $\endgroup$ Commented Mar 30, 2020 at 11:33
  • $\begingroup$ I think its quite easy and fast done, maybe you already have a list, or a register like the name of the fodlers with the images, which you can transform into an array for example. With names= next(os.walk(path_of_folders))[2] you can scan a folder for all the elements in there and get the names of them. For more: os_walk $\endgroup$ Commented Mar 30, 2020 at 11:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.