Keras model.predict always 0 - python

I am using keras applications for transfer learning with resnet 50 and inception v3 but when predicting always get [[ 0.]]
The below code is for a binary classification problem. I have also tried vgg19 and vgg16 but they work fine, its just resnet and inception. The dataset is a 50/50 split. And I am only changing the model = applications.resnet50.ResNet50 line of code for each model.
below is the code:
from keras.callbacks import EarlyStopping
early_stopping = EarlyStopping(monitor='val_loss', patience=2)
img_width, img_height = 256, 256
train_data_dir = xxx
validation_data_dir = xxx
nb_train_samples = 14000
nb_validation_samples = 6000
batch_size = 16
epochs = 50
if K.image_data_format() == 'channels_first':
input_shape = (3, img_width, img_height)
else:
input_shape = (img_width, img_height, 3)
model = applications.resnet50.ResNet50(weights = "imagenet", include_top=False, input_shape = (img_width, img_height, 3))
from keras.callbacks import EarlyStopping
early_stopping = EarlyStopping(monitor='val_loss', patience=2)
img_width, img_height = 256, 256
train_data_dir = xxx
validation_data_dir = xxx
nb_train_samples = 14000
nb_validation_samples = 6000
batch_size = 16
epochs = 50
if K.image_data_format() == 'channels_first':
input_shape = (3, img_width, img_height)
else:
input_shape = (img_width, img_height, 3)
model = applications.resnet50.ResNet50(weights = "imagenet", include_top=False, input_shape = (img_width, img_height, 3))
#Freeze the layers which you don't want to train. Here I am freezing the first 5 layers.
for layer in model.layers[:5]:
layer.trainable = False
#Adding custom Layers
x = model.output
x = Flatten()(x)
x = Dense(1024, activation="relu")(x)
x = Dropout(0.5)(x)
#x = Dense(1024, activation="relu")(x)
predictions = Dense(1, activation="sigmoid")(x)
# creating the final model
model_final = Model(input = model.input, output = predictions)
# compile the model
model_final.compile(loss = "binary_crossentropy", optimizer = optimizers.SGD(lr=0.0001, momentum=0.9), metrics=["accuracy"])
# Initiate the train and test generators with data Augumentation
train_datagen = ImageDataGenerator(
rescale=1. / 255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
test_datagen = ImageDataGenerator(
rescale=1. / 255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
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')
# Save the model according to the conditions
#checkpoint = ModelCheckpoint("vgg16_1.h5", monitor='val_acc', verbose=1, save_best_only=True, save_weights_only=False, mode='auto', period=1)
#early = EarlyStopping(monitor='val_acc', min_delta=0, patience=10, verbose=1, mode='auto')
model_final.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,
callbacks=[early_stopping])
from keras.models import load_model
import numpy as np
from keras.preprocessing.image import img_to_array, load_img
#test_model = load_model('vgg16_1.h5')
img = load_img('testn7.jpg',False,target_size=(img_width,img_height))
x = img_to_array(img)
x = np.expand_dims(x, axis=0)
#preds = model_final.predict_classes(x)
prob = model_final.predict(x, verbose=0)
#print(preds)
print(prob)
Note That model_final.evaluate_generator(validation_generator, nb_validation_samples) provides an expected accuracy like 80% its just predict that is always 0.
Just find it strange that vgg19 and vgg16 work fine but not resnet50 and inception. Do these models require something else to work?
Any insight would be great.
Thanks in advance.

I was running into similar problem. You are scaling all the RGB values from 0-255 to 0-1 during training.
Thse same should be done at the time of prediction.
Try
x = img_to_array(img)
x = x/255

Related

how to extract features from an image using VGG16 and predict images by SVM

i want to extract feature by using vgg16 to train ML like (SVM, RF,...) for i can classifie images and visualise them.
i already creat a model by vgg16 but i have diffecult to visualise test images and predict them by using ML.any help please
VGG16 = VGG16(input_shape=IMAGE_SIZE + [3], weights='imagenet',
include_top=False)
for layer in VGG16.layers:
layer.trainable = False
folders = glob('')
x = Flatten()(VGG16.output)
x = Dense(4096, activation='relu')(x)
x = Dropout(0.5)(x)
x = Dense(4096, activation='relu')(x)
x = Dropout(0.3)(x)
prediction = Dense(len(folders), activation='sigmoid')(x)
model = Model(inputs=VGG16.input, outputs=prediction)
model.summer()
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_set = train_datagen.flow_from_directory('
apple_disease_classification/Train',
target_size = (224, 224),
batch_size = 32,
class_mode = 'categorical')
test_set = test_datagen.flow_from_directory('
apple_disease_classification/Test',
target_size = (224, 224),
batch_size = 32,
class_mode = 'categorical')
r = model.fit_generator(
training_set,
validation_data=test_set,
epochs=50,
steps_per_epoch=len(training_set),
validation_steps=len(test_set))

TensorFlow results are not reproducible while the global seed is set - Python - Tensorflow - MacOS M1

My results are not reproducible while the global seed is set. Am I doing something wrong or is this an issue of the macbook M1?
I am using:
MacOS 12.5
Python 3.10.6
tensorflow-macos 2.9.2
The terminal is opened using the use rosetta option.
Besides, the model is also unusually bad.
The datasets are from https://www.kaggle.com/competitions/dogs-vs-cats
# Imports.
import tensorflow as tf
import numpy as np
# Some global variables.
seed = 1234
batch_size = 32
learning_rate = 0.001
width = 180
height = 180
epochs = 250
# Set the seed.
tf.random.set_seed(seed);
np.random.seed(seed);
# Create the cnn model
def cnn_model():
model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(32, (3,3), activation="relu", input_shape=(width, height, 3)),
tf.keras.layers.MaxPooling2D((2,2)),
tf.keras.layers.Conv2D(64, (3,3), activation="relu"),
tf.keras.layers.MaxPooling2D((2,2)),
tf.keras.layers.Conv2D(128, (3,3), activation="relu"),
tf.keras.layers.MaxPooling2D((2,2)),
tf.keras.layers.Conv2D(128, (3,3), activation="relu"),
tf.keras.layers.MaxPooling2D((2,2)),
tf.keras.layers.Flatten(),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(512, activation="relu"),
tf.keras.layers.Dense(1, activation="sigmoid"),
])
opt = tf.keras.optimizers.Adam(learning_rate=0.001)
model.compile(optimizer=opt, loss="binary_crossentropy", metrics=["accuracy"])
return model
# Load an image for predictions.
def load_image(path):
img = tf.keras.preprocessing.image.load_img(
path,
target_size=(width, height),
color_mode="rgb",
)
img_tensor = tf.keras.preprocessing.image.img_to_array(img)
img_tensor = np.expand_dims(img_tensor, axis=0)
img_tensor /= 255.
return img_tensor
# Dump the evaluation metrics to the console.
def dump_metrics(message, model, metrics):
index, s = 0, ""
for name in model.metrics_names:
s += f" - {name}: {round(metrics[index], 3)}"
index += 1
print(f"{message} {s[3:]}")
# Define the image data generator.
train_datagen = tf.keras.preprocessing.image.ImageDataGenerator(
rescale = 1./255,
# rotation_range = 45,
# width_shift_range = 0.2,
# height_shift_range = 0.2,
# shear_range = 0.2,
# zoom_range = 0.2
)
val_datagen = tf.keras.preprocessing.image.ImageDataGenerator(rescale = 1./255)
# Load the training dataset.
train_df = train_datagen.flow_from_directory(
"datasets/train/",
class_mode="binary",
batch_size=batch_size,
target_size=(width, height),
shuffle=True,
color_mode="rgb",
seed=seed,
)
train_samples_count = len(train_df)
# Load the validation dataset.
val_df = val_datagen.flow_from_directory(
"datasets/val/",
class_mode="binary",
batch_size=batch_size,
target_size=(width, height),
shuffle=True,
color_mode="rgb",
seed=seed,
)
val_samples_count = len(train_df)
# Create the model.
model = cnn_model();
model.summary()
# Training callbacks.
callbacks = []
callbacks.append(tf.keras.callbacks.EarlyStopping(monitor="val_loss", patience=5, restore_best_weights=True))
# Train the model.
history = model.fit(
train_df,
steps_per_epoch=train_samples_count // batch_size,
epochs=epochs,
validation_data=val_df,
validation_steps=val_samples_count // batch_size,
callbacks=callbacks,
)
dump_metrics("Training:", model, model.evaluate(train_df, verbose=0))
dump_metrics("Valiation:", model, model.evaluate(val_df, verbose=0))

create precision/recall curve and roc curve

i'm trying to create a precision/recall curve and an roc curve, but i can't seem to figure out which values from the model i need to capture to do this. i'm building a cnn model for the dogs vs cats kaggle dataset:
img_width = 64
img_height = 64
batch_size = 20
datagen = ImageDataGenerator(rescale=1./255)
train_generator = datagen.flow_from_directory(directory=train_80_data_dir, target_size = (img_width, img_height),
classes = ['dogs', 'cats'], class_mode = 'binary',
batch_size = batch_size, seed=40)
train_generator.classes
test_generator = datagen.flow_from_directory(directory=test_20_data_dir, target_size = (img_width, img_height),
classes = ['dogs','cats'], class_mode = 'binary',
batch_size = batch_size, seed=41)
score_generator = datagen.flow_from_directory(directory=score_data_dir, target_size = (img_width, img_height),
batch_size = 1, class_mode = None, color_mode = "rgb", seed=42)
METRICS = [
tf.keras.metrics.BinaryAccuracy(name='accuracy'),
tf.keras.metrics.TruePositives(name='tp'),
tf.keras.metrics.FalsePositives(name='fp'),
tf.keras.metrics.TrueNegatives(name='tn'),
tf.keras.metrics.FalseNegatives(name='fn'),
tf.keras.metrics.Precision(name='precision'),
tf.keras.metrics.Recall(name='recall'),
tf.keras.metrics.AUC(name='auc'),
]
model1 = Sequential()
model1.add(Conv2D(filters=64, kernel_size=(3,3), activation='relu', padding='same', input_shape = (img_width,
img_height, 3)))
model1.add(MaxPool2D(2,2))
model1.add(Flatten())
model1.add(Dense(128, activation='relu'))
model1.add(Dense(1, activation='sigmoid'))
opt = SGD(learning_rate=0.01, momentum=0.9)
model1.compile(optimizer=opt, loss='binary_crossentropy', metrics=METRICS)
model1.summary()
model1_history = model1.fit_generator(generator=train_generator, steps_per_epoch=len(train_generator), epochs = 5,
validation_data=test_generator, validation_steps=len(test_generator), verbose=1)
score_generator.reset()
prediction_model_1 = model1.predict_generator(score_generator,steps=12500,verbose=1)
i tried doing the following to get values for traing_generator and then try to build the curves, but i don't think that's the right approach?
train_model_1 = model1.predict_generator(train_generator,steps=12500,verbose=1)
it does appear that precision and recall increase at the same time through each epoch, which doesn't make sense either or is that actually possible?
any clarification or guidance is appreciated. thank you.

model.predict() function always returns 1 for binary image classification model

I was working on a binary image classification deep learning model using transfer learning in Google colab.
!wget https://storage.googleapis.com/mledu-datasets/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5 -O /tmp/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5
local_weights_file = '/tmp/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5'
pre_trained_model = InceptionV3(input_shape = (300, 300, 3),
include_top = False,
weights = None)
pre_trained_model.load_weights(local_weights_file)
for layer in pre_trained_model.layers:
layer.trainable = False
last_layer = pre_trained_model.get_layer('mixed7')
last_output = last_layer.output
x = layers.Flatten()(last_output)
x = layers.Dense(512, activation='relu')(x)
x = layers.Dropout(0.2)(x)
x = layers.Dense(1, activation='sigmoid')(x)
model = Model(pre_trained_model.input, x)
from tensorflow.keras.optimizers import RMSprop
model.compile(optimizer=RMSprop(lr=0.0001),
loss='binary_crossentropy',
metrics=['accuracy'])
from tensorflow.keras.preprocessing.image import ImageDataGenerator
train_datagen = ImageDataGenerator(
rescale=1/255,
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode="nearest")
validation_datagen = ImageDataGenerator(rescale=1/255)
train_generator = train_datagen.flow_from_directory(
train_dir,
target_size=(300, 300),
batch_size=100,
class_mode='binary')
validation_generator = validation_datagen.flow_from_directory(
validation_dir,
target_size=(300, 300),
batch_size=100,
class_mode='binary')
history = model.fit(
train_generator,
steps_per_epoch=20,
epochs=30,
verbose=1,
validation_data=validation_generator,
validation_steps=10,
callbacks=[callbacks])
import numpy as np
from google.colab import files
from tensorflow.keras.preprocessing import image
uploaded=files.upload()
for fn in uploaded.keys():
path='/content/' + fn
img=image.load_img(path, target_size=(300, 300))
x=image.img_to_array(img)
x=np.expand_dims(x, axis=0)
images = np.vstack([x])
classes = model.predict(images, batch_size=10)
print(classes)
Even though after training the model and obtaining a quite good accuracy on training and validation data, the model is always predicting 1 for any new image. I have tried changing the batch size, epochs, learning rate, etc. But, no luck.
Can anyone explain what's the problem here?

ValueError: Error when checking target: expected avg_pool to have 4 dimensions, but got array with shape (100, 2)

I try to run this code (binary classification) but still stuck with this error : ValueError: Error when checking target: expected avg_pool to have 4 dimensions, but got array with shape (100, 2)
NUM_CLASSES = 2
CHANNELS = 3
IMAGE_RESIZE = 224
RESNET50_POOLING_AVERAGE = 'avg'
DENSE_LAYER_ACTIVATION = 'softmax'
OBJECTIVE_FUNCTION = 'binary_crossentropy'
NUM_EPOCHS = 10
EARLY_STOP_PATIENCE = 3
STEPS_PER_EPOCH_VALIDATION = 10
BATCH_SIZE_TRAINING = 100
BATCH_SIZE_VALIDATION = 100
resnet_weights_path = '../input/resnet50/resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5'
train_data_dir = "C:\\Users\\Desktop\\RESNET"
model = ResNet50(include_top=True, weights='imagenet')
x = model.get_layer('avg_pool').output
predictions = Dense(1, activation='sigmoid')(x)
model = Model(input = model.input, output = predictions)
print(model.summary())
model.layers.pop()
model = Model(input=model.input,output=model.layers[-1].output)
sgd = optimizers.SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='binary_crossentropy', optimizer=SGD(lr=0.01, momentum=0.9), metrics= ['binary_accuracy'])
data_dir = "C:\\Users\\Desktop\\RESNET"
batch_size = 32
from keras.applications.resnet50 import preprocess_input
from keras.preprocessing.image import ImageDataGenerator
image_size = IMAGE_RESIZE
data_generator = ImageDataGenerator(preprocessing_function=preprocess_input)
def append_ext(fn):
return fn+".jpg"
dir_path = os.path.dirname(os.path.realpath(__file__))
train_dir_path = dir_path + '\data'
onlyfiles = [f for f in listdir(dir_path) if isfile(join(dir_path, f))]
NUM_CLASSES = 2
data_labels = [0, 1]
t = []
maxi = 25145
LieOffset = 15799
i = 0
while i < maxi: # t = tuple
if i <= LieOffset:
t.append(label['Lie'])
else:
t.append(label['Truth'])
i = i+1
train_datagenerator = ImageDataGenerator(rescale=1./255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
validation_split=0.2)
train_generator = train_datagenerator.flow_from_directory(
train_data_dir,
target_size=(image_size, image_size),
batch_size=BATCH_SIZE_TRAINING,
class_mode='categorical', shuffle=False, subset='training') # set as training data
validation_generator = train_datagenerator.flow_from_directory(
train_data_dir, # same directory as training data
target_size=(image_size, image_size),
batch_size=BATCH_SIZE_TRAINING,
class_mode='categorical', shuffle=False, subset='validation')
(BATCH_SIZE_TRAINING, len(train_generator), BATCH_SIZE_VALIDATION, len(validation_generator))
from sklearn.grid_search import ParameterGrid
param_grid = {'epochs': [5, 10, 15], 'steps_per_epoch' : [10, 20, 50]}
grid = ParameterGrid(param_grid)
# Accumulate history of all permutations (may be for viewing trend) and keep watching for lowest val_loss as final model
for params in grid:
fit_history = model.fit_generator(
train_generator,
steps_per_epoch=STEPS_PER_EPOCH_TRAINING,
epochs = NUM_EPOCHS,
validation_data=validation_generator,
validation_steps=STEPS_PER_EPOCH_VALIDATION,
callbacks=[cb_checkpointer, cb_early_stopper]
)
model.load_weights("../working/best.hdf5")
Remove these lines and it'll work,
model.layers.pop()
model = Model(input=model.input,output=model.layers[-1].output)
The former is removing the last(Dense) layer, and the letter means create a model without the last(Flatten, as Dense is already popped) layer.
It doesn't make sense as your target data is (100, 2). Why do you put them there in the first place?
Also I think this line
predictions = Dense(1, activation='sigmoid')(x)
Will error, as your target data is 2 channel, if it does error then change this to
predictions = Dense(2, activation='sigmoid')(x)
Update
The output of avg_pool is 4 dimention, (batch_size, height, width, channel). You need to do the Flatten first or use GlobalAveragePooling2D instead of AveragePooling2D.
Like
x = model.get_layer('avg_pool').output
x = keras.layers.Flatten()(x)
predictions = Dense(1, activation='sigmoid')(x)
Or
model = ResNet50(include_top=False, pooling='avg', weights='imagenet') # `pooling='avg'` makes the `ResNet50` include a `GlobalAveragePoiling` layer and `include_top=False` means that you don't include the imagenet's output layer
x = model.output # as I use `include_top=False`, you don't need to care the layer name, just use the model's output right away
predictions = Dense(1, activation='sigmoid')(x)
Also just as #bit01 said, change class_mode='categorical' to class_mode='binary'.
Change class_mode='categorical' to class_mode='binary' in both train_generator and validation_generator.
Additionally, delete the following lines as you have already created model.
model.layers.pop()
model = Model(input=model.input,output=model.layers[-1].output)
So, your model would be like:
model = ResNet50(include_top=True, weights='imagenet')
x = model.get_layer('avg_pool').output
x = Flatten()(x)
predictions = Dense(1, activation='sigmoid')(x)
model = Model(input = model.input, output = predictions)

Categories

Resources