CNN model not learning - python

I'm building a CNN model to classify images, however, I guess that my model is not learning because of the constant values of accuracy and loss function. See my code below:
Building the images train, test and validation datasets
import pandas as pd
from keras_preprocessing.image import ImageDataGenerator
import numpy as np
#Creating three datasets from the the 3 .txt files.
trainingfile = pd.read_table('data/training.txt', delim_whitespace=True, names=('class', 'image'))
testingfile = pd.read_table('data/testing.txt', delim_whitespace=True, names=('class', 'image'))
validationfile = pd.read_table('data/validation.txt', delim_whitespace=True, names=('class', 'image'))
#Changing target variable type
trainingfile = trainingfile.replace([0, 1, 2], ['class0', 'class1', 'class2'])
testingfile = testingfile.replace([0, 1, 2], ['class0', 'class1', 'class2'])
validationfile = validationfile.replace([0, 1, 2], ['class0', 'class1', 'class2'])
#Data augmentation
datagen=ImageDataGenerator()
train_datagen = ImageDataGenerator(
#Apliquem una mica de rotació no gaire ja que generalment les fotografies estaran centrades
rotation_range=5,
zoom_range=0.1)
#Final datasets containing the images
train=train_datagen.flow_from_dataframe(dataframe=trainingfile, directory="data/", x_col="image", y_col="class", class_mode="categorical", target_size=(256,256),color_mode='rgb',batch_size=32)
test=datagen.flow_from_dataframe(dataframe=testingfile, directory="data/", x_col="image", y_col="class", class_mode="categorical", target_size=(256,256),color_mode='rgb',batch_size=32)
#No data augmentation to the validation dataset.
validation=datagen.flow_from_dataframe(dataframe=validationfile, directory="data/", x_col="image", y_col="class", class_mode="categorical", target_size=(256,256),color_mode='rgb', batch_size=32)
CNN model
from keras.models import Sequential
from keras.layers import Dense, Conv2D, Flatten, Activation, Dropout, MaxPooling2D, BatchNormalization
from keras.constraints import maxnorm
#Creació del model
model = Sequential()
#1r bloc convolució
model.add(Conv2D(32, kernel_size = (3, 3), activation='relu', input_shape=(256, 256,3)))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(BatchNormalization())
#2n bloc convolució
model.add(Conv2D(64, kernel_size=(3,3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(BatchNormalization())
#3r bloc convolució
model.add(Conv2D(64, kernel_size=(3,3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(BatchNormalization())
#4t bloc convolució
model.add(Conv2D(96, kernel_size=(3,3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(BatchNormalization())
#5e bloc convolució
model.add(Conv2D(32, kernel_size=(3,3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(BatchNormalization())
#Dropout
model.add(Dropout(0.2))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
#model.add(Dropout(0.3))
model.add(Dense(3, activation = 'softmax'))
from keras import regularizers, optimizers
from keras.optimizers import RMSprop
from keras.callbacks import EarlyStopping
# Compile model
model.compile(optimizer='adam',loss="categorical_crossentropy",metrics=["accuracy"])
# Early stopping
es = EarlyStopping(monitor='val_loss', mode='min', verbose=1,patience=10)
Training the model
h=model.fit_generator(generator=train,
validation_data=validation,
epochs=50,
callbacks=[es])
Results
It is the first time that I use fit_generator and perhaps I'm not using it properly?

As I can see from the results images, you are training just for 1 epoch. This could be because the EarlyStopping is too strict. Try adding patience=3to the EarlyStopping callback.
es = EarlyStopping(monitor='val_loss', mode='min', verbose=1, patience=3)
EDIT
Overfitting example:
Check this post to know more about how to deal with overfitting.

Related

why is my model performing poorly for a keras sequential model?

I'm a newbie to deep learning (and machine learning), and I created a python script that uses TensorFlow/Keras to identify flowers into different groups using this dataset. Here is my code: (I'm doing this on Kaggle)
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn.preprocessing import LabelEncoder
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.optimizers import Adam, SGD
from keras.utils import to_categorical
from keras.layers import Conv2D, Dropout, Dense, Flatten
import matplotlib.pyplot as plt
import cv2
import os
NUM_CLASSES = 5
IMG_SIZE = 150
DAISY = '../input/flowers-recognition/flowers/daisy'
DANDELION = '../input/flowers-recognition/flowers/dandelion'
ROSE = '../input/flowers-recognition/flowers/rose'
SUNFLOWER = '../input/flowers-recognition/flowers/sunflower'
TULIP = '../input/flowers-recognition/flowers/tulip'
x = []
y = []
def train_data_gen(DIR, ID):
for img in os.listdir(DIR):
try:
path = DIR + '/' + img
img = plt.imread(path)
img = cv2.resize(img,(IMG_SIZE,IMG_SIZE))
x.append(img)
y.append(ID)
except:
None
train_data_gen(DAISY, 0)
train_data_gen(DANDELION, 1)
train_data_gen(ROSE, 2)
train_data_gen(SUNFLOWER, 3)
train_data_gen(TULIP, 4)
x = np.array(x)
y = to_categorical(y,num_classes = 5)
x_train,x_test,y_train,y_test = train_test_split(x, y, test_size = 0.15)
x_train,x_val,y_train,y_val = train_test_split(x_train, y_train, test_size = 0.15)
datagen = ImageDataGenerator(
featurewise_center=False,
samplewise_center=False,
samplewise_std_normalization=False,
rotation_range=60,
zoom_range = 0.1,
width_shift_range=0.1,
height_shift_range=0.1,
shear_range=0.1,
fill_mode = "reflect"
)
datagen.fit(x_train)
model = Sequential()
model.add(Conv2D(64, kernel_size=(3, 3), strides=2, activation='relu', input_shape=(IMG_SIZE, IMG_SIZE, 3)))
model.add(Dropout(0.5))
model.add(Conv2D(128, kernel_size=(3, 3), strides=2, activation='relu'))
model.add(Dropout(0.5))
model.add(Conv2D(128, kernel_size=(3, 3), strides=2, activation='relu'))
model.add(Dropout(0.5))
model.add(Conv2D(128, kernel_size=(3, 3), strides=2, activation='relu'))
model.add(Dropout(0.5))
model.add(Flatten())
model.add(Dense(1024, activation='relu'))
model.add(Dense(5, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit_generator(datagen.flow(x_train,y_train,batch_size=16), epochs=10, steps_per_epoch=x_train.shape[0]//16, validation_data=(x_val, y_val), verbose=1)
I know that the epochs is 10 here, but later on, I set it to 100. That was taking a really like time, so I stopped it on the 63rd epoch. Even then, it was floating around 60% accuracy, which is way too low. What could be something that I can change to make it more accurate? Would it be that my CNN is too small for this? Or is there something wrong with my data? I'm really new to this so I can't specify my question any further than "Why is my model performing badly?"
Thank you all in advance for the constructive feedback.
You model uses too many Dropout layers. model.add(Dropout(0.5)) effectively drops 50% of your neurons of your incoming layer and on top of that you have 4 of these. You are most probably underfitting.
After each Conv2D layer add a keras.layers.MaxPooling2D layer.
First try removing all the Dropout layers. In that case you will run the risk of overfitting - but if you don't overfit then there is no point of Dropout layers. If you do overfit, experiment with just 1 dropout layer with 20% dropout rate and gradually increase that to 50% and then maybe add another dropout of 20% and continue.

I am getting shape related error on running the fit function

valueError: A target array with shape (90, 300, 300, 1) was passed for an output of shape (None, 1) while using as loss binary_crossentropy. This loss expects targets to have the same shape as the output.
I am getting the above error when I run the below code. Can anyone please help me to rectify it.
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, Activation, Flatten, Conv2D, MaxPooling2D
import pickle
import numpy as np
# X = np.array(pickle.load(open("X.pickle","rb")))
# Y = np.array(pickle.load(open("Y.pickle","rb")))
X = np.array(pickle.load(open("x_train.pickle","rb")))
Y = np.array(pickle.load(open("y_train.pickle","rb")))
#scaling our image data
X = X/255.0
model = Sequential()
model.add(Conv2D(64 ,(3,3), input_shape = X.shape[1:]))
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size = (2,2)))
model.add(Conv2D(128 ,(3,3)))
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size = (2,2)))
model.add(Conv2D(256 ,(3,3)))
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size = (2,2)))
model.add(Conv2D(512 ,(3,3)))
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size = (2,2)))
model.add(Flatten())
model.add(Dense(2048))
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'])
model.summary()
model.fit(X, Y, batch_size=32, epochs = 1, validation_split=0.1)

How do I reconcile predictions from keras flow_from_dataframe to actual labels?

I've been researching this issue and while there seems to be references to it, I wasn't able to to get it to work.
I'm using keras flow_from_dataframe. My file names and labels are stored in two dataframes, one for train (df) and one for validation (dfv).
As I train my model the validation accuracy is at .75. I can verify that looking at model.history. Even model.evaluate_generator will confirm the exact same values.
But when I do a model.predict_generator using the exact same validation dataset provided to .fit and model.evaluate_generator, I get essentially randomness (.5), which tells me that either something with the order of observation is going on, or that there might be parts of the pipeline that are not carried on to the evaluation part (like rescaling).
Here's my code:
datagen=ImageDataGenerator(rescale=1./255.)
train_generator=datagen.flow_from_dataframe(
dataframe=df,
directory=path+'\\img.tar\\img',
x_col="loc",
y_col="target",
weight_col=None,
target_size=(32, 32),
color_mode="rgb",
classes=None,
class_mode="binary",
batch_size=100,
shuffle=True,
seed=SEED,
save_to_dir=None,
save_prefix="",
save_format="png",
subset=None,
interpolation="nearest",
validate_filenames=True
)
valid_generator=datagen.flow_from_dataframe(
dataframe=dfv,
directory=path+'\\img.tar\\img',
x_col="loc",
y_col="target",
weight_col=None,
target_size=(32, 32),
color_mode="rgb",
classes=None,
class_mode="binary",
batch_size=100,
shuffle=False,
seed=SEED,
save_to_dir=None,
save_prefix="",
save_format="png",
subset=None,
interpolation="nearest",
validate_filenames=True
)
#Found 8500 validated image filenames belonging to 2 classes.
#Found 500 validated image filenames belonging to 2 classes.
from keras.models import Sequential
#Import from keras_preprocessing not from keras.preprocessing
from keras_preprocessing.image import ImageDataGenerator
from keras.layers import Dense, Activation, Flatten, Dropout, BatchNormalization
from keras.layers import Conv2D, MaxPooling2D
from keras import regularizers, optimizers
import pandas as pd
import numpy as np
model = Sequential()
model.add(Conv2D(32, (3, 3), padding='same',
input_shape=(32,32,3)))
model.add(Activation('relu'))
model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(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(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam',metrics=["accuracy"])
STEP_SIZE_TRAIN=train_generator.n//train_generator.batch_size
STEP_SIZE_VALID=valid_generator.n//valid_generator.batch_size
#STEP_SIZE_TEST=test_generator.n//test_generator.batch_size
hx = model.fit_generator(generator=train_generator,
steps_per_epoch=STEP_SIZE_TRAIN,
validation_data=valid_generator,
validation_steps=STEP_SIZE_VALID,
epochs=1
)
#Epoch 1/1
#85/85 [==============================] - 74s 871ms/step - loss: 0.6584 - accuracy: 0.6398 - val_loss: 0.6059 - val_accuracy: 0.7500
hx.history
#{'val_loss': [0.6059464812278748],
#'val_accuracy': [0.75],
#'loss': [0.6583675097016727],
#'accuracy': [0.6397647]}
model.evaluate_generator(generator=valid_generator,
steps=STEP_SIZE_VALID)
#[0.6059464812278748, 0.75]
pred=model.predict_generator(valid_generator,verbose=1,steps=STEP_SIZE_VALID)
roc_auc_score(dfv.label.values,pred.ravel())
#0.51
print(roc_auc_score(dfv.label.values,pred.ravel()>df['label'].mean()))
print(roc_auc_score(dfv.label.values,pred.ravel()>0.5))
#0.5
#0.5

AttributeError: 'ImageDataGenerator' object has no attribute 'shape'

I am new in coding. I am trying to get the score but unfortunately i am getting errors. I was using first import.keras until it gave me when i wanted to evaluate the score and predict.The training model happened well, i have gotten no problem there.It is after that, when i was aboout to get the score of my model that i got as error ImageDataGnerator: Object has no 'ndim'.
Then i looked for help and someone told me to use import.tensorflow.keras instead and i did it....
After training the model again,reaching that part in order to get the score and predict after i've gotten another error saying : ImageDataGenerator object has no attribute shapes and a warning saying :
WARNING : tensorflow : Falling back from v2 loop because of error : Failed to find data* **adapter that can handle input : < class 'tensorflow.python.keras.preprocessing.image.ImageDataGenerator'> , < class 'NoneType'
This is some of the code below.
import numpy as np
import tensorflow as tf
import cv2
import sys
import os
import matplotlib.pyplot as plt
from tensorflow import keras
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, Activation, Flatten
from tensorflow.keras.layers import Conv2D, MaxPooling2D
from tensorflow.keras.optimizers import Adam
image_width, image_height = 150,150
Epochs =10
batch_size=45
Steps_per_epoch=190
Validation_data=20
num_classes = len(map_characters)
model = Sequential()
model.add(Conv2D(32, (3, 3), padding='same', input_shape= (image_height,image_width ,3)))
model.add(Activation('relu'))
model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))
model.add(Conv2D(64, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))
model.add(Conv2D(256, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(Conv2D(256, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))
model.add(Flatten())
model.add(Dense(1024))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))
opt = Adam(lr=0.01, decay=1e-6, )
model.summary()
model.compile(loss='categorical_crossentropy',
optimizer='Adam',
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)
training_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size = (image_height, image_width),
batch_size = batch_size,
class_mode = 'categorical')
validation_generator = test_datagen.flow_from_directory(
validation_data_dir,
target_size = (image_height, image_width),
batch_size = batch_size,
class_mode = 'categorical')
result=model.fit_generator(training_generator,
steps_per_epoch=Steps_per_epoch,
epochs = Epochs,
validation_data = validation_generator,
validation_steps=Validation_data)
score = model.evaluate(test_datagen,
validation_generator,
batch_size=batch_size)
To evaluate on a generator, you need to use evaluate_generator, not evaluate.

How should i increase accuracy of face recognition using cnn?

from tensorflow.python.keras.applications.inception_v3 import preprocess_input
from tensorflow.python.keras.preprocessing.image import ImageDataGenerator
from tensorflow.python.keras.models import Sequential
from tensorflow.python.keras.layers import Dense, Flatten, Conv2D, MaxPool2D, Dropout
from keras.layers.normalization import BatchNormalization
from keras import regularizers
import os
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
os.environ['CUDA_VISIBLE_DEVICES'] = '-1'
data_gen = ImageDataGenerator(preprocessing_function=preprocess_input, shear_range=0.2, zoom_range=0.2, horizontal_flip=True)
train_gen = data_gen.flow_from_directory('/home/bg22/PycharmProjects/KUNAL/dataset/training_set', target_size=(64,64), batch_size=16, class_mode='categorical')
test_gen = data_gen.flow_from_directory('/home/bg22/PycharmProjects/KUNAL/dataset/test_set', target_size=(64,64), batch_size=16, class_mode='categorical')
model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=(64, 64, 3)))
#model.add(BatchNormalization())
#model.add(Dropout(0.5))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Conv2D(32, kernel_size=(3, 3), activation='relu'))
#model.add(BatchNormalization())
#model.add(Dropout(0.5))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Conv2D(16, kernel_size=(3, 3), activation='relu'))
#model.add(BatchNormalization())
#model.add(Dropout(0.5))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Conv2D(16, kernel_size=(3, 3), activation='relu'))
#model.add(BatchNormalization())
#model.add(Dropout(0.5))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Flatten())
#model.add(Dense(16, activation='relu', kernel_regularizer=regularizers.l2(0.01)))
model.add(Dense(2, activation='softmax'))
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit_generator(train_gen, epochs= 10, validation_data=test_gen)
With this architecture i'm getting 80% accuracy.
I tried these methods to increase accuracy:
Batch normalization
Weight Decay(L2 regularizer)
Dropout
But all of them failed to give expected result.
Batch normalization gives error:
/usr/bin/python3.5 "/home/bg22/PycharmProjects/KUNAL/Face Recognition.py"
Using TensorFlow backend.
Found 8000 images belonging to 2 classes.
Found 2000 images belonging to 2 classes.
Traceback (most recent call last):
File "/home/bg22/PycharmProjects/KUNAL/Face Recognition.py", line 20, in <module>
model.add(BatchNormalization())
File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/training/checkpointable/base.py", line 364, in _method_wrapper
method(self, *args, **kwargs)
File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/keras/engine/sequential.py", line 130, in add
'Found: ' + str(layer))
TypeError: The added layer must be an instance of class Layer. Found: keras.layers.normalization.BatchNormalization object at 0x7fddf526e9e8>
On the other hand Dropout and regularizer reduces the accuracy instead!!
First you have import the BatchNormalization layer from keras.layers.BatchNormalization. You can take the following measures to increase the accuracy.
Decrease the batch size.
Decrease the learning rate to a smaller number like 0.001 or 0.0001.
Slightly increase the dropout rates to 0.5 or 0.6.
Use the LeakyReLU activation with alpha ( negative slope ) 0.2 or 0.01.
Try using AdaGrad or Nadam optimizers.
Add two Conv2d layers and then add the pooling layer.

Categories

Resources