keras model prediction only one and zero instead of probability - tensorflow

This is my model and data generator, when I predicted I got array([0., 0., 0., 1., 0., 0., 0., 0.] instead of probability. I think it should be a probability.
model = keras.models.Sequential()
model.add ...
model.add(keras.layers.Dense(num_class))
model.add(keras.layers.Softmax())
sgd_opt = keras.optimizers.SGD(lr=0.001, momentum=0.9)
cce_loss = keras.losses.categorical_crossentropy
model.compile(optimizer=sgd_opt, loss='sparse_categorical_crossentropy', metrics=['accuracy'])
train_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size=IMAGE_SIZE,
batch_size=batch_size,
class_mode='sparse')
validation_generator = train_datagen.flow_from_directory(
test_data_dir, # same directory as training data
target_size=IMAGE_SIZE,
batch_size=batch_size,
class_mode='sparse')

Looks like your model literally remembered labels for samples.
Validating on training data is bad practice. Try to split datasets:
from tensorflow.keras.preprocessing.image import ImageDataGenerator
train_datagen = ImageDataGenerator(
validation_split=0.2
)
train_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size=IMAGE_SIZE,
batch_size=batch_size,
subset='training',
class_mode='sparse'
)
validation_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size=IMAGE_SIZE,
batch_size=batch_size,
subset='validation',
class_mode='sparse')

Related

For test_datagen.flow from directory, what should I specify the class_mode?

I'm attempting to create a CNN model using image data. My entire data set was divided into train, test, and validation. I used class_mode = 'categorical' for the training data since training data needs labels, and class_mode = None for the test data because testing shouldn't be done with labels.
the snippet of code
train_datagen = ImageDataGenerator(
rescale=1 / 255.0,
rotation_range=20,
zoom_range=0.05,
width_shift_range=0.05,
height_shift_range=0.05,
shear_range=0.05,
horizontal_flip=True,
vertical_flip=True,
fill_mode="nearest"
)
test_datagen = ImageDataGenerator(
rescale=1/255,
)
train_generator = train_datagen.flow_from_directory(
directory=train_dir,
target_size=(height, width),
batch_size=batch_size,
class_mode='categorical',
shuffle=True,
seed=42
)
valid_generator = train_datagen.flow_from_directory(
directory=val_dir,
target_size=(height, width),
batch_size=batch_size,
class_mode='categorical',
shuffle=True,
seed=42
)
test_generator = test_datagen.flow_from_directory(
"/content/drive/MyDrive/MonkeyPox/output/test",
target_size=(height, width),
batch_size=1,
class_mode=None, **here**
shuffle=False,
seed=42
)
when I specify class_moede=None in the test_generator,
model.evaluate(test_generator, batch_size=16)
the loss & accuracy is [0.0, 0.0], which means my model is failed to evaluate
again when I specify class_moede='categorical' in the test_generator`` ,
model.evaluate(test_generator, batch_size=16)
it gives a certain loss and accuracy
My question is why i am getting [0.0, 0.0] when i am using class_moede=None in the test_generator ?

Getting wrong y_pred values from model.predict

First of all I am very new to deep learning. Here I want to create a confusion matrix. For this reason, I need y_pred and y_true. I calculated y_true and y_pred the following way:
y_true = test_gen.classes
y_pred = (model.predict(test_gen)>0.5).astype("int32")
My confusion matrix code is:
from sklearn.metrics import classification_report, confusion_matrix
print('Confusion Matrix')
print(confusion_matrix(y_true, y_pred ))
mat = confusion_matrix(y_true, y_pred)
I set metrics=['accuracy','TruePositives', 'TrueNegatives', 'FalsePositives', 'FalseNegatives'] in my model.compile
best_model = model
best_model.load_weights('./classify_model.h5')
best_model.evaluate(test_gen)
The value that I get for TruePositives,TrueNegatives, FalsePositives,FalseNegatives from best_model.evaluate(test_gen) don't match with my confusion matrix value.
My Train dataset:
My test dataset:
target_size=(224,224)
batch_size=64
train_datagen = ImageDataGenerator(
preprocessing_function=tf.keras.applications.resnet_v2.preprocess_input,
horizontal_flip=True, zoom_range=0.1
)
test_datagen = ImageDataGenerator(
preprocessing_function=tf.keras.applications.resnet_v2.preprocess_input
)
train_gen = train_datagen.flow_from_dataframe(
train_df,
directory=train_path,
x_col='file_paths',
y_col='labels',
target_size=target_size,
batch_size=batch_size,
color_mode='rgb',
class_mode='binary'
)
valid_gen = test_datagen.flow_from_dataframe(
valid_df,
directory=train_path,
x_col='file_paths',
y_col='labels',
target_size=target_size,
batch_size=batch_size,
color_mode='rgb',
class_mode='binary'
)
test_gen = test_datagen.flow_from_dataframe(
test_df,
directory=test_path,
x_col='file_paths',
y_col='labels',
target_size=target_size,
batch_size=batch_size,
color_mode='rgb',
class_mode='binary'
)
base_model = tf.keras.applications.ResNet50V2(include_top=False, input_shape=(224,224,3))
model = tf.keras.Sequential([
base_model,
tf.keras.layers.GlobalAveragePooling2D(),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(1, activation='sigmoid')
])
lr=0.001
model.compile(loss='binary_crossentropy', optimizer=Adam(learning_rate=lr), metrics=['accuracy', 'TruePositives', 'TrueNegatives', 'FalsePositives', 'FalseNegatives'])
I am having trouble calculating y_true and y_pred correctly. Please help me to construct confusion matrix for this code.

How to solve ValueError in model.predict()?

I am new in neural network problems. I have searched for couple of hours but could not understand what should I do to fix this issue! I'm working with nsl-kdd dataset for intrusion detection system with convolutional neural net.
I stuck with this problem : ValueError: Input 0 of layer dense_14 is incompatible with the layer: expected axis -1 of input shape to have value 3904 but received input with shape [None, 3712]
Shapes:
x_train (125973, 122)
y_train (125973, 5)
x_test (22544, 116)
y_test (22544,)
After reshape :
x_train = np.reshape(x_train, (x_train.shape[0], x_train.shape[1], 1)) #(125973, 122, 1)
x_test = np.reshape(x_test, (x_test.shape[0], x_test.shape[1], 1)) #(22544, 116, 1)
Model :
model = Sequential()
model.add(Convolution1D(64, 3, padding="same",activation="relu",input_shape = (x_train.shape[1], 1)))
model.add(MaxPooling1D(pool_size=(2)))
model.add(Flatten())
model.add(Dense(128, activation="relu"))
model.add(Dropout(0.5))
model.add(Dense(5, activation="softmax"))
Compile :
model.compile(optimizer = 'adam', loss = 'categorical_crossentropy', metrics = ['accuracy'])
model.fit(x_train, Y_train, epochs = 5, batch_size = 32)
pred = model.predict(x_test) #problem is occurring for this line
y_pred= np.argmax(pred, axis = 1)
model summary
Your x_test should have same dimensions as x_train.
x_train = (125973, 122, 1)
x_test = (22544, 116, 1) # the second parameter must match the train set
Code sample:
import tensorflow as tf
import pandas as pd
import numpy as np
from tensorflow.keras.layers import *
from tensorflow.keras import *
x1 = np.random.uniform(100, size =(125973, 122,1))
x2 = np.random.uniform(100, size =(22544, 122, 1))
y1 = np.random.randint(100, size =(125973,5), dtype = np.int32)
y2 = np.random.randint(2, size =(22544, ), dtype = np.int32)
def create_model2():
model = Sequential()
model.add(Convolution1D(64, 3, padding="same",activation="relu",input_shape = (x1.shape[1], 1)))
model.add(MaxPooling1D(pool_size=(2)))
model.add(Flatten())
model.add(Dense(128, activation="relu"))
model.add(Dropout(0.5))
model.add(Dense(5, activation="softmax"))
model.compile(optimizer = 'adam', loss = 'categorical_crossentropy', metrics = ['accuracy'])
return model
model = create_model2()
tf.keras.utils.plot_model(model, 'my_first_model.png', show_shapes=True)
You model looks like this:
Now if use your test set to create your model keeping your dimension as (22544, 116, 1).
You get a model that looks this.
As the dimensions are different the expected input and output of each layers are different.
When you have appropriate test dimensions the output works as expected:
pred = model.predict(x2)
pred
Output:
array([[1., 0., 0., 0., 0.],
[1., 0., 0., 0., 0.],
[1., 0., 0., 0., 0.],
...,
[1., 0., 0., 0., 0.],
[1., 0., 0., 0., 0.],
[1., 0., 0., 0., 0.]], dtype=float32)
Problem: The problem is that your test set does have the same dimensions as your training set. The test set should look as if you took a sample from your training set. So if your training set has the dimensions x_train.shape = (125973, 122) and y_train.shape = (125973, 5). Then your test set should have the dimensions x_test.shape = (sample_num, 122) and y_test.shape = (sample_num, 5).
Possible Solution: An easy way to do testing if you didn't want to use your test set with be with a validation split in the .fit().
So this: model.fit(x_train, Y_train, epochs = 5, batch_size = 32)
would turn into this: model.fit(x_train, Y_train, epochs = 5, batch_size = 32, validation_split=0.2)
This would chop off 20% of your training data and use that for testing. Then after every epoch, TensorFlow will print how the network performed on that validation data so that you can see how your model performs on data it has never seen before.

what is wrong with the metrics arg in this code?

please look at this code
solver = Adam(learning_rate = 0.001)
model.compile(
optimizer=solver,
loss='binary_crossentropy',
metrics=[
metrics.SensitivityAtSpecificity(0.5),
metrics.SpecificityAtSensitivity(0.5),
metrics.Precision(),
metrics.Accuracy(),
metrics.AUC()
]
)
train_datagen = ImageDataGenerator(
rescale=1./255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
vertical_flip=True,
rotation_range=270,
)
test_datagen = ImageDataGenerator(rescale=1./255)
train_set = train_datagen.flow_from_directory(
'DFU_Dataset/training',
target_size=(256, 256),
batch_size=8,
class_mode='binary')
test_set = test_datagen.flow_from_directory(
'DFU_Dataset/testing',
target_size=(256, 256),
batch_size=8,
class_mode='binary')
up to here everything executes fine with no errors or warnings at all, now when i execute this next part :
model.fit(
train_set,
epochs=40,
validation_split= 5.9,
verbose=1
)
i get : "ValueError: Shapes (None, 2) and (None, 1) are incompatible".
now when i completely remove the metrics arg like in here :
model.compile(
optimizer=solver,
loss='binary_crossentropy'
)
everything works fine and starts training.
can you please point out what am doing wrong and a way to fix it.
I think the root-cause is shape mismatch between data and prediction.
Last layer for the binary classification should have
Dense(1, activation='sigmoid')
Based on the above model.summary(), currently you have 2 nodes in the output layer whereas some metrics are looking for single output.

Tensorflow-keras : CNN predictions are very close to 1 or 0

I trained a CNN on 96x96 bacterias images. I have 3 classes : "bacterias", "flocs" and "nothing".
Then, to detect bacterias on a 1920x1080 image, I scan the image with 96x96 windows and I run my CNN for all scanned windows.
But my predictions are always [0,1,0] like. And I never have eg. [0.1, 0.8, 0.1]
Here is my model :
batch_size = 32
nb_epochs = 10
taille_image = (96,96)
model = Sequential()
model.add(Conv2D(16, (3, 3), input_shape=(96, 96, 3)))
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(Dropout(0.5))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(3))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy',
optimizer='adam',
metrics=['accuracy'])
def Entrainer():
train_datagen = ImageDataGenerator(
rescale=1./255,
horizontal_flip=True,
vertical_flip=True,
validation_split=0.2)
train_generator = train_datagen.flow_from_directory(
"Images_traitees/Vignettes_squared",
target_size = taille_image,
batch_size=batch_size,
class_mode="categorical",
shuffle=True,
save_to_dir="augmented_data",
save_prefix="augmented_",
save_format="jpeg",
subset="training"
)
validation_generator = train_datagen.flow_from_directory(
"Images_traitees/Vignettes_squared",
target_size = taille_image,
batch_size=batch_size,
class_mode="categorical",
subset="validation"
)
tbCallback = keras.callbacks.TensorBoard(log_dir='./Graph', histogram_freq=0, write_graph=True, write_images=True)
history = model.fit_generator(
train_generator,
steps_per_epoch=train_generator.samples // batch_size,
validation_data = validation_generator,
validation_steps = validation_generator.samples // batch_size,
epochs=nb_epochs,
callbacks = [tbCallback]
)
plt.plot(history.history['acc'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.show()
plt.plot(history.history['loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.show()
model.save("my_model.h5")
if __name__ == "__main__":
model.summary()
Entrainer()
tensorboard results
And this is the code to call my model and color the the detected class.
model = load_model("my_model.h5")
model.compile(loss='categorical_crossentropy',
optimizer='adam',
metrics=['accuracy'])
def Predire(img, vignettes, pos):
image = Image.open(img)
draw = ImageDraw.Draw(image, mode='RGBA')
for vignette in vignettes:
x = img_to_array(vignette)
x = np.expand_dims(x, axis=0)
y = model.predict(x)
if y[0][1] > max (y[0][0],y[0][2]):
draw.rectangle(pos[nb], outline='red', fill=(255,0,0,125))
proto +=1
if y[0][0] > max (y[0][1],y[0][2]):
draw.rectangle(pos[nb], outline='blue', fill=(0,0,255,125))
floc +=1
if y[0][2] > max(y[0][1],y[0][0]):
draw.rectangle(pos[nb], outline='black')
print (y)
return image
When I print y, it returns :
[[0. 0. 1.]]
[[0. 0. 1.]]
[[0. 0. 1.]]
[[0. 0. 1.]]
[[1. 0. 0.]]
[[1. 0. 0.]]
[[1. 0. 0.]]
[[1. 0. 0.]]
[[1. 0. 0.]]
[[1. 0. 0.]]
[[1. 0. 0.]]
[[1.0000000e+00 1.7819082e-33 0.0000000e+00]]
[[1. 0. 0.]]
...
Each line represents the CNN prediction of a 96x96 sliding windows of the entire image.
I thought it was overfitting, but i tried with only 735 trainable parameters and i have still the same pb.
It might be the case that your model has heavily overfitted the data. Check your models accuracy on your training vs your test set and see if they are reasonable.
Update: Turns out preprocessing of the image data was the problem. Always make sure you apply the same preprocessing to both training, validation and test set.