0

Here is my training code:

def train():


#START

img_input = layers.Input(shape=(150, 150, 3))

x = layers.Conv2D(16, 3, activation='relu')(img_input)
x = layers.MaxPooling2D(2)(x)

x = layers.Conv2D(32, 3, activation='relu')(x)
x = layers.MaxPooling2D(2)(x)

x = layers.Conv2D(64, 3, activation='relu')(x)
x = layers.MaxPooling2D(2)(x)

x = layers.Flatten()(x)
x = layers.Dense(512, activation='relu')(x)


output = layers.Dense(1, activation='sigmoid')(x)

model = Model(img_input, output)

model.compile(loss='binary_crossentropy',
          optimizer=RMSprop(lr=0.001),
          metrics=['acc'])
 
#END

# All images will be rescaled by 1./255
train_datagen = ImageDataGenerator(rescale=1./255)
val_datagen = ImageDataGenerator(rescale=1./255)
bs = 20
# Flow training images in batches of 20 using train_datagen generator
train_generator = train_datagen.flow_from_directory(
        train_dir,  # This is the source directory for training images
        target_size=(150, 150),  # All images will be resized to 150x150
        batch_size=bs,
        # Since we use binary_crossentropy loss, we need binary labels
        class_mode='binary')

# Flow validation images in batches of 20 using val_datagen generator
validation_generator = val_datagen.flow_from_directory(
        validation_dir,
        target_size=(150, 150),
        batch_size=bs,
        class_mode='binary')
        

  history = model.fit(
  train_generator,
  steps_per_epoch=train_steps, 
  epochs=4,
  validation_data=validation_generator,
  validation_steps=val_steps,  
  verbose=1)     
  
  
  
model.save_weights("trained_weights.h5")

Here is my prediction code:

def evaluate(imgpath):
if not os.path.isfile(imgpath):
    print("No such file: {}".format(imgpath))
    sys.exit(-1)


# START
img_input = layers.Input(shape=(150, 150, 3))


x = layers.Conv2D(16, 3, activation='relu')(img_input)
x = layers.MaxPooling2D(2)(x)

x = layers.Conv2D(32, 3, activation='relu')(x)
x = layers.MaxPooling2D(2)(x)

x = layers.Conv2D(64, 3, activation='relu')(x)
x = layers.MaxPooling2D(2)(x)


x = layers.Flatten()(x)
x = layers.Dense(512, activation='relu')(x)

output = layers.Dense(1, activation='sigmoid')(x)

model = Model(img_input, output)

model.compile(loss='binary_crossentropy',
          optimizer=RMSprop(lr=0.001),
          metrics=['acc'])
 
# END

model.load_weights("trained_weights.h5")

img = image.load_img(path=imgpath,grayscale=False,target_size=(150,150),color_mode='rgb')
img_arr = image.img_to_array(img)
test_img = np.expand_dims(img_arr, axis=0)
y_prob = model.predict(test_img)


classname = y_prob.argmax(axis=-1)
print("Class: ",classname)
return classname  

I have a feeling that the error is somewhere in the last 5-6 lines of the evaluate function, where I am loading the image. The problem is that whenever I run the evaluate function for any image, my output is [0]. Even though the training went well, as seen in the image below.
enter image description here

Am I making some silly mistake somewhere?

sriramcu
  • 27
  • 5
  • 2
    Your mistake is at `classname = y_prob.argmax(axis=-1)`. I think, [that](https://stackoverflow.com/questions/66356195/confusion-matrix-giving-bad-results-but-validation-accuracy-95/66356667#66356667) should answer your question. – Frightera Feb 28 '21 at 11:23
  • 1
    There is also the problem that you are not normalizing your new images, see the rescale=1.0/255.0 that you use in your generator. – Dr. Snoopy Feb 28 '21 at 12:28
  • test_img = np.expand_dims(img_arr, axis=0)/255 – Gerry P Feb 28 '21 at 23:42

1 Answers1

0

since you have a single neuron as the top layer, when you do predictions you will get a single prediction. Since you have a single prediction using argmax will always return 0. What you need to do is to set a threshold value for the prediction for example

if yprob>=.5:
    klass=1 
else:
    klass=0

Also as pointed out by Dr. Snoopy you should rescale your image by 1/255.

Gerry P
  • 7,662
  • 3
  • 10
  • 20
  • Okay, I forgot that argmax returns index and not value. But, when I printed y_prob, the result was always [[1.]] or [[0.]] and never anything in between, even when I considered some random pictures unrelated to my classification model. "you should rescale your image by 1/255"- In the predict() function? Where do I do this? – sriramcu Feb 28 '21 at 16:37