Why my prediction result is very bad comparing with the accuracy - python

I write a code for image classification(2 categories, 'good'&'bad') in python using Keras, the accuracy on training data is about 99%, and on validation data is about 95%. (the image is 60 times 30 pixels grayscale png file)
img_width, img_height = 60, 30
nb_train_samples = 4000
nb_validation_samples = 600
epochs = 30
batch_size = 32
if K.image_data_format() == 'channels_first':
input_shape = (1, img_width, img_height)
else:
input_shape = (img_width, img_height, 1)
model = Sequential()
model.add(Conv2D(16, (3, 3), input_shape=input_shape,padding='same'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(32, (3, 3),padding='same'))
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(1))
model.add(Activation('sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer='rmsprop',
metrics=['binary_accuracy'])
train_datagen = ImageDataGenerator(rescale= 1. /255)
validation_datagen = ImageDataGenerator(rescale= 1. /255)
train_generator = train_datagen.flow_from_directory(
'/home/admin/Desktop/dataset/train',
target_size=(img_width, img_height),
batch_size=batch_size,
class_mode='binary',
color_mode='grayscale')
validation_generator = validation_datagen.flow_from_directory(
'/home/admin/Desktop/dataset/validation',
target_size=(img_width, img_height),
batch_size= batch_size,
class_mode='binary',
color_mode='grayscale')
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_weights('test_weights.h5')
now I want to make prediction for all the 600 images in validation directory, using this code.
path='/home/admin/Desktop/dataset/validation/good'
for file in os.listdir(path):
im=cv2.imread(os.path.join(path,file))
im=cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
im=np.reshape(im,[1, img_width,img_height,1])*(1. /255)
result=model.predict_classes(im)
However, the result for 300 images in 'bad' directory is 9[1] with 291[0], and for 300 images in 'good' directory is 42[1] with 258[0], this is obviously wrong.
I think my way for data processing is different from ImageDataGenerator and flow_from_directory, which leads to the bug, but I'm not sure.
********update********
When I use the following code, the result is correct
predict_data=ImageDataGenerator(rescale=1. / 255).flow_from_directory(
'/home/admin/Desktop/dataset/validation/good',
target_size=(img_width, img_height),
batch_size= 300,
class_mode=None,
color_mode='grayscale')
result=model.predict_generator(
predict_data,
steps=1)
But I still don't know where the bug is.

Related

Tensorflow Fused conv implementation does not support grouped convolutions

I did a neural network machine learning on colored images (3 channels). It worked but now I want to try to do it in grayscale to see if I can improve accuracy.
Here is the code:
train_datagen = ImageDataGenerator(
rescale=1. / 255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
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',
shuffle=True)
validation_generator = test_datagen.flow_from_directory(
validation_data_dir,
target_size=(img_width, img_height),
batch_size=batch_size,
color_mode='grayscale',
class_mode='binary',
shuffle=True)
model = tf.keras.Sequential()
input_shape = (img_width, img_height, 1)
model.add(Conv2D(32, 2, input_shape=input_shape, activation='relu'))
model.add(MaxPooling2D(pool_size=2))
model.add(Conv2D(32, 2, activation='relu'))
model.add(MaxPooling2D(pool_size=2))
model.add(Conv2D(64, 2, activation='relu'))
model.add(MaxPooling2D(pool_size=2))
model.add(Flatten())
model.add(Dense(128))
model.add(Dense(len(classes)))
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
history = model.fit(train_generator,
validation_data=validation_generator,
epochs=EPOCHS)
You can see that I have changed the input_shape to have 1 single channel for grayscale.
I'm getting an error:
Node: 'sequential_26/conv2d_68/Relu' Fused conv implementation does not support grouped convolutions for now. [[{{node sequential_26/conv2d_68/Relu}}]] [Op:__inference_train_function_48830]
Any idea how to fix this?
Your train_generator does not seem to have the colormode='grayscale'. Try:
train_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size=(img_width, img_height),
batch_size=batch_size,
class_mode='binary',
colormode='grayscale',
shuffle=True)
This error arises when the no. channel differs from the model. Maybe due to the input_shape, you've given a 3d shape tensor. This MAY help you.:)
input_shape = (img_width, img_height, 1)

Image Classification using keras predict same output for different classes

I have problem with my image classification model using keras.
This is the code which have binary class.
tried to set the number of images in datasets as equal.
this is a code for Keras model
train_data_dir = 'path'
validation_data_dir = 'path'
nb_train_samples = 2000
nb_validation_samples = 800
epochs = 10
batch_size = 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(1))
model.add(Activation('sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
train_datagen = ImageDataGenerator(
rescale=1. / 255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
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.load_weights('second_try.h5')
and the model saved well.
so I run the test code
from keras.models import load_model
from keras.preprocessing import image
import numpy as np
# dimensions of our images
img_width, img_height = 150, 150
# load the model we saved
model = load_model('modelpath')
model.compile(loss='binary_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
#predicting multiple images at once
img = image.load_img('imgpath', target_size=(img_width, img_height))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
y = image.img_to_array(img)
y = np.expand_dims(y, axis=0)
images = np.vstack([x, y])
classes = model.predict_classes(images, batch_size=10)
print(classes)
and both images from different classes are printed as 1.
Why does this happening?
You should be saving the model or model weights after your training, rather than doing load_weights after fit(). So, 2 ways to do this
After model.fit(), do model.save_weights('second_try.hdf5') which only saves weights. To load the weights, you should first compile your model, and then call load_weights on the model as model.load_weights('second_try.hdf5')
After model.fit(), do model.save('model.hdf5') which saves the weights and the model structure to a single HDF5 file. Then you can use that HDF5 file with load() to reconstruct the whole model, including weights.
model = load_model('model.hdf5')
Also, do check if your test data is being prepared correctly. As your training loop uses a generator to prepare the data, you should use a similar generator for preparing the test data as well.

How to predict input probability of image using trained model in Keras?

I'm beginning ML and have come to a huge road bump, looked at this thing for hours. I want to get the predict() probability as output but the predictions are only outputting [[1.]] for every test image. Using larger numbers of training data and more epochs, the acc and validation acc are up to about 90% each. This is only binary classification but I don't want predict_classes. I have no idea why it's printing [[1.]]
Here is the code I'm using:
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
img_width, img_height = 150, 150
train_data_dir = 'D:\Machine_Learning\\train'
validation_data_dir = 'D:\Machine_Learning\\test'
nb_train_samples = 20000
nb_validation_samples = 7000
epochs = 50
batch_size = 40
if K.image_data_format() == 'channels_first':
input_shape = (3, img_width, img_height)
else:
input_shape = (img_width, img_height, 3)
# Build model structure
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(1))
model.add(Activation('sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer='adam',
metrics=['accuracy'])
# Image augmentation
train_datagen = ImageDataGenerator(
rescale=1. / 255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
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('first_try.h5')
model.save_weights('my_weights.model')
And for predictions:
from keras.models import load_model
from keras.preprocessing import image
model = load_model('first_try.h5')
def prepare(image):
imageSize = 150
#imageArray = cv2.imread(filePath)
newImageArray = cv2.resize(image, (imageSize, imageSize))
return newImageArray.reshape(-1, imageSize, imageSize, 3)
for i in range(len(test_images)):
print(test_images[i])
im = prepare(test_images[i])
prediction = model.predict([im])
print(prediction)

Fully connected layer output ValueError

I am working on a glaucoma detection CNN and I'm getting the following error
ValueError: Error when checking target: expected activation_1 to have shape (2,) but got array with shape (1,) for any other number at the final Dense layer except 1. Since the number of classifications is 2, I need to give Dense(2) before the activation function. But whenever I run the code with Dense(1), I get a good accuracy but during testing, everything is predicted to be from the same class. How do I solve this error without changing my Dense layer back to Dense(1)
This is the code:
img_width, img_height = 256, 256
input_shape = (img_width, img_height, 3)
train_data_dir = "data/train"
validation_data_dir = "data/validation"
nb_train_samples = 500
nb_validation_samples = 50
batch_size = 10
epochs = 10
model = Sequential()
model.add(Conv2D(3, (11, 11), activation='relu', input_shape=input_shape))
model.add(MaxPooling2D(pool_size=(3, 3), strides=(2, 2)))
model.add(Conv2D(96, (5, 5), activation='relu'))
model.add(MaxPooling2D(pool_size=(3, 3), strides=(2, 2)))
model.add(Dropout(0.5))
model.add(Conv2D(192, (3, 3)))
model.add(MaxPooling2D(pool_size=(3, 3), strides=(2, 2)))
model.add(Dropout(0.5))
model.add(Conv2D(192, (3, 3)))
model.add(Flatten())
model.add(Dense(2))
model.add(Activation('softmax'))
model.summary()
model.compile(loss="binary_crossentropy", optimizer=optimizers.Adam(lr=0.001, beta_1=0.9,
beta_2=0.999, epsilon=None, decay=0.0, amsgrad=False), metrics=["accuracy"])
# Initiate the train and test generators with data Augumentation
train_datagen = ImageDataGenerator(
rescale=1./255,
horizontal_flip=True,
rotation_range=30)
test_datagen = ImageDataGenerator(
rescale=1./255,
horizontal_flip=True,
rotation_range=30)
train_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size=(img_height, img_width),
batch_size=batch_size,
class_mode="binary")
validation_generator = test_datagen.flow_from_directory(
validation_data_dir,
target_size=(img_height, img_width),
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('f1.h5')
Any help will be much appreciated.
That is because you specify class_mode='binary' in your image generators which means two classes will be encoded as 0 or 1 rather than [1,0] or [0,1]. You can easily solve this by changing your final layer to:
model.add(Dense(1, activation='sigmoid'))
# No need for softmax activation
model.compile(loss='binary_crossentropy', ...)
Binary cross-entropy on 0-1 is mathematically equivalent to 2 class softmax with cross-entropy so you achieve the same thing.

Keras ValueError when checking target

I'm trying to build a model in keras. I followed a tutorial almost to the letter, but I'm getting an error that says:
ValueError: Error when checking target: expected activation_5 to have shape (None, 1) but got array with shape (16, 13)
The code I have is the following:
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(1))
model.add(Activation('sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
batch_size = 16
epochs = 50
number_training_data = 999
number_validation_data = 100
train_datagen = ImageDataGenerator(
rescale=1./255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
test_datagen = ImageDataGenerator(rescale=1. / 255)
train_generator = train_datagen.flow_from_directory(
'data/train', # this is the target directory
target_size=(200, 200),
batch_size=batch_size,
class_mode='categorical')
validation_generator = test_datagen.flow_from_directory(
'data/validation',
target_size=(200, 200),
batch_size=batch_size,
class_mode='categorical')
model.fit_generator(
train_generator,
steps_per_epoch=number_training_data // batch_size,
epochs=epochs,
validation_data=validation_generator,
validation_steps=number_validation_data // batch_size)
The dataset I have has 13 classes, so the shape of the array in the error message corresponds to the batch size and the number of classes. Any idea why I'm getting this error?
Your model is configured to perform binary classification, not multi-class classification with 13 classes. To do that you should change:
The number of units in the last dense to 13, the number of classes.
The activation at the output to softmax.
The loss to categorical cross-entropy (categorical_crossentropy).

Categories