I have a Tensorflow image classification DNN that uses binary crossentropy as its loss and the corresponding label mode binary in the tf.keras.preprocessing.image_dataset_from_directory call. When i train the model and run inference on images the predictions outputs are something like [[-3.5601902]] or [[2.1026382]]. How im to interpret that to get to which of the two classes the model is assigning the image. I think the answer would be an implementation of a softmax function but im not getting it right.
Call to tf.keras.preprocessing.image_dataset:
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
images_directory,
label_mode="binary",
validation_split=0.2,
subset="training",
seed=123,
image_size=(img_height, img_width),
batch_size=batch_size)
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
images_directory,
label_mode="binary",
validation_split=0.2,
subset="validation",
seed=123,
image_size=(img_height, img_width),
batch_size=batch_size)
and the model
model = Sequential([
layers.experimental.preprocessing.Rescaling(1./255, input_shape=(img_height, img_width, 3)),
layers.Conv2D(16, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Conv2D(32, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Conv2D(64, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Flatten(),
layers.Dense(128, activation='relu'),
layers.Dense(num_classes)
])
model.compile(optimizer='adam',
loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
metrics=['accuracy'])
Also any input on the model would be appreciated.
It is a bit confusing what you are trying to achieve.
If you are doing a binary classification ( which I believe you are ), the size of your output layer should not be 'num_classes', it should be 1 with a sigmod for activation function. if you did that, the output 'p' would be the probability of class 1 and 1-'p' the probability of class 0. It seems that you mixed a bit of multi categorical approach with binary classification.
I guess the only thing possible to say about those values is that they are logit outputs.
Related
I try to load my dataset and design a CNN but when I try to train my model this error came up and I want to know how can I fix this?
ValueError: The channel dimension of the inputs should be defined. Found None.
and this is the way I split data
xtrain, xtest, ytrain, ytest = trian_test_split(images_total,
image_labels,
stratify=image_labels,
random_state=1234,
test_size=0.2)
xvalid, xtest, yvalid, ytest= trian_test_split(xtest,
ytest,
stratify=ytest,
random_state=1234,
test_size=0.5)
def read_img(path, label):
file = tf.io.read_file(path)
img = tf.image.decode_png(file)
img = tf.image.resize(img, (32, 32))
return img, label
train_dataset = tf.data.Dataset.from_tensor_slices((xtrain, ytrain))
train_dataset = train_dataset.map(read_img).batch(batch_size)
valid_dataset = tf.data.Dataset.from_tensor_slices((xvalid, yvalid))
valid_dataset = valid_dataset.map(read_img).batch(batch_size)
test_dataset = tf.data.Dataset.from_tensor_slices((xtest, ytest))
test_dataset = test_dataset.map(read_img).batch(batch_size)
And this is my model
num_classes = 26
model = tf.keras.Sequential([
tf.keras.layers.experimental.preprocessing.Resizing(32, 32),
tf.keras.layers.experimental.preprocessing.Rescaling(1./255),
tf.keras.layers.Conv2D(32, 3, activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Conv2D(32, 3, activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Conv2D(32, 3, activation='relu'),
tf.keras.layers.MaxPooling2D(),
layers.Dropout(0.2),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(num_classes)
])
model.compile(
optimizer='adam',
loss=tf.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
model.fit(train_dataset, epochs=5, validation_data=valid_dataset)
when I try to fit this model the error came up and I can't fix this
You haven't passed y label to model while calling, model needs both and x and y label to train accordingly,
Here i added an example
please take a pause and go through videos of keras architecture and documentation in keras io these would give more information about deep learning modelling
once after you got familiar with all, jump to modelling
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=3)
I'm building a Tensorflow/Keras multiclassification model to identify 33 different species of birds. I've around 33,000 images and I've cleaned and removed the corrupt images and reduced the size of the images down from ~4347x3260 to 512x512 while retaining the aspect ratio.
I'm using a batch size of 32, input image size: 250x250. I've split the training/validation/test datasets into ratios of 80:10:10 which consists of 26253 training images, 3266 validation images and 3311 test images.
I've set the seed for the training image generator but the problem I've ran into is that when I change the number of layers/architecture the model stops improving at roughly the same level, around the 50% accuracy level and the validation/training curve remains flat albeit a gap starts to open up as seen in the figures below, a sign of overfitting but it retains the gap more or less.
Updated Validation/Training Accuracy
Updated Validation/Training Loss
So, I plotted the graph of the optimized learning rate curve shown below and it is flat. I chose 1e-4 as my base learning rate and 1e-2 as my max learning rate and implemented a CLR as shown by Smith. You can see the results below. Now it does improve the validation accuracy to around 58% at present and it hasn't started to really overfit yet, in fact all the curves are only slightly overfitting besides the original baseline graph. Maybe if I reduce the learning rate interval, the plot would give a better view of the curve.
But would it be worth to train it for longer or can someone advise on the next steps to take? Any advice is welcome.
I've added updates to the graphs.
batch_size = 32
epochs = 2000
IMG_HEIGHT = 250
IMG_WIDTH = 250
STEPS_PER_EPOCH = count_data_items(os.path.join(data_dir, 'train')) // batch_size
training_dir = 'train_test_val/train'
# All images will be rescaled by 1./255
train_datagen = ImageDataGenerator(
rescale=1./255,
rotation_range=45,
zoom_range=0.15,
width_shift_range=0.1,
height_shift_range=0.1,
shear_range=0.15,
horizontal_flip=True,
vertical_flip=True,
fill_mode="reflect"
)
print("The number of training images: ")
train_datagen = train_datagen.flow_from_directory(
directory = training_dir,
shuffle=True,
target_size=(IMG_HEIGHT, IMG_WIDTH),
batch_size=batch_size,
seed=123,
class_mode='categorical'
)
test_dir = 'train_test_val/test'
print("The number of test images: ")
# All images will be rescaled by 1./255
test_datagen = ImageDataGenerator(rescale=1./255)
test_datagen = test_datagen.flow_from_directory(
directory = test_dir,
target_size=(IMG_HEIGHT, IMG_WIDTH),
batch_size=batch_size,
#seed=123,
class_mode='categorical'
)
val_dir = 'train_test_val/val'
print("The number of validation images: ")
# All images will be rescaled by 1./255
val_datagen = ImageDataGenerator(rescale=1./255)
val_datagen = val_datagen.flow_from_directory(
directory = val_dir,
target_size=(IMG_HEIGHT, IMG_WIDTH),
batch_size=batch_size,
#seed=123,
class_mode='categorical'
)
clr_step_size = int(4 * STEPS_PER_EPOCH)
base_lr = 1e-4
max_lr = 1e-2
mode='triangular'
# The mode is set to triangular: that's equal to linear moce.
def get_callbacks():
return [
tf.keras.callbacks.TensorBoard(log_dir=run_logdir, histogram_freq=0, embeddings_freq=0, update_freq='epoch'),
tf.keras.callbacks.EarlyStopping(monitor='val_loss', min_delta=0, patience=21, verbose=1),
#tf.keras.callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=8,verbose=1),
tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_path, monitor ='val_loss', save_best_only=True, verbose=1),
CyclicLR(base_lr=base_lr, max_lr=max_lr, step_size=clr_step_size, mode=mode)
#tf.keras.callbacks.CSVLogger(filename=csv_logger, separator=',', append=True)
]
def fit_model(model, n_epochs, initial_epoch=0, batch_size=batch_size):
print("Fitting model on training data")
history = model.fit(
train_datagen,
steps_per_epoch=STEPS_PER_EPOCH,
epochs=n_epochs,
validation_data=val_datagen,
validation_steps=n_val // batch_size,
callbacks=get_callbacks(),
verbose=1,
initial_epoch = initial_epoch
)
model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(32, (3,3), activation='relu', input_shape=(IMG_HEIGHT, IMG_WIDTH, 3)),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.MaxPooling2D(pool_size=(2,2)),
tf.keras.layers.Conv2D(64, (3,3), padding='same', activation='relu'),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.MaxPooling2D(pool_size=(2,2)),
tf.keras.layers.Conv2D(128, (3,3), padding='same', activation='relu'),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.MaxPooling2D(pool_size=(2,2)),
tf.keras.layers.Conv2D(256, (3,3), padding='same', activation='relu'),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.MaxPooling2D(pool_size=(2,2)),
tf.keras.layers.Conv2D(512, (3,3), padding='same', activation='relu'),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.MaxPooling2D(pool_size=(2,2)),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(512, activation='relu'),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.Dense(256, activation='relu'),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.Dense(num_classes, activation='softmax')
])
model.compile(optimizer=optimizers.RMSprop(),
loss='categorical_crossentropy',
metrics=['accuracy'])
Edit: 20/03/2021 Applied InceptionV3 Transfer Learning Model and the Accuracy stalls out at 50%.
I'm trying to train a model on the stanford_dogs dataset to classify 120 dog breeds but my code is acting strange.
I downloaded the image data from http://vision.stanford.edu/aditya86/ImageNetDogs/images.tar
Then ran the following code to split each folder of the breeds into training and testing folders:
dataset_dict = {}
source_path = 'C:/Users/visha/Downloads/stanford_dogs/dataset'
dir_root = os.getcwd()
dataset_folders = [x for x in os.listdir(os.path.join(dir_root, source_path)) if os.path.isdir(os.path.join(dir_root, source_path, x))]
for category in dataset_folders:
dataset_dict[category] = {'source_path': os.path.join(dir_root, source_path, category),
'train_path': create_folder(new_path='C:/Users/visha/Downloads/stanford_dogs/train',
folder_type='train',
data_class=category),
'validation_path': create_folder(new_path='C:/Users/visha/Downloads/stanford_dogs/validation',
folder_type='validation',
data_class=category)}
dataset_folders = [x for x in os.listdir(os.path.join(dir_root, source_path)) if os.path.isdir(os.path.join(dir_root, source_path, x))]
for key in dataset_dict:
print("Splitting Category {} ...".format(key))
split_data(source_path=dataset_dict[key]['source_path'],
train_path=dataset_dict[key]['train_path'],
validation_path=dataset_dict[key]['validation_path'],
split_size=0.7)
I fed the images through the network after some image augmentation and used sigmoid activation in the final layer and categorical_crossentropy loss.
import tensorflow as tf
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.optimizers import RMSprop
model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(16, (3, 3), activation='relu', input_shape=(150, 150, 3)),
tf.keras.layers.MaxPooling2D(2, 2),
tf.keras.layers.Conv2D(32, (3, 3), activation='relu'),
tf.keras.layers.MaxPooling2D(2, 2),
tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),
tf.keras.layers.MaxPooling2D(2, 2),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(512, activation='relu'),
tf.keras.layers.Dense(120, activation='softmax')
])
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
TRAINING_DIR = 'C:/Users/visha/Downloads/stanford_dogs/train'
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')
train_generator = train_datagen.flow_from_directory(TRAINING_DIR,
batch_size=10,
class_mode='categorical',
target_size=(150, 150))
VALIDATION_DIR = 'C:/Users/visha/Downloads/stanford_dogs/validation'
validation_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_generator = validation_datagen.flow_from_directory(VALIDATION_DIR,
batch_size=10,
class_mode='categorical',
target_size=(150, 150))
history = model.fit(train_generator,
epochs=10,
verbose=1,
validation_data=validation_generator)
But the code is not working as intended. The val_accuracy after 10 epochs is something like 4.756.
For validation data you should not do any image augmentation, just do rescale. In validation flow_from_directory set shuffle=False. Be advised that the Stanford Dog Data set is very difficult. To achieve a reasonable degree of accuracy you will need a much more complex model. I recommend you consider transfer learning using the Mobilenet model. The code below shows how to do that.
base_model=tf.keras.applications.mobilenet.MobileNet( include_top=False,
input_shape=(150,150,3) pooling='max', weights='imagenet',dropout=.4)
x=base_model.output
x=keras.layers.BatchNormalization(axis=-1, momentum=0.99, epsilon=0.001 )(x)
x = Dense(1024, activation='relu')(x)
x=Dropout(rate=.3, seed=123)(x)
output=Dense(120, activation='softmax')(x)
model=Model(inputs=base_model.input, outputs=output)
model.compile(Adamax(lr=.001),loss='categorical_crossentropy',metrics=
['accuracy'] )
I forgot to mention that Mobilenet was trained on Images with pixel values in the range -1 to +1. So in ImageDataGenerator include the code
preprocessing_function=tf.keras.applications.mobilenet.preprocess_input
this scales the pixels so you do not need the code
rescale=1./255
or alternatively set
rescale=1/157.5-1
which will rescale the values between -1 and +1
I'm trying to implement a Convolutional Neural Network that can detect whether a person is wearing glasses or not. Unfortunately, I keep getting very strange results no matter which exact settings I use for learning rate, the specific optimizer, etc. With most settings, I notice that the accuracy of my model doesn't change after the second epoch and gets stuck at around 0.56 (which is close to the ratio of one label, 2700 images, compared to the other label, 2200 images). In other runs, with slightly different settings, the accuracy suddenly rockets to about 0.9 and keeps increasing. In both cases, however, the model predicts the exact same classification ('with glasses') each time (even on images that were in the training/validation set), always with a confidence level of 100% (the label is exactly 1 each time).
I'm not all that experienced with Neural Networks for image classification so I wasn't quite sure how to figure out the issue. I tried printing some values from my dataset and their respective labels, and the labels do contain both labels (0s and 1s). Therefore, I assume it's probably an issue with my model but I can't really figure out much myself. I've tried different optimizers (Adam, SGD mostly), smaller and bigger learning rates, different momentum values, less/more convolutional layers and different parameters for the padding and kernel_initializer, different batch sizes... It's still stuck with either the very quickly improving accuracy or the static one.
My code looks as follows:
#parameters
batch_size = 16
img_height = 180
img_width = 180
num_classes = 2
epochs = 10
#training data
train_db = tf.keras.preprocessing.image_dataset_from_directory(
`D:\archive\faces\`,
validation_split=0.2,
subset="training",
seed=123,
image_size=(img_height, img_width), color_mode = "grayscale",
batch_size=batch_size)
#validation data
val_db = tf.keras.preprocessing.image_dataset_from_directory(
`D:\archive\faces\`,
validation_split=0.2,
subset="validation",
seed=123,
image_size=(img_height, img_width), color_mode = "grayscale",
batch_size=batch_size)
#speeds up the model training
AUTOTUNE = tf.data.experimental.AUTOTUNE
train_db = train_db.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
val_db = val_db.cache().prefetch(buffer_size=AUTOTUNE)
#establishing the model
model = Sequential([
layers.experimental.preprocessing.Rescaling(1./255),
layers.Conv2D(16, (3,3), activation='relu', input_shape=(img_width, img_height, 1), kernel_initializer='he_uniform', padding='same'),
layers.MaxPooling2D(2, 2),
layers.Conv2D(32, (3,3), activation='relu', kernel_initializer='he_uniform', padding='same'),
layers.MaxPooling2D(2,2),
layers.Conv2D(64, (3,3), activation='relu', kernel_initializer='he_uniform', padding='same'),
layers.MaxPooling2D(2,2),
layers.Conv2D(64, (3,3), activation='relu', kernel_initializer='he_uniform', padding='same'),
layers.MaxPooling2D(2,2),
layers.Conv2D(64, (3,3), activation='relu', kernel_initializer='he_uniform', padding='same'),
layers.MaxPooling2D(2,2),
layers.Flatten(),
layers.Dense(512, activation='relu', kernel_initializer='he_uniform'),
layers.Dense(1, activation='sigmoid')
])
#different optimizer options
opt = tf.keras.optimizers.SGD(learning_rate=0.001, momentum=0.9)
opt2 = tf.keras.optimizers.Adam(learning_rate=0.001)
#compiling the model
model.compile(
optimizer=opt,
loss=tf.losses.BinaryCrossentropy(),
metrics='accuracy')
#training the model
model.fit(train_db,validation_data=val_db,epochs=epochs)
since you are using loss=tf.losses.BinaryCrossentropy() then in image_dataset_from_directory you need to add label_mode='binary' for both the train_db and val_db. For val_db add shuffle=False
I'm new to Tensorflow. I followed some tutorials with a provided dataset and wanted to try something on my own. I decided I'd try to classify Magic the Gathering sets. Each card has a symbol in different colors on it: Black, Gold and so on.
The colors don't matter, just the different symbols. So I created a dataset of 3 different sets (so 3 different symbols) and got around 15'000 images like this. Some are a little bit rotated, some have an X and Y offset, just to get some different images.
Then I adapted the tutorial on the tensorflow website for image classification. Instead of two classes I wanted to try three:
batch_size = 250
epochs = 3
IMG_HEIGHT = 55
IMG_WIDTH = 55
train_image_generator = ImageDataGenerator(rescale=1./255)
validation_image_generator = ImageDataGenerator(rescale=1./255)
train_data_gen = train_image_generator.flow_from_directory(batch_size=batch_size,
directory=train_dir,
shuffle=True,
target_size=(IMG_HEIGHT, IMG_WIDTH),
class_mode='binary')
val_data_gen = validation_image_generator.flow_from_directory(batch_size=batch_size,
directory=validation_dir,
target_size=(IMG_HEIGHT, IMG_WIDTH),
class_mode='binary')
model = Sequential([
Conv2D(16, 3, padding='same', activation='relu', input_shape=(IMG_HEIGHT, IMG_WIDTH ,3)),
MaxPooling2D(),
Conv2D(32, 3, padding='same', activation='relu'),
MaxPooling2D(),
Conv2D(64, 3, padding='same', activation='relu'),
MaxPooling2D(),
Flatten(),
Dense(512, activation='relu'),
Dense(1, activation='sigmoid')
])
model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])
history = model.fit_generator(
train_data_gen,
steps_per_epoch=total_train // batch_size,
epochs=epochs,
validation_data=val_data_gen,
validation_steps=total_val // batch_size,
callbacks=[cp_callback]
)
But my loss is negative and I don't get a good accuracy after training. What did I mess up? Is the model used in the tutorial not good for my usecase? Or is there an error in the code because I used three instead of two classes?
The model from the tutorial was used for binary classification (only two classes, cat or dog). You on the other hand want to classify 3 classes not 2. Therefore you have to adapt the architecture a little bit. Your last layer should be:
Dense(3, activation='softmax')
Three neurons because you have three classes and softmax activation because you want your outputs to be valid probabilities. To compile the model, use categorical_crossentropy instead of binary_crossentropy and make sure your labels are one-hot-encoded. Also for your ImageDataGenerator you should pass class_mode=categorical to the .flow_from_directory() function.