OlafenwaMoses / ImageAI

A python library built to empower developers to build applications and systems with self-contained Computer Vision capabilities
https://www.genxr.co/#products
MIT License
8.62k stars 2.19k forks source link

Custom image prediction always predicts the same class #670

Open AsifGhaffar2220 opened 3 years ago

AsifGhaffar2220 commented 3 years ago

I'm trying to implement a custom image prediction that classifies images into one of the two discrete categories, I trained model. The problem is, however, that it currently always predicts same class for any input and I'm not really sure why.

ekesdf commented 3 years ago

Can you send you code that you used for training and prediction thy

AsifGhaffar2220 commented 3 years ago

Here is code for training, that I used:

from imageai.Classification.Custom import ClassificationModelTrainer

model_trainer = ClassificationModelTrainer()

model_trainer.setModelTypeAsResNet50() model_trainer.setDataDirectory("v_data") model_trainer.trainModel(num_objects=2, num_experiments=100, enhance_data=True, batch_size=32, show_network_summary=True)

Here is code for prediction, that I used:

from imageai.Classification.Custom import CustomImageClassification

prediction = CustomImageClassification()

model_path = "./v_data/models/model_ex-001_acc-0.522500.h5" json_path = "./v_data/json/model_class.json" input_path = "./v_data/test/cars/1.jpg"

prediction.setModelTypeAsResNet50() prediction.setModelPath(model_path) prediction.setJsonPath(json_path) prediction.loadModel(num_objects=2)

predictions, probabilities = prediction.classifyImage(input_path, result_count=2)

for eachPrediction, eachProbability in zip(predictions, probabilities): print(eachPrediction , " : " , eachProbability)

I will use different num_experiments some times but not same result

AsifGhaffar2220 commented 3 years ago

I will use different num_experiments some times but always same result

ekesdf commented 3 years ago

You code you used looks fine :)

I think that your dataset might be the problem bc it seems like you have only two items in your dataset like objects A and B. How big is the amount of images for class A and how big for class B? If they're very different like 2000 A and 500 B I do not doubt why it just detects one class bc you trained to do a coin flip is it A or B. The only problem is that due to the unbalanced dataset the probabilities of getting head or tail are not 50-50 they are more like 500-1 for example and that little chance is so rare that you model always goes for one class then the other bc image ai goes for the class with the highest score.

short version

More training images = higher score Less training images = lower score

Unbalanced dataset (500xA and 50xB)= one class preferred

Balanced dataset (500xA and 500xB) = all classes the same probability to get right detected

AsifGhaffar2220 commented 3 years ago

Ok thanks, I will look about it, then inform about result.

AsifGhaffar2220 commented 3 years ago

In my dataset every class contains 200 for training and 50 for testing

ekesdf commented 3 years ago

And you have 2 classes ?

AsifGhaffar2220 commented 3 years ago

yes

ekesdf commented 3 years ago

And do you get the same class for each image ??

AsifGhaffar2220 commented 3 years ago

yes

ekesdf commented 3 years ago

Do you check what score you're predictions get ?

AsifGhaffar2220 commented 3 years ago

I am training model again, So I will inform you about score.

In previous predication every time 100 score and same class.

AsifGhaffar2220 commented 3 years ago

Same result again

ekesdf commented 3 years ago

train.txt use this model it will work for sure this file is for

predict.txt this file is for the actual prediction

run those files as a python script by replacing .txt with .py

your dataset folder should look like this

Dataset

|-- Class A .... |-- image1 .....|-- imagexyz

|-- Class B .... |-- image1 .....|-- imagexyz

(the actual image name doesn't matter bc the folder there in stands for the class they belong to)

robertoaran79 commented 3 years ago

Hi,

I had the same issue, i tried the example idenprof, but after running with ResNet50 amd DenseNet121 the problem is the same.

Here is the train code: from imageai.Classification.Custom import ClassificationModelTrainer

model_trainer = ClassificationModelTrainer() model_trainer.setModelTypeAsDenseNet121() model_trainer.setDataDirectory("idenprof") model_trainer.trainModel(num_objects=10, num_experiments=15, enhance_data=True, batch_size=32, show_network_summary=True)

Here is de classify code: from imageai.Classification.Custom import CustomImageClassification import os

execution_path = os.getcwd()

prediction = CustomImageClassification() prediction.setModelTypeAsDenseNet121() prediction.setModelPath("model_ex-076_acc-0.999108.h5") prediction.setJsonPath("model_class.json") prediction.loadModel(num_objects=10)

predictions, probabilities = prediction.classifyImage("image.jpg", result_count=10)

for eachPrediction, eachProbability in zip(predictions, probabilities): print(eachPrediction , " : " , eachProbability)

Doesn't matter the image i use the result always related to police class: police : 99.76385831832886 engineer : 0.23614077363163233 firefighter : 5.706436625313449e-10 waiter : 7.887313984442437e-12 pilot : 3.6265207416924516e-13 farmer : 1.3212530248623297e-13 doctor : 7.946953637786084e-14 chef : 8.109176277871243e-19 mechanic : 6.302315649809356e-27 judge : 3.379923151490309e-31

I tried the code suggested Above with some adaption:

Train import matplotlib.pyplot as plt import tensorflow as tf from tensorflow.keras import layers from tensorflow.keras.models import Sequential from time import time

start = time()

data_dir = "idenprof/train" batch_size = 32 img_height = 244 img_width = 244

train_ds = tf.keras.preprocessing.image_dataset_from_directory( data_dir, validation_split=0.3, subset="training", seed=123, image_size=(img_height, img_width), batch_size=batch_size)

class_names = train_ds.class_names

val_ds = tf.keras.preprocessing.image_dataset_from_directory( data_dir, validation_split=0.3, subset="validation", seed=123, image_size=(img_height, img_width), batch_size=batch_size)

AUTOTUNE = tf.data.AUTOTUNE

train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE) val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)

num_classes = len(class_names)

model = Sequential([ layers.experimental.preprocessing.Rescaling(1./255), layers.Conv2D(32, 3, padding='same', activation='relu'), layers.MaxPooling2D(), layers.Conv2D(64, 3, padding='same', activation='gelu'), layers.MaxPooling2D(), layers.Conv2D(128, 3, padding='same', activation='relu'), layers.MaxPooling2D(), layers.Dropout(0.3), layers.Flatten(), layers.Dense(256, activation='relu'), layers.Dense(num_classes) ])

model.compile(optimizer='sgd', loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), metrics=['accuracy'])

epochs=25 history = model.fit(train_ds,validation_data=val_ds,epochs=epochs) model.summary() acc = history.history['accuracy'] val_acc = history.history['val_accuracy']

loss = history.history['loss'] val_loss = history.history['val_loss']

epochs_range = range(epochs)

plt.figure(figsize=(8, 8)) plt.subplot(1, 2, 1) plt.plot(epochs_range, acc, label='Training Accuracy') plt.plot(epochs_range, val_acc, label='Validation Accuracy') plt.legend(loc='lower right') plt.title('Training and Validation Accuracy')

plt.subplot(1, 2, 2) plt.plot(epochs_range, loss, label='Training Loss') plt.plot(epochs_range, val_loss, label='Validation Loss') plt.legend(loc='upper right') plt.title('Training and Validation Loss') print(f"Trained Model in {(time()-start)/60} minutes") plt.show()

model.save("models")

Classify:

import numpy as np from tensorflow import keras import tensorflow as tf from PIL import Image from tqdm import tqdm import os

image_path = "image.jpg"

class_names = sorted(os.listdir("idenprof/train")) reconstructed_model = keras.models.load_model("models")

img = np.asarray(Image.open(image_path).resize((244, 244), Image.NEAREST)) img = np.reshape(img, (1, 244, 244, 3))

predictions = reconstructed_model.predict(img) score = tf.nn.softmax(predictions[0]) label = class_names[np.argmax(score)][0]

for class_name_prt, score_prt in zip(class_names, predictions[0]): print(class_name_prt , " : " , score_prt)

In this case, the high score is related to image, but is very low all the time: import numpy as np from tensorflow import keras import tensorflow as tf from PIL import Image from tqdm import tqdm import os

image_path = "image.jpg"

class_names = sorted(os.listdir("idenprof/train")) reconstructed_model = keras.models.load_model("models")

img = np.asarray(Image.open(image_path).resize((244, 244), Image.NEAREST)) img = np.reshape(img, (1, 244, 244, 3))

predictions = reconstructed_model.predict(img) score = tf.nn.softmax(predictions[0]) label = class_names[np.argmax(score)][0]

for class_name_prt, score_prt in zip(class_names, predictions[0]): print(class_name_prt , " : " , score_prt)