How to fit an autoencoder using flow_from_directory - python-3.x

I'm building out a basic autoencoder and using the keras documentation here as a guide: https://blog.keras.io/building-autoencoders-in-keras.html.
I'm getting stuck and switching it to be able to fit from a flow_from_directory object, here's the one I've set up:
data_gen = tf.keras.preprocessing.image.ImageDataGenerator()
train_generator = data_gen.flow_from_directory(
directory= 'train_images',
target_size=(28, 28),
color_mode="rgb",
batch_size=128,
shuffle=True,
seed=42,
class_mode=None,
)
I'm trying to fit the model (which is more or less the same as the one in the keras documentation using this code:
autoencoder.fit(train_generator, train_generator,
epochs=500,
shuffle=True)
However, the problem is that passing it in like this gives me this error:
`ValueError: `y` argument is not supported
I think maybe this is saying that I can't specify a y if my x comes from a flow_for_directory, which makes sense, but how can I specify labels to be the same the data-itself?

Putting the answer here in case it helps anyone else. As Frightera suggested in the comments, changing the class_mode to 'input' solved this problem:
data_gen = tf.keras.preprocessing.image.ImageDataGenerator()
train_generator = data_gen.flow_from_directory(
directory= 'train_images',
target_size=(28, 28),
color_mode="rgb",
batch_size=128,
shuffle=True,
seed=42,
class_mode='input',
)
autoencoder.fit(train_generator,
epochs=500,
shuffle=True)

Try modifying your fit function:
autoencoder.fit(train_generator,
epochs=500,
shuffle=True)
You were using train_generator twice, when you are using ImageDataGenerator.flow_from_directory function it returns a DirectoryIterator yielding tuples of (x, y) where x is a numpy array containing batches of data and y is a numpy array of corresponding labels.
Please refer to the Keras docs:
https://keras.io/api/preprocessing/image/#flowfromdirectory-method

Related

image augmentation went wrong

I was trying to make image augmentation and see how it will affect the model but for some reason I got this error
TypeError: '>' not supported between instances of 'int' and 'ImageDataGenerator'
I'm using efficientNetb4 with adding my own classifier layer.
augment = ImageDataGenerator(horizontal_flip=True, vertical_flip=True, rotation_range=30, validation_split=0.15)
train = augment.flow_from_directory(path, target_size=(380,380), batch_size=35, subset='training')
valid = augment.flow_from_directory(path, target_size=(380,380), batch_size=35, subset='validation')
base_model = keras.applications.EfficientNetB4(weights="imagenet",include_top=False, input_shape=(380, 380,3))
for layer in base_model.layers:
layer.trainable = False
avg = keras.layers.GlobalAveragePooling2D()(base_model.output)
output = keras.layers.Dense(3, activation="softmax")(avg)
model = keras.Model(inputs=base_model.input, outputs=output)
earlystopping = keras.callbacks.EarlyStopping(monitor='loss', patience=3)
optimizer = keras.optimizers.SGD(learning_rate=0.001, momentum=0.9, decay=0.0001)
model.compile(loss="sparse_categorical_crossentropy",optimizer=optimizer,metrics=["accuracy"])
history = model.fit_generator(train, augment, validation_data=valid, epochs=25, verbose=2, callbacks=[earlystopping])
I think the problem is the batch_size i specified but couldn't understand shy it caused this error
Please check documentation for fit_generator (https://faroit.com/keras-docs/1.2.0/models/model/):
fit_generator(self, generator, samples_per_epoch, nb_epoch, verbose=1, callbacks=[], validation_data=None, nb_val_samples=None, class_weight={}, max_q_size=10, nb_worker=1, pickle_safe=False, initial_epoch=0)
The second argument is 'samples_per_epoch', which is int, but you are passing ImageDataGenerator instead. Hence the error message. I don't see why you need to pass 'augment' here. The following should work:
history = model.fit_generator(train, validation_data=valid, epochs=25, verbose=2, callbacks=[earlystopping])

Array mismatch in Keras classifier model output layer

I am designing a classifier which takes 10 values - signal (acquired by processing pixels of MNIST dataset, normalized 0-1) at the input, and outputs the class of digit. The 10 valued signal is unique for each digit and therefore classification can be performed.
num_classes=10
y_train=to_categorical(y_train,num_classes)
y_test=to_categorical(y_test,num_classes)
x_train=(60000,10,1,1)
y_train=(60000,10)
x_test=(10000,10,1,1)
y_test=(10000,10)
The code is given as
input_img = Input(shape=(10,1,1))
x = Flatten()(input_img)
x = Dense(100, activation='relu')(x)
x = Dense(100, activation='relu')(x)
decoded = Dense(10, activation='softmax')(x)
autoencoder=Model(input_img,decoded)
autoencoder.compile(optimizer='adam',loss='categorical_crossentropy',metrics=['accuracy'])
history=autoencoder.fit(x_train, y_train,
epochs=30,
batch_size=32,
verbose=1,
shuffle=True,
validation_data=(x_test, y_test))
Please suggest what changes can be made.
I think you should probably use the tf.keras.losses.CategoricalCrossentropy loss function because you encoded your target to one hot vector using to_categorical. According to doc:
Use this crossentropy loss function when there are two or more label classes. We expect labels to be provided in a one_hot representation. If you want to provide labels as integers, please use SparseCategoricalCrossentropy loss.
However, IMO, without reproducible code, it's really ambitious to give a specific answer.

Repeated error for every activation_9n (eg: activation_9, ..activation_45.. etc)

"ValueError: Error when checking target: expected activation_81 to have shape (1,) but got array with shape (7,)"
I am performing a multiclass classification of 7 classes for speech emotion classification using a neural network, but it fails at this point
cnnhistory=model.fit(x_traincnn,
y_train,
batch_size=16,
epochs=700,
validation_data=(x_testcnn, y_test),
callbacks=[mcp_save, lr_reduce])
at the line callbacks=[mcp_save, lr_reduce]
mcp_save being
mcp_save = ModelCheckpoint('model/aug_noiseNshift_2class2_np.h5',
save_best_only=True, monitor='val_loss', mode='min')
and lr_reduce being
lr_reduce = ReduceLROnPlateau(monitor='val_loss', factor=0.9, patience=20, min_lr=0.000001)
Final layer of NN
Dense(7) for 7 classes
model.add(Dense(7))
model.add(Activation('softmax'))
opt = keras.optimizers.SGD(lr=0.0001, momentum=0.0, decay=0.0, nesterov=False)
compiled model using
model.compile(loss='sparse_categorical_crossentropy', optimizer=opt, metrics=['accuracy', fscore])
I have already transformed the dataset, with normalised values, changed the loss function to 'sparse_categorical_crossentropy' from 'categorical_crossentropy'. Nothing has worked just pushed the error from activation_9 to activation_18 to activation_45 to activation_54 to now activation_81. But the error is still there.
Any help would be highly appreciated!
I am new to neural networks.
TIA
If you have labels as numbers, that means y_train has shape (samples, 1) and you should use 'sparse_categorical_crossentropy'.
If you have labels as one-hot encodings, that means y_train has shape (samples, 7) and you should use 'categorical_crossentropy'.

Errors while fine tuning InceptionV3 in Keras

I am going to fine-tune InceptionV3 model using my self-defined dataset. Unfortunately, when using model.fit to train, here comes the error below:
ValueError: Error when checking target: expected dense_6 to have shape (4,) but got array with shape (1,)
Firstly, I load my own dataset as training_data which contains a pair of image and corresponding label. Then, I use the code below to convert them into specific array-type(img_new and label_new) so that it's compatible to Keras's inputs of both data and labels.
for img, label in training_data:
img_new[i,:,:,:] = img
label_new[i,:] = label
i=i+1
Second, I fine tune the Inception Model below.
InceptionV3_model=keras.applications.inception_v3.InceptionV3(include_top=False,
weights='imagenet',
input_tensor=None,
input_shape=None,
pooling=None,
classes=1000)
#InceptionV3_model.summary()
# add a global spatial average pooling layer
x = InceptionV3_model.output
x = GlobalAveragePooling2D()(x)
# let's add a fully-connected layer
x = Dense(1024, activation='relu')(x)
# and a logistic layer -- let's say we have 4 classes
predictions = Dense(4, activation='softmax')(x)
# this is the model we will train
model = Model(inputs=InceptionV3_model.input, outputs=predictions)
# Transfer Learning
for layer in model.layers[:311]:
layer.trainable = False
for layer in model.layers[311:]:
layer.trainable = True
from keras.optimizers import SGD
model.compile(optimizer=SGD(lr=0.001, momentum=0.9), loss='categorical_crossentropy')
model.fit(x=X_train, y=y_train, batch_size=3, epochs=3, validation_split=0.2)
model.save_weights('first_try.h5')
Does anyone have ideas of what is wrong while training using model.fit?
Sincerely thanks for your kind help.
The error is caused because my labels r integers, I gotta compile it by sparse_categorical_crossentropy which is set for integer labels instead of categorical_crossentropy which is used for one-hot encoding.
Sincerely thank for the help by #Amir very much. :-)

Keras flow_from_directory class index

I used to make it manually, but i am using now flow_from_directory to train my network with my own data. I just have one question. When i make model.predict(), how can i know that my index 0 on predictions is for label category dog and index 1 is for category cats?
The code i am using is the following.
train_datagen = ImageDataGenerator(
rescale=1./255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
test_datagen = ImageDataGenerator(rescale=1./255)
train_generator = train_datagen.flow_from_directory(
train_images_path,
target_size=(64, 64),
batch_size=batch_size)
validation_generator = test_datagen.flow_from_directory(
validate_images_path,
target_size=(64, 64),
batch_size=batch_size)
early_stopping = keras.callbacks.EarlyStopping(monitor='val_acc', min_delta=0, patience=3, verbose=1, mode='auto')
history = model.fit_generator(
train_generator,
steps_per_epoch=1700,
epochs=epochs,
verbose=1,
callbacks=[early_stopping],
validation_data=validation_generator,
validation_steps=196
)
What i wanted to know is the pair images vs ground truth label.
Thank you
You can have the the index of each class generated by the generator with class_indices property.
print(validation_generator.class_indices)
Simple...
When you gather data, you define that. There is no rule. But a simple way to check is:
see what your first training image is, look at it yourself: is it a cat or a dog?
then see the training Y (result/class/desired output), is it [0,1] or [1,0]?
This will answer your question.
For getting one sample from a generator, you can see this question: How to get one value from a generator in Python?
As defined in Keras documentation, the generator output is a tuple of (inputs, targets)
Its pretty simple. When you pre-process your data, just replace the class labels with some specific integers (you can call it id). So, when you compute the loss or accuracy from the model's output, just compare the prediction with the ground truth in terms of integer labels (id).
In case if you need the label text, you can get it back from the id (integer).

Resources