Model not learning with tf.keras.preprocessing.image_dataset_from_directory - tensorflow

I tried to make a simple model to recognize images of animals (3 classes),
with the function tf.keras.preprocessing.image_dataset_from_directory, when i fit the model with the train and validation dataset, it seems to work, but on evaluate and predict, it find always the same class, I dont know why, here is my code :
import matplotlib.pyplot as plt
import numpy as np
import PIL
import tensorflow as tf
from tensorflow.keras.layers import Dense, Flatten
from tensorflow.keras.models import Sequential
from tensorflow.keras.optimizers import Adam
from tensorflow import keras
import os
i = 0
def fast_scandir(dirname):
subfolders= [f.path for f in os.scandir(dirname) if f.is_dir()]
for dirname in list(subfolders):
subfolders.extend(fast_scandir(dirname))
return subfolders
classnames = fast_scandir("/home/someone/Documents/machinelearning/path/testimage")
for name in classnames:
classnames[i] = classnames[i].replace("/home/someone/Documents/machinelearning/path/images/","")
i+=1
i=0
classesnum = len(classnames)
#print(classesnum)
img_height = 256
img_width = 256
batch_size = 16
IMAGE_SIZE = 256
data_dir = "/home/someone/Documents/machinelearning/path/testimage"
test_dir = "/home/someone/Documents/machinelearning/path/testimage"
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="training",
label_mode="categorical",
seed=123,
shuffle=False,
image_size=(img_height, img_width),
batch_size=batch_size,
color_mode='rgb')
print(train_ds)
'''
test_ds = tf.keras.preprocessing.image_dataset_from_directory(
test_dir,
label_mode="categorical",
seed=123,
shuffle=False,
image_size=(img_height, img_width),
batch_size=batch_size,
color_mode='rgb')
'''
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="validation",
label_mode="categorical",
seed=123,
shuffle=False,
image_size=(img_height, img_width),
batch_size=batch_size,
color_mode='rgb')
'''
#####debug######
for images,labels in train_ds.take(1):
for i in range(len(labels)):
img = plt.imshow(images[i].numpy().astype("uint8"))
plt.title(str(labels[i]))
plt.show()
'''
#tf.data.experimental.cardinality(train_ds)
#print(val_ds)
#print(np.shape(val_ds))
#print(type(val_ds))
import matplotlib.pyplot as plt
pretrained_model= tf.keras.applications.ResNet50(include_top=False,
input_shape=(img_width,img_height,3),
pooling='avg',classes=classesnum,
weights='imagenet')
for layer in pretrained_model.layers:
layer.trainable=False
from tensorflow.keras.layers import Conv2D, MaxPooling2D
from tensorflow.keras.layers import Dense, Flatten
from tensorflow.keras import optimizers
model = Sequential()
model.add(Conv2D(32,(3,3),input_shape=(IMAGE_SIZE,IMAGE_SIZE,3),activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Conv2D(64,(3,3),activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Conv2D(96,(3,3),activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Conv2D(128,(3,3),activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Flatten())
model.add(Dense(512,activation='relu'))
model.add(Dense(3,activation='softmax'))
model.summary()
model.compile(loss='categorical_crossentropy',
optimizer=keras.optimizers.Adam(learning_rate=3e-4),
metrics=['accuracy'])
history = model.fit(train_ds, validation_data=val_ds, epochs=10)
fig1 = plt.gcf()
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.axis(ymin=0.4,ymax=1)
plt.grid()
plt.title('Model Accuracy')
plt.ylabel('Accuracy')
plt.xlabel('Epochs')
plt.legend(['train', 'validation'])
plt.show()
model.save("/home/someone/Documents/machinelearning/path/model.h5")
'''
evaluation = model.evaluate(test_ds, return_dict=True)
for name, value in evaluation.items():
print(f"{name}: {value:.4f}")
'''
I think its something that is set wrong like a bad number of classes somewhere..

It seems that setting shuffle=True in the dataset, resolved the issue, because somehow just a part of the dataset is used in my model.

Related

I am trying to run a tensorflow visual recognitiontraining on a m1 MacBook Pro but get always the same error

'''import numpy as np
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense, GlobalAveragePooling2D
from keras.preprocessing.image import ImageDataGenerator
from keras.callbacks import ModelCheckpoint, EarlyStopping
from tensorflow.keras.optimizers import Adam
from keras.applications.inception_resnet_v2 import InceptionResNetV2
import glob
n_data = len(glob.glob("raw_data\*"))*64
n_epoch = 50
n_batch = 32
datagen = ImageDataGenerator(
rotation_range=20,
brightness_range=[0.8, 1.2],
shear_range=0.2,
zoom_range=0.2,
fill_mode='nearest',
horizontal_flip=True,
rescale=1. /255,
data_format=None,
validation_split=0.2
)
train_gen = datagen.flow_from_directory(
'./dataset',
target_size = (400, 400),
class_mode = 'categorical',
color_mode = 'rgb',
batch_size = n_batch,
subset="training",
shuffle=True
)
val_gen = datagen.flow_from_directory(
'./dataset',
target_size = (400, 400),
class_mode = 'categorical',
color_mode = 'rgb',
batch_size = n_batch,
subset="validation",
shuffle=True
)
model = Sequential()
base_model = InceptionResNetV2(weights='imagenet', include_top=False, input_shape=(400,400,3))
model.add(base_model)
model.add(GlobalAveragePooling2D())
model.add(Dense(units = 1024, activation="relu"))
#model.add(Dropout(0.2))
#model.add(Dense(units = 1024, activation="relu"))
model.add(Dense(units=13, activation="softmax"))
base_total = len(base_model.layers)
for layer in base_model.layers[:base_total]:
layer.trainable=False
for layer in model.layers[base_total:]:
layer.trainable=True
for layer in model.layers[1:]:
layer.trainable = True
opt = Adam(learning_rate=0.0001)
model.compile(optimizer=opt, loss="categorical_crossentropy", metrics=['accuracy'], run_eagerly=True)
model.summary()
checkpoint = ModelCheckpoint("chess_check.h5", monitor="val_acc", verbose=1, save_bes_only=True, save_weights_onlny=False, mode="auto", period=1)
early = EarlyStopping(monitor="val_acc", min_delta=0, patience=10, verbose=1, mode="auto", restore_best_weights=True)
hist = model.fit_generator(steps_per_epoch = int((0.8*n_data)//n_batch), generator = train_gen, validation_data = val_gen, validation_steps = int((0.2*n_data)//n_batch), epochs=n_epoch, verbose=1, callbacks=[checkpoint, early])
model.save_weights('chess.h5')'''
this is the terminal output:
File "/Users/Coden/.Trash/vs-r/tutorial-en/lib/python3.10/site-packages/keras/engine/training.py", line 1420, in fit
raise ValueError('Unexpected result of train_function '
ValueError: Unexpected result of train_function (Empty logs). Please use Model.compile(..., run_eagerly=True), or tf.config.run_functions_eagerly(True) for more information of where went wrong, or file a issue/bug to tf.keras.
these are the installed packages:
'''
absl-py==1.1.0
astunparse==1.6.3
cachetools==5.2.0
certifi==2022.6.15
charset-normalizer==2.0.12
flatbuffers==1.12
gast==0.4.0
google-auth==2.8.0
google-auth-oauthlib==0.4.6
google-pasta==0.2.0
grpcio==1.46.3
h5py==3.7.0
idna==3.3
keras==2.9.0
Keras-Preprocessing==1.1.2
libclang==14.0.1
Markdown==3.3.7
numpy==1.22.4
oauthlib==3.2.0
opt-einsum==3.3.0
packaging==21.3
Pillow==9.1.1
protobuf==3.19.4
pyasn1==0.4.8
pyasn1-modules==0.2.8
pyparsing==3.0.9
requests==2.28.0
requests-oauthlib==1.3.1
rsa==4.8
scipy==1.8.1
six==1.16.0
tensorboard==2.9.1
tensorboard-data-server==0.6.1
tensorboard-plugin-wit==1.8.1
tensorflow-estimator==2.9.0
tensorflow-macos==2.9.2
termcolor==1.1.0
typing_extensions==4.2.0
urllib3==1.26.9
Werkzeug==2.1.2
wrapt==1.14.1
'''
the code works on a weak windows laptop

0 validation loss while training TensorFlow CNN model

import numpy as np
import matplotlib.pyplot as plt
import os
import cv2
DATADIR = "C:\\Users\\John\\Documents\\CroppedYale"
CATEGORIES = ["yaleB01","yaleB02","yaleB03","yaleB04","yaleB05","yaleB06","yaleB07","yaleB08","yaleB09","yaleB10","yaleB11","yaleB12","yaleB13","yaleB15","yaleB16","yaleB17","yaleB18","yaleB19","yaleB20","yaleB21","yaleB22","yaleB23","yaleB24","yaleB25","yaleB26","yaleB27","yaleB28","yaleB29","yaleB30","yaleB31","yaleB32","yaleB33","yaleB34","yaleB35","yaleB36","yaleB37","yaleB38","yaleB39"]
for category in CATEGORIES:
path = os.path.join(DATADIR, category)
for img in os.listdir(path):
img_array = cv2.imread(os.path.join(path,img), cv2.IMREAD_GRAYSCALE)
plt.imshow(img_array, cmap="gray")
plt.show()
break
break
print(img_array)
IMG_SIZE = 50
new_array = cv2.resize(img_array, (IMG_SIZE,IMG_SIZE))
plt.imshow(new_array,cmap="gray")
plt.show()
training_data = []
def create_training_data():
for category in CATEGORIES:
path = os.path.join(DATADIR, category)
class_num = CATEGORIES.index(category)
for img in os.listdir(path):
try:
img_array = cv2.imread(os.path.join(path,img), cv2.IMREAD_GRAYSCALE)
new_array = cv2.resize(img_array, (IMG_SIZE,IMG_SIZE))
training_data.append([new_array, class_num])
except Exception as e:
pass
create_training_data()
print(len(training_data))
import random
random.shuffle(training_data)
for sample in training_data[:10]:
print(sample[1])
X = []
y = []
for features, label in training_data:
X.append(features)
y.append(label)
X = np.array(X).reshape(-1, IMG_SIZE, IMG_SIZE, 1)
y = np.array(y)
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, Activation, Flatten, Conv2D, MaxPooling2D
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(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(Dense(1))
model.add(Activation("sigmoid"))
model.compile(loss="CategoricalCrossentropy",
optimizer="adam",
metrics=['accuracy'])
model.fit(X, y, batch_size=32, epochs=10, validation_split=0.1)
Does anyone know why I get 0.00 loss? Obviously I'm doing something wrong. I just don't know what. It's 40 people with their own folder each folder has 36 images of their face. Is it a problem with how I processed my data or the model itself? Maybe the model has wrong layers or the preprocessing is wrong altogether.

how implement cross validation with flower dataset?

I hope you are all doing well ^_^
how implement cross validation with flower dataset? the dataset contains 3670 images in 5 folders ['daisy', 'dandelion', 'roses', 'sunflowers', 'tulips'] i want to use vgg16 or any model and Cross-Validation to improve my accuracy, right now it's between 84-86%.
.I'm a noob in this field, i have tested transfer learning models with the flower dataset, i read some article about cross validation and i want to test it with this dataset. but the dataset does not contain csv file.
link to the dataset : https://www.kaggle.com/rajmehra03/flower-recognition-cnn-keras/data
----------------------------------------code------------------------------------------------------
import matplotlib.pyplot as plt
import numpy as np
import os
import PIL
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense,Conv2D,MaxPool2D,Dropout,Flatten
import pathlib
dataset_url =
"https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz"
data_dir = tf.keras.utils.get_file('flower_photos', origin=dataset_url, untar=True)
data_dir = pathlib.Path(data_dir)
image_count = len(list(data_dir.glob('*/*.jpg')))
print(image_count)
batch_size = 32
img_height = 224
img_width = 224
train_ds = tf.keras.utils.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="training",
seed=123,
image_size=(img_height, img_width),
batch_size=batch_size)
val_ds = tf.keras.utils.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="validation",
seed=123,
image_size=(img_height, img_width),
batch_size=batch_size)
class_names = train_ds.class_names
print(class_names)
for image_batch, labels_batch in train_ds:
print(image_batch.shape)
print(labels_batch.shape)
break
AUTOTUNE = tf.data.AUTOTUNE
train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
normalization_layer = layers.Rescaling(1./255)
normalized_ds = train_ds.map(lambda x, y: (normalization_layer(x), y))
image_batch, labels_batch = next(iter(normalized_ds))
first_image = image_batch[0]
# Notice the pixel values are now in `[0,1]`.
print(np.min(first_image), np.max(first_image))
num_classes = len(class_names)
vgg16_model = keras.applications.vgg16.VGG16()
model = Sequential()
for layer in vgg16_model.layers:
model.add(layer)
print(len(model.layers))
model.summary()
#model.pop()
print(len(model.layers))
for layer in model.layers:
layer.trainable = False
model.add(Dense(1000, activation = 'softmax'))
model.add(Dense(5, activation = 'softmax'))
print(len(model.layers))
model.summary()
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
epochs=10
history = model.fit(
train_ds,
validation_data=val_ds,
epochs=epochs
)
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')
plt.show()

Why my Keras Image classification prediction always return one value...?

I am using CNN to classify multiple people. People's number is 114 and each has about 120 image dataset.
I use keras and model that is used in dog vs cat classification.
It works well in Dogs and Cat classification.
But this is only return same value in different person image.
It says accuracy 99.12 but not work.
this is my train code
# coding: utf-8
# In[1]:
import os
import cv2
import numpy as np
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import OneHotEncoder
from sklearn.cross_validation import train_test_split
from keras import backend as K
from keras import layers, models, optimizers
from keras.preprocessing.image import ImageDataGenerator, img_to_array, array_to_img
from keras.applications.resnet50 import preprocess_input
from keras.utils import np_utils
from numpy import array
# In[2]:
TRAIN_DIR = './Dataset'
train_folder_list = array(os.listdir(TRAIN_DIR))
# In[13]:
X = []
Y = []
# In[14]:
label_encoder = LabelEncoder()
integer_encoded = label_encoder.fit_transform(train_folder_list)
onehot_encoder = OneHotEncoder(sparse=False)
integer_encoded = integer_encoded.reshape(len(integer_encoded), 1)
onehot_encoded = onehot_encoder.fit_transform(integer_encoded)
for idx, index in enumerate(range(len(train_folder_list))):
path = os.path.join(TRAIN_DIR, train_folder_list[index])
path = path + '/'
img_list = os.listdir(path)
for img in img_list:
img_path = os.path.join(path, img)
img = cv2.imread(img_path)
if img is not None:
img = cv2.resize(img, (100, 100))
img = img_to_array(img)
X.append(img)
Y.append(idx)
X = np.array(X, dtype="float") / 255.0
# In[15]:
(X_train, X_test, Y_train, Y_test) = train_test_split(X,Y,test_size=0.2, random_state = 42)
Y_train = np_utils.to_categorical(Y_train, len(train_folder_list))
Y_test = np_utils.to_categorical(Y_test, len(train_folder_list))
print(X_train[0])
# In[17]:
nb_train_samples = len(X_train)
nb_valivation_samples = len(X_test)
batch_size = 32
# In[18]:
print(K.image_data_format())
# In[19]:
model = models.Sequential()
model.add(layers.Conv2D(32, (3,3), input_shape=(100, 100, 3)))
model.add(layers.Activation('relu'))
model.add(layers.MaxPooling2D(pool_size=(2, 2)))
model.add(layers.Conv2D(32, (3, 3)))
model.add(layers.Activation('relu'))
model.add(layers.MaxPooling2D(pool_size=(2, 2)))
model.add(layers.Conv2D(64, (3, 3)))
model.add(layers.Activation('relu'))
model.add(layers.MaxPooling2D(pool_size=(2, 2)))
model.add(layers.Flatten())
model.add(layers.Dense(500))
model.add(layers.Activation('relu'))
model.add(layers.Dropout(0.5))
model.add(layers.Dense(114))
model.add(layers.Activation('softmax'))
model.compile(loss='binary_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
model.summary()
# In[20]:
train_datagen = ImageDataGenerator(
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
rescale=1. / 255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest')
test_datagen = ImageDataGenerator(
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
rescale=1. / 255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest')
# In[21]:
train_generator = train_datagen.flow(X_train, Y_train, batch_size=batch_size)
test_generator = test_datagen.flow(X_test , Y_test, batch_size=batch_size)
print(train_generator)
# In[ ]:
history = model.fit_generator(
train_generator,
steps_per_epoch=nb_train_samples // batch_size,
epochs=3,
validation_data=test_generator,
validation_steps=nb_valivation_samples // batch_size
)
model.save_weights('model_weights.h5')
model.save('model_keras.h5')
and my test code
from keras.models import load_model
import cv2
from keras.applications.resnet50 import preprocess_input
import numpy as np
model = load_model('model_keras.h5')
img = cv2.imread('input_test.jpg')
if img is not None:
img = cv2.resize(img, (100,100), interpolation=cv2.INTER_CUBIC)
img = np.reshape(img,[1,100,100,3])
img = preprocess_input(img)
classes = model.predict_classes(img)
print(classes)
Replace binary_crossentropy with categorical_crossentropy like this:
model.compile(loss='categorical_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])

what will happen if an image for testing my cnn model which is trained to detect potholes and garbage receive an non pothole or non garbage image?

I am using keras from tensorflow backend to detect potholes and garbage in my trained model. The output generated for detecting potholes or garbage works fine but when i give a random image of a car or bike or cat or human or building it identifies everything as a garbage class.what should i do now? what should be the optimal output for such cases. I am providig my code here.
#train
import numpy as np
np.random.seed(123) # for reproducibility
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Convolution2D, MaxPooling2D
from keras.utils import np_utils
from dataset_pothole import pothole
from keras.models import model_from_json
# 4. Load pre-shuffled MNIST data into train and test sets
(X_train, y_train), (X_test, y_test) = pothole.load_data()
# 5. Preprocess input data
X_train = X_train.reshape(X_train.shape[0], 50, 50, 3)
X_test = X_test.reshape(X_test.shape[0], 50, 50, 3)
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
X_test /= 255
# 6. Preprocess class labels
Y_train = np_utils.to_categorical(y_train, 2)
Y_test = np_utils.to_categorical(y_test, 2)
# 7. Define model architecture
model = Sequential()
model.add(Convolution2D(32, 3, 3, activation='relu', input_shape=(50, 50, 3)))
model.add(Convolution2D(32, 3, 3, activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(3, activation='softmax'))
# 8. Compile model
model.compile(loss='categorical_crossentropy',
optimizer='adam',
metrics=['accuracy'])
# 9. Fit model on training data
model.fit(X_train, Y_train,
batch_size=32, nb_epoch=20, verbose=1)
# 10. Evaluate model on test data
score = model.evaluate(X_test, Y_test, verbose=0)
model_json = model.to_json()
with open("model.json", "w") as json_file:
json_file.write(model_json)
# serialize weights to HDF5
model.save_weights("model.h5")
print("Saved model to disk")
print('Test loss: ', score[0])
print('Test accuracy: ', score[1])
#evaluation
import numpy as np
np.random.seed(123) # for reproducibility
import keras
from keras.utils import np_utils
from keras.models import model_from_json
import os
from PIL import Image
from numpy import *
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Convolution2D, MaxPooling2D
img = input("Please enter the test filename:")
test = array(array(Image.open(img)).flatten())
print(test.shape)
X_test = test.reshape((1, 50, 50, 3))
print(X_test.shape)
json_file = open('model.json', 'r')
loaded_model_json = json_file.read()
json_file.close()
loaded_model = model_from_json(loaded_model_json)
# load weights into new model
loaded_model.load_weights("model.h5")
#loaded_model.compile(loss='categorical_crossentropy',
# optimizer='adam',
# metrics=['accuracy'])
prediction = loaded_model.predict_classes(X_test)
print(prediction)
print(loaded_model.predict(X_test))
if prediction==[1]:
print("Pothole")
elif prediction==[0]:
print("Garbage")
else:
print("Invalid Image!")