I'm new to Deep Learning and Keras
. With my simple training code below, I was classifying 10 classes. But now I want to re-use this code and convert this code to binary case where I say if an image is my object or not.
I tried to change the activation from softmax
to sigmoid
, and also changed updated loss='binary_crossentropy'
. Is this enough to change? Any other changes?
I get an error saying:
File "train.py", line 94, in <module>
shuffle=True, callbacks=callbacks_list)
File "/usr/local/lib/python3.5/dist-packages/keras/legacy/interfaces.py", line 91, in wrapper
return func(*args, **kwargs)
File "/usr/local/lib/python3.5/dist-packages/keras/engine/training.py", line 1732, in fit_generator
initial_epoch=initial_epoch)
File "/usr/local/lib/python3.5/dist-packages/keras/engine/training_generator.py", line 260, in fit_generator
callbacks.on_epoch_end(epoch, epoch_logs)
File "/usr/local/lib/python3.5/dist-packages/keras/callbacks/callbacks.py", line 152, in on_epoch_end
callback.on_epoch_end(epoch, logs)
File "/usr/local/lib/python3.5/dist-packages/keras/callbacks/callbacks.py", line 702, in on_epoch_end
filepath = self.filepath.format(epoch=epoch + 1, **logs)
KeyError: 'acc'
Here is my simple training code for multi-class classification:
#==========================
HEIGHT = 300
WIDTH = 300
TRAIN_DIR = "data"
BATCH_SIZE = 8 #8
steps_per_epoch = 1000 #1000
NUM_EPOCHS = 50 #50
lr= 0.00001
#==========================
FC_LAYERS = [1024, 1024]
dropout = 0.5
def build_finetune_model(base_model, dropout, fc_layers, num_classes):
for layer in base_model.layers:
layer.trainable = False
x = base_model.output
x = Flatten()(x)
for fc in fc_layers:
# New FC layer, random init
x = Dense(fc, activation='relu')(x)
x = Dropout(dropout)(x)
# New softmax layer
predictions = Dense(num_classes, activation='softmax')(x)
finetune_model = Model(inputs=base_model.input, outputs=predictions)
return finetune_model
train_datagen = ImageDataGenerator(preprocessing_function=preprocess_input)
train_generator = train_datagen.flow_from_directory(TRAIN_DIR,
target_size=(HEIGHT, WIDTH),
batch_size=BATCH_SIZE)
base_model = MobileNetV2(weights='imagenet', include_top=False, input_shape=(HEIGHT, WIDTH, 3))
root=TRAIN_DIR
class_list = [ item for item in os.listdir(root) if os.path.isdir(os.path.join(root, item)) ]
print (class_list)
FC_LAYERS = [1024, 1024]
dropout = 0.5
finetune_model = build_finetune_model(base_model, dropout=dropout, fc_layers=FC_LAYERS, num_classes=len(class_list))
adam = Adam(lr=0.00001)
finetune_model.compile(adam, loss='categorical_crossentropy', metrics=['accuracy'])
filepath="./checkpoints/" + "MobileNetV2_{epoch:02d}_{acc:.2f}" +"_model_weights.h5"
checkpoint = ModelCheckpoint(filepath, monitor=["acc"], verbose=1, mode='max', save_weights_only=True)
callbacks_list = [checkpoint]
history = finetune_model.fit_generator(train_generator, epochs=NUM_EPOCHS, workers=8,
steps_per_epoch=steps_per_epoch,
shuffle=True, callbacks=callbacks_list)
Well, you should have only one output node, since it will have the probability of the class (hence 1 - that is the probability of not having that class).
Changing the activation to sigmoid
is correct, since you want to work with a conditional type of probability output, instead of a join probability.
Binary cross-entropy is correct to apply, since you are dealing with binary target data.
Finally, the error seems to be the keyword you are passing in monitor
. Try replacing it with monitor= "val_accuracy"
.