Keras cnn: training accuracy and validation accuracy are incredibly high - tensorflow

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D
from tensorflow.keras.layers import MaxPooling2D
from tensorflow.keras.layers import Flatten
from tensorflow.keras.layers import Dense
from tensorflow.keras.layers import Dropout
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
import numpy as np
import cv2
import os
from imutils import paths
import imutils
def image_to_feature_vector(image, size=(32, 32)):
# resize the image to a fixed size, then flatten the image into
# a list of raw pixel intensities
return np.reshape(cv2.resize(image, size).flatten(), (32, 32, 3))
def extract_color_histogram(image, bins=(8, 8, 8)):
# extract a 3D color histogram from the HSV color space using
# the supplied number of `bins` per channel
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
hist = cv2.calcHist([hsv], [0, 1, 2], None, bins,
[0, 180, 0, 256, 0, 256])
# handle normalizing the histogram if we are using OpenCV 2.4.X
if imutils.is_cv2():
hist = cv2.normalize(hist)
# otherwise, perform "in place" normalization in OpenCV 3
else:
cv2.normalize(hist, hist)
# return the flattened histogram as the feature vector
return hist.flatten()
DATA_SET_PATH = '../training_images'
# grab the list of images that we'll be describing
print("[INFO] describing images...")
imagePaths = list(paths.list_images(DATA_SET_PATH))
# initialize the raw pixel intensities matrix, the features matrix,
# and labels list
rawImages = []
features = []
labels = []
# loop over the input images
for (i, imagePath) in enumerate(imagePaths):
# load the image and extract the class label (assuming that our
# path as the format: /path/to/dataset/{class}.{image_num}.jpg
image = cv2.imread(imagePath)
label = imagePath.split(os.path.sep)[-2].split(".")[1]
# extract raw pixel intensity "features", followed by a color
# histogram to characterize the color distribution of the pixels
# in the image
pixels = image_to_feature_vector(image)
hist = extract_color_histogram(image)
# update the raw images, features, and labels matricies,
# respectively
rawImages.append(pixels)
labels.append(label)
features.append(hist)
# show an update every 1,000 images
if i > 0 and i % 1000 == 0:
print("[INFO] processed {}/{}".format(i, len(imagePaths)))
# show some information on the memory consumed by the raw images
# matrix and features matrix
rawImages = np.array(rawImages)
features = np.array(features)
labels = np.array(labels)
print("[INFO] pixels matrix: {:.2f}MB".format(
rawImages.nbytes / (1024 * 1000.0)))
encoder = LabelEncoder()
encoder.fit(labels)
labels = to_categorical(encoder.transform(labels))
# partition the data into training and testing splits, using 75%
# of the data for training and the remaining 25% for testing
(trainRI, testRI, trainRL, testRL) = train_test_split(
rawImages, labels, test_size=0.15, random_state=42)
model = Sequential()
model.add(Conv2D(32, (3, 3), padding='same', activation='relu', input_shape=(32, 32, 3)))
model.add(Conv2D(32, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3), padding='same', activation='relu'))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3), padding='same', activation='relu'))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(257, activation='softmax'))
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
aug = ImageDataGenerator(rotation_range=30, width_shift_range=0.1,
height_shift_range=0.1, shear_range=0.2, zoom_range=0.2,
horizontal_flip=True, fill_mode="nearest")
model.fit_generator(aug.flow(trainRI, trainRL, batch_size=256), epochs=10, validation_data=(testRI, testRL))
model.evaluate(testRI, testRL)
I'm a beginner in cnn and keras and I'm trying to create a cnn to classify 257 different objects using keras. Above is my code. When I run the code, both training accuracy and validation are incredibly high.
100/102 [============================>.] - ETA: 1s - loss: 0.0265 - acc: 0.9960
101/102 [============================>.] - ETA: 0s - loss: 0.0264 - acc: 0.9960
102/102 [==============================] - 56s 553ms/step - loss: 0.0264 - acc: 0.9960 - val_loss: 0.0250 - val_acc: 0.9961
Could anyone tell me what's wrong with my code? Thanks.

Related

Require 'flatttened_input' when building ANN

Hello i need to build an ANN using binary_alpha_digits from tensorflow but i am unable to pass in the train data inside as it requires 'flatten_input' but I am passing in ['image','label'] dictionary. How do i solve this problem? Appreciate any help on this problem thanks.
from matplotlib import pyplot as plt
import tensorflow as tf
from tensorflow.keras import layers
train_ds, test_ds = tfds.load('BinaryAlphaDigits',
split=['train[:60%]', 'train[60%:]'])
model = tf.keras.Sequential()
model.add(layers.Flatten(input_shape=(28, 28)))
model.add(layers.Dense(10, activation=tf.nn.relu))
model.add(layers.Dense(10, activation=tf.nn.relu))
model.add(layers.Dense(10, activation=tf.nn.softmax))
model.compile(optimizer= tf.optimizers.Adam(),
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
epochs = 10
model.fit(train_ds, epochs=epochs)
as you feed images into model, so the input shape must have defined in shape (Height, Width, Channel) which refers to image dimensions and color mode and the second one is that you should preprocess dataset before fitting model on it.
Even notice the output layers units for multi-class classification is not set correctly for this dataset, while there are more than 10 labels, based on dataset it contains 39 labels and so the last layer units would be set to 39.
Here i would implement code which work correctly for you with preprocessing function for images and labels, And even notice the images of the dataset are in shape (20, 16, 1) so you could resize images to set it into (28, 28, 1) or just fed model with the images in their size.
After preprocessing, images are grouped by creating batches or mini-batches, and even shuffle training set to avoid high variance on testing set, so the operations below will be have done cause of that
from matplotlib import pyplot as plt
import tensorflow as tf
from tensorflow.keras import layers
import tensorflow_datasets as tfds
train_ds, test_ds = tfds.load('BinaryAlphaDigits', split=['train[:60%]', 'train[60%:]'])
def preprocess(data):
image = data['image']
image = tf.image.resize(image, (28, 28))
label = data['label']
return image, label
train_ds = train_ds.map(preprocess)
train_ds = train_ds.shuffle(1024)
train_ds = train_ds.batch(batch_size = 32)
test_ds = test_ds.map(preprocess)
test_ds = test_ds.batch(batch_size = 32)
model = tf.keras.Sequential()
model.add(layers.Flatten(input_shape=(28, 28, 1)))
model.add(layers.Dense(10, activation=tf.nn.relu))
model.add(layers.Dense(10, activation=tf.nn.relu))
model.add(layers.Dense(39, activation=tf.nn.softmax))
model.compile(optimizer= tf.optimizers.Adam(), loss='sparse_categorical_crossentropy', metrics=['accuracy'])
epochs = 10
model.fit(train_ds, epochs=epochs)
tfds.load by default gives a dictionary with image and label as the keys.
train_ds, test_ds = tfds.load('BinaryAlphaDigits',
split=['train[:60%]', 'train[60%:]'])
train_ds = train_ds.shuffle(1024).batch(4)
for x in train_ds.take(1):
print(type(x))
print(x['image'].shape, x['label'])
>>>
<class 'dict'>
(4, 20, 16, 1) tf.Tensor([ 6 32 6 12], shape=(4,), dtype=int64)
There is a setting called as_supervised that gives it as a proper dataset. Check docs here
If you use that setting and use proper input and output sizes, your model works
train_ds, test_ds = tfds.load('BinaryAlphaDigits',
split=['train[:60%]', 'train[60%:]'],as_supervised=True)
train_ds = train_ds.shuffle(1024).batch(4)
for x in train_ds.take(1):
print(type(x))
print(x[0].shape, x[1])
>>>
<class 'tuple'>
(4, 20, 16, 1) tf.Tensor([13 13 22 31], shape=(4,), dtype=int64)
model = tf.keras.Sequential()
model.add(layers.Flatten(input_shape=(20, 16,1)))
model.add(layers.Dense(10, activation=tf.nn.relu))
model.add(layers.Dense(10, activation=tf.nn.relu))
model.add(layers.Dense(36, activation=tf.nn.softmax))
model.compile(optimizer= tf.optimizers.Adam(),
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
epochs = 10
model.fit(train_ds, epochs=epochs)
>>>
Epoch 1/10
211/211 [==============================] - 1s 3ms/step - loss: 3.5428 - accuracy: 0.0629
Epoch 2/10
211/211 [==============================] - 0s 2ms/step - loss: 3.2828 - accuracy: 0.1105

Modern syntax for old-fashioned Keras command "Convolution2D"?

I was studying different CNN architectures to predict the CIFAR10 dataset, and I found this interesting Github repository:
https://gist.github.com/wielandbrendel/ccf1ff6f8f92139439be
I tried to run the model, but it was created in 6 years ago and the following Keras command is no longer valid:
model.add(Convolution2D(32, 3, 3, 3, border_mode='full'))
How is this command translated into the modern Keras syntax for Conv2D?
I get an error in Keras when I try to input the sequence of integers in Convolution2D(32, 3, 3, 3, ...)?
I guess 32 is the number of channels, and then we specify a 3x3 kernel size, but I am not sure about the meaning of the last 3 mentioned (4th position).
PS. Changing border_mode into padding = 'valid' or 'same' returns the following error:
model.add(Convolution2D(32, 3, 3, 3, padding='valid'))
TypeError: __init__() got multiple values for argument 'padding'
The gist there you're following is backdated and also has some issues. You don't need to follow this now. Here is the updated version of it. Try this.
Imports and DataSet
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import (Dense, Dropout, Activation,
Flatten, Conv2D, MaxPooling2D)
from tensorflow.keras.optimizers import SGD, Adadelta, Adagrad
import tensorflow as tf
# parameters
batch_size = 32
nb_classes = 10
nb_epoch = 5
# the data, shuffled and split between tran and test sets
(X_train, y_train), (X_test, y_test) = tf.keras.datasets.cifar10.load_data()
# convert class vectors to binary class matrices
Y_train = tf.keras.utils.to_categorical(y_train, nb_classes)
Y_test = tf.keras.utils.to_categorical(y_test, nb_classes)
# train model
X_train = X_train.astype("float32") / 255
X_test = X_test.astype("float32") / 255
X_train.shape, y_train.shape, X_test.shape, y_test.shape
((50000, 32, 32, 3), (50000, 1), (10000, 32, 32, 3), (10000, 1))
Modeling
model = Sequential()
model.add(Conv2D(filters=32, kernel_size=(3, 3),
strides=(1, 1), activation='relu', padding="same"))
model.add(Activation('relu'))
model.add(Conv2D(filters=32, kernel_size=(3, 3),
strides=(1, 1), activation='relu', padding="same"))
model.add(Activation('relu'))
model.add(MaxPooling2D((2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(filters=32, kernel_size=(3, 3),
strides=(1, 1), activation='relu', padding="same"))
model.add(Activation('relu'))
model.add(Conv2D(filters=32, kernel_size=(3, 3),
strides=(1, 1), activation='relu', padding="same"))
model.add(Activation('relu'))
model.add(MaxPooling2D((2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(nb_classes))
model.add(Activation('softmax'))
# let's train the model using SGD + momentum (how original).
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])
Compile and Run
model.fit(X_train, Y_train, batch_size=batch_size, epochs=nb_epoch)
# test score & top 1 performance
score = model.evaluate(X_test, Y_test, batch_size=batch_size)
y_hat = model.predict(X_test)
yhat = np.argmax(y_hat, 1)
top1 = np.mean(yhat == np.squeeze(y_test))
print('Test score/Top1', score, top1)
The Convolutional2D is now named Conv2D, but there is still an alias for Convolutional2D, so that's not a problem.
The border_mode argument is not available anymore, the equivalent is padding, with options valid or same.
Try both to see if any of those fits the shapes of the outputs and allows to code to work.

how to increase the accuracy of an image classifier?

I made an image classifier using Tensorflow, Keras with the implementation of a CNN architecture, the model works pretty fine (at least for the images that I have tested on it ) and it has reached an accuracy of 78.87%, the only thing that I m facing is that I want to make the accuracy no less than 85%.
Please Note:
Dataset: 2 folders: [Train Folder===> 80 folders each has 110 images, Validation folder===> 80 folders each has 22 images] size of the images [240-260]x[40-60]
Below is the code I used to create, save and test 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 = {"0":"0", "1":"0.25", "2":"0.5", "3":"0.75", "4":"1", "5":"1.25", "6":"1.5", "7":"1.75",
"47":"2", "48":"2.25", "49":"2.5", "50":"2.75", "52":"3","53":"3.25", "54":"3.5", "55":"3.75", "56":"4", "57":"4.25", "58":"4.5",
"59":"4.75","60":"5", "61":"5.25", "62":"5.5", "63":"5.75", "64":"6", "65":"6.25","66":"6.5", "67":"6.75", "68":"7", "69":"7.25",
"70":"7.5", "71":"7.75", "72":"8", "73":"8.25", "74":"8.5", "75":"8.75", "76":"9", "77":"9.25", "78":"9.5", "79":"9.75", "8":"10",
"9":"10.25", "10":"10.5", "11":"10.75", "12":"11", "13":"11.25", "14":"11.5", "15":"11.75", "16":"12","17":"12.25", "18":"12.5",
"19":"12.75", "20":"13", "21":"13.25", "22":"13.5", "23":"13.75","24":"14", "25":"14.25", "26":"14.5", "27":"14.75", "28":"15",
"29":"15.25", "30":"15.5", "31":"15.75", "32":"16", "33":"16.25", "34":"16.5", "35":"16.75", "36":"17", "37":"17.25", "38":"17.5",
"39":"17.75", "40":"18", "41":"18.25", "42":"18.5", "43":"18.75", "44":"19", "45":"19.25", "46":"19.5", "51":"20"}
def load_image(img_path, show=False):
img = image.load_img(img_path, target_size=(251, 54))
img_tensor = image.img_to_array(img) # (height, width, channels)
img_tensor = np.expand_dims(img_tensor, axis=0) # (1, height, width, channels), add a dimension because the model expects this shape: (batch_size, height, width, channels)
img_tensor /= 255. # imshow expects values in the range [0, 1]
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/5.75/a.png'
# load a single image
new_image = load_image(img_path)
# check prediction
#pred = model.predict(new_image)
pred = model.predict_classes(new_image)
#print(pred[0])
print(result[str(pred[0])])
Taking all the information about dataset and considering your CNN model already has around 80% accuracy you can start with training the model for a higher number of epochs (typically > 100 epochs). That should give the required boost to your model.
If that alone does not work you can implement:
Transformation/augmentation:
perform transformation/augmentation on the images before feeding into the model.
Tweak Model:
make changes to model layers and do hyperparameter tuning.
You can follow this article to learn more.

ValueError: Error when checking target: expected dense_2 to have shape (None, 2) but got array with shape (321, 3)

I want to create an image classifier using keras, and train it with a few example images. Then, i will be using pre-trained models and adding a few layers at the end, but first, i want to understand keras and CNNs.
My console prints the following error:
ValueError: Error when checking target: expected dense_2 to have shape
(None, 2) but got array with shape (321, 3)
Here is my code:
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import argparse
import sys
import time
import numpy as np
import cv2
import time
from PIL import Image
import keras
import glob
from keras.models import Sequential
from keras.models import load_model
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras.optimizers import SGD
from sklearn.preprocessing import LabelBinarizer
labels = ['buena', 'mala', 'otro']
def to_one_hot(labels, ys):
result = np.zeros((len(ys),len(labels)))
for i in range(result.shape[0]):
for j in range(result.shape[1]):
result[i,j] = int(ys[i] == labels[j])
return result
def build_dataset(labels):
num_classes = len(labels)
x = []
y = []
for label in labels:
for filename in (glob.glob('./tf_files/papas_fotos/'+label+'/*.jpg')):
img = cv2.imread(filename)
img = np.resize(img,(100,100, 3))
x.append(img)
y.append(label)
y = to_one_hot(labels, y)
# y = keras.utils.to_categorical(y, num_classes=3)
x = np.array(x)
x_train = x[20:]
y_train = y[20:]
x_test = x[:19]
y_test = y[:19]
print (x.shape, y.shape)
return x_train, y_train, x_test, y_test
model = Sequential()
# input: 100x100 images with 3 channels -> (100, 100, 3) tensors.
# this applies 32 convolution filters of size 3x3 each.
model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(100, 100, 3)))
model.add(Conv2D(32, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(256, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(3, activation='softmax'))
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd)
x_train, y_train, x_test, y_test = build_dataset(labels)
model = load_model('thebestmodel.h5')
print (model)
model.fit(x_train, y_train, batch_size=32, epochs=20)
score = model.evaluate(x_test, y_test, batch_size=32)
model.save('thebestmodel.h5')
print (score)
What mistake am I making? I think that may be the size of my one hot encoded labels, but i can't make it work.
Thanks!
Although your code was fixed for this specific error, you're loading a saved model: model = load_model('thebestmodel.h5')
This is undoing everything before this line.

About use keras for multi-label classification

I try to train a multi-labels classifier, I used sigmoid units in the output layer and then use "binary_crossentrpy" loss. Current problem is the results of the training and testing were ideal, values of loss and accuracy were great.But when I used model.predict() predicted label, the output don't match the real label value. How to change code to solve it?
The shape of the training set and testing set is (-1, 1, 300, 300), the shape of the target label is (-1, 478), I have 478 in total.
My complete code:
import numpy as np
from keras.models import Sequential
from keras.layers import Dense, Activation, Convolution2D, MaxPooling2D, Flatten, Dropout
from keras.optimizers import Adam
X = np.load('./data/X_train.npy')
y = np.load('./data/Y_train.npy')
X_train, y_train = X[:2000], y[:2000]
X_test, y_test = X[2000:], y[2000:]
model = Sequential()
model.add(Convolution2D(nb_filter=32, nb_row=5, nb_col=5, padding='same', input_shape=(1, 300, 300)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same'))
model.add(Dropout(0.25))
model.add(Convolution2D(64, 5, 5, padding='same'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2), border_mode='same'))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(1024))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(478))
model.add(Activation('sigmoid'))
model.compile(optimizer=Adam(lr=1e-4), loss='binary_crossentropy', metrics=['accuracy'])
print('Training ------------')
model.fit(X_train, y_train, epochs=5, batch_size=300, validation_data=(X_test, y_test), verbose=1)
model.save('model.h5')
Could you help me to find a solution? Thanks!
Have you tried to filter the values based on a threshold?
pred = model.predict(x_test)
pred[pred>=0.5] = 1
pred[pred<0.5] = 0
print(pred[0:5])