Keras seed does not augment images and masks the same - keras

I'm trying to transform my images and mask labels in sync, but the random augmentations are applied differently to both generators (proven when I save both images to a directory).
I've tried
seeding all generators in my library stack
disabling shuffle and multiprocessing
ensuring augmentation options are identical between images and masks
One thing that did work was setting batch size to 1, but then my training performance suffered.
seed_val=0
data_gen_args = dict(
rescale=1./255,
horizontal_flip=True,
validation_split=validation_split)
image_datagen = ImageDataGenerator(**data_gen_args)
mask_datagen = ImageDataGenerator(**data_gen_args)
image_generator = image_datagen.flow_from_directory(
'data/x/train_images/',
target_size=(224, 224),
color_mode='rgb',
class_mode=None,
batch_size=batch_size,
subset='training',
save_to_dir='tmp/img/',
seed=seed_val)
mask_generator = mask_datagen.flow_from_directory(
'data/x/train_annotations/',
target_size=(224, 224),
color_mode='grayscale',
class_mode=None,
batch_size=batch_size,
subset='training',
save_to_dir='tmp/mask/',
seed=seed_val)
train_generator = zip((image_generator), (mask_generator))

try setting shuffle to False to both image and mask
image_generator = image_datagen.flow_from_directory(
'data/x/train_images/',
target_size=(224, 224),
shuffle = False,
color_mode='rgb',
class_mode=None,
batch_size=batch_size,
subset='training',
save_to_dir='tmp/img/',
seed=seed_val)
mask_generator = mask_datagen.flow_from_directory(
'data/x/train_annotations/',
target_size=(224, 224),
shuffle = False,
color_mode='grayscale',
class_mode=None,
batch_size=batch_size,
subset='training',
save_to_dir='tmp/mask/',
seed=seed_val)

I had the problem that my augmentations for the images and masks weren't in the same order, e.g.
img: pan, increase brightness, transform, rgbshift
mask: pan, transform
With that, "increase brightness" changes the value from the seed. Should be
img: pan, transform, increase brightness, rgbshift
mask: pan, transform

Related

how to overfit a model on a single batch in keras?

I am trying to overfit my model on a single batch to check model integrity. I am using Keras and TensorFlow for the implementation of my model and coding style for this project.
I know how to get the single batch and overfit the model in PyTorch but don't have an idea in Keras.
to get a single batch in PyTorch I used:
images, labels = next(iter(train_dataset))
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr = 0.0001)
for epoch in range(epochs):
print(f"Epoch [{epoch}/{epochs}]")
# for batch_idx, (data, target) in enumerate(train_loader):
data, target = data.to(device), target.to(device)
data = data.reshape(data.shape[0], -1)
# forward
score = model(data)
loss = criterion(score, target)
print(f"Loss: {loss.item()}")
# backward
optimizer.zero_grad()
loss.backward()
optimizer.step()
How to do it in keras any helping matrial?
Thank you everyone for coming here. I found a solution and here it is:
datagen = ImageDataGenerator(rescale=1 / 255.0,
rotation_range=20,
zoom_range=0.2,
width_shift_range=0.05,
height_shift_range=0.05,
shear_range=0.2,
horizontal_flip=True,
fill_mode="nearest"
)
# preprocessing_function=preprocess_input,
# Declare an image generator for validation & testing without generation
test_datagen = ImageDataGenerator(rescale = 1./255,)#preprocessing_function=preprocess_input
# Declare generators for training, validation, and testing from DataFrames
train_gen = datagen.flow_from_directory(directory_train,
target_size=(512, 512),
color_mode='rgb',
batch_size=BATCH_SIZE,
class_mode='binary',
shuffle=True)
val_gen = test_datagen.flow_from_directory(directory_val,
target_size=(512, 512),
color_mode='rgb',
batch_size=BATCH_SIZE,
class_mode='binary',
shuffle=False)
test_gen = test_datagen.flow_from_directory(directory_test,
target_size=(512, 512),
color_mode='rgb',
batch_size=BATCH_SIZE,
class_mode='binary',
shuffle=False)
train_images, train_labels = next(iter(train_gen))
val_images, val_labels = next(iter(val_gen))
test_images, test_labels = next(iter(val_gen))
#check shape for selected Batch
print("Length of Train images : {}".format(len(train_images)))
print("shape of Train images : {}".format(train_images.shape))
print("shape of Train labels : {}".format(train_labels.shape))
Length of Train images : 32
shape of Train images : (32, 512, 512, 3)
shape of Train labels : (32,)
history = model.fit(train_images, train_labels,
use_multiprocessing=True,
workers=16,
epochs=100,
class_weight=class_weights,
validation_data=(val_images, val_labels),
shuffle=True,
callbacks=call_backs)

grayscale input for keras InceptionV3

I have made this network which seems to work ok.
datagen = tf.keras.preprocessing.image.ImageDataGenerator(
#zoom_range=0.2,
#shear_range=0.2,
#rotation_range=10,
rescale=1/255,
validation_split=0.2,
# other things...
)
train_ds = datagen.flow_from_directory(
data_dir,
subset="training",
class_mode='binary',
target_size=target_size,
batch_size=batch_size,
)
val_ds = datagen.flow_from_directory(
data_dir,
subset="validation",
class_mode='binary',
target_size=target_size,
batch_size=batch_size,
)
pre_trained_model = InceptionV3(input_shape=(128,128,3),
include_top=False,
weights='imagenet')
for layer in pre_trained_model.layers:
layer.trainable = False
global_average_layer = tf.keras.layers.GlobalAveragePooling2D()
Dl_1 = tf.keras.layers.Dropout(rate = 0.2)
prediction_layer = tf.keras.layers.Dense(1,activation='sigmoid')
model_V3 = tf.keras.Sequential([
pre_trained_model,
global_average_layer,
Dl_1,
prediction_layer
])
model_V3.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])
lr_reduce = ReduceLROnPlateau(monitor='val_loss', factor=0.2, patience=3, verbose=2, mode='max')
hist = model_V3.fit(
train_ds,
epochs=5,
steps_per_epoch=len(train_ds),
validation_data=val_ds,
validation_steps=len(val_ds),
callbacks=[lr_reduce])
However the issue here is that the network is built for RGB images. My data is grayscale images. Right now I am just replicating channels so that R,G and B get same value for each pixel.
The problem is that this is extremely memory consuming and slow.
Is there a way to make the network use graylevel images instead of rgb?
Is there maybe another pretrained network which is better to classify grayscale images of elliptic cell-like structures?
When importing InceptionV3 try this:
pre_trained_model = InceptionV3(input_shape=(128,128,1),
include_top=False,
weights='imagenet')
128 and 128 are the physical dimensions of your image and the 3 (or 1 in my case) are the color channels.

Generating a train, test and validation set from the same directory in Keras

I'm using keras to build an image classification model and all of my data is in one directory with subfolders for each class:
data/
----class1/
----class2/
----class3/
----class4/
I'm wondering if there is a way to split my data into a train, test AND validation set in keras using ImageDataGenerator.
Yes, there is a way you can do that.
train_datagen = ImageDataGenerator(rescale=1./255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
validation_split=0.2) # set validation split
train_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size=(img_height, img_width),
batch_size=batch_size,
class_mode='binary',
subset='training') # set as training data
validation_generator = train_datagen.flow_from_directory(
train_data_dir, # same directory as training data
target_size=(img_height, img_width),
batch_size=batch_size,
class_mode='binary',
subset='validation') # set as validation data
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)
https://keras.io/preprocessing/image/

Keras methods 'predict' and 'predict_generator' with different result

I have trained a basic CNN model for image classification.
While training the model I have used ImageDataGenerator from keras api.
After the model is being trained i used testdatagenerator and flow_from_directory method for testing.
Everything Went well.
Then I saved the model for future use.
Now i am using the same model and used predict method from keras api with a single image, but the prediction is very different every time I test using different images.
Could you please let me know any solution.
training_augmentation = ImageDataGenerator(rescale=1 / 255.0)
validation_testing_augmentation = ImageDataGenerator(rescale=1 / 255.0)
# Initialize training generator
training_generator = training_augmentation.flow_from_directory(
JPG_TRAIN_IMAGE_DIR,
class_mode="categorical",
target_size=(32, 32),
color_mode="rgb",
shuffle=True,
batch_size=batch_size
)
# initialize the validation generator
validation_generator = validation_testing_augmentation.flow_from_directory(
JPG_VAL_IMAGE_DIR,
class_mode="categorical",
target_size=(32, 32),
color_mode="rgb",
shuffle=False,
batch_size=batch_size
)
# initialize the testing generator
testing_generator = validation_testing_augmentation.flow_from_directory(
JPG_TEST_IMAGE_DIR,
class_mode="categorical",
target_size=(32, 32),
color_mode="rgb",
shuffle=False,
batch_size=batch_size
)
history = model.fit_generator(
training_generator,
steps_per_epoch=total_img_count_dict['train'] // batch_size,
validation_data=validation_generator,
validation_steps=total_img_count_dict['val'] // batch_size,
epochs=epochs,
callbacks=callbacks)
testing_generator.reset()
prediction_stats = model.predict_generator(testing_generator, steps=(total_img_count_dict['test'] // batch_size) + 1)
### Trying to use predict method
img_file = '/content/drive/My Drive/Traffic_Sign_Recognition/to_display_output/Copy of 00003_00019.jpg'
img = cv2.imread(img_file)
img=cv2.resize(img, (32,32))
img = img/255.0
a=np.reshape(img, (1, 32, 32, 3))
model = load_model('/content/drive/My Drive/Traffic_Sign_Recognition/basic_cnn.h5')
prediction = model.predict(a)
When I am trying to use predict, every time wrong prediction is coming.
Any leads will be appreciated.
Keras generator uses PIL for image reading which read images from disk as RGB.
You are using opencv for reading which reads images as BGR. You have to convert your image from BGR to RGB.
img = cv2.imread(img_file)
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
...

U-net Final Layer

I'm trying to do an image segmentation problem where I want to segment 5 objects in an image. I'm using a U-net architecture. My final layer looks like this:
conv_final = Conv2D(OUTPUT_MASK_CHANNELS, (1, 1))(up_conv_224)
conv_final = Activation('sigmoid')(conv_final)
model = Model(inputs, conv_final, name="ZF_UNET_224")
However I get an error saying:
ValueError: Error when checking target: expected conv2d_24 to have shape (224, 224, 5) but got array with shape (224, 224, 3)
This is the generator that I'm using
image_generator = train_datagen.flow_from_directory(
'data/train', # this is the target directory
target_size=(224, 224),
color_mode = 'rgb',# all images will be resized to 150x150
batch_size=batch_size,
class_mode=None,
seed = 1) # since we use binary_crossentropy loss, we need binary labels
# this is a similar generator, for validation data
mask_generator = mask_datagen.flow_from_directory(
'data/train',
target_size=(224, 224),
color_mode = 'rgb',
batch_size=batch_size,
class_mode=None,
seed = 1)
train_generator = zip(image_generator, mask_generator)
What can I do to fix this? Any help appreciated!
You have to convert the data into one hot encoded format.
Use from keras.utils import to_categorical

Resources