I am trying to retrain the model for a new class but not getting any accuracy.
I have around 1k images(64x64) of an object.
from keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.models import load_model
from tensorflow.keras import layers
from keras.models import Sequential
from keras.layers import *
# Load your custom model
model = load_model('model.h5',compile=False)
# Create a new output layer
num_classes = 1 # Number of new classes to add
new_output = layers.Dense(num_classes, activation='softmax')(model.layers[-2].output)
# Replace the last layer with the new output layer
model.layers[-1] = new_output
# Freeze the weights of the pre-existing layers
for layer in model.layers[:-1]:
layer.trainable = False
# Compile the model
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
# Prepare your new dataset
# ... (Load and preprocess your dataset for the new classes)
train_ = ImageDataGenerator(rescale=1/255.0,horizontal_flip=True,
rotation_range=0.2,shear_range=0.2,
height_shift_range=0.2,
width_shift_range=0.2,zoom_range=0.2)
train= train_.flow_from_directory(r'training',target_size=(64,64),class_mode='categorical',)
# Train the model on the new
model=Sequential()
model.add(Conv2D(filters=32, input_shape=(64,64,3), kernel_size=(3,3) , padding='valid'))
model.add(Activation('relu'))
# Max Pooling
model.add(MaxPooling2D(pool_size=(2,2), padding='valid'))
# 2nd Convolutional Layer
model.add(Conv2D(filters=64, kernel_size=(3,3), padding='valid'))
model.add(Activation('relu'))
# Max Pooling
model.add(MaxPooling2D(pool_size=(2,2), padding='valid'))
# 3rd Convolutional Layer
model.add(Conv2D(filters=64, kernel_size=(3,3), padding='valid'))
model.add(Activation('relu'))
# Max Pooling
model.add(MaxPooling2D(pool_size=(2,2), padding='valid'))
# 4th Convolutional Layer
model.add(Conv2D(filters=128, kernel_size=(3,3), padding='valid'))
model.add(Activation('relu'))
# Max Pooling
model.add(MaxPooling2D(pool_size=(2,2), padding='valid'))
# Passing it to a Fully Connected layer
model.add(Flatten())
# 1st Fully Connected Layer
model.add(Dense(128))
model.add(Activation('relu'))
# Add Dropout to prevent overfitting
model.add(Dropout(0.2))
# 2nd Fully Connected Layer
model.add(Dense(256))
model.add(Activation('relu'))
# Add Dropout
model.add(Dropout(0.2))
# 3rd Fully Connected Layer
model.add(Dense(128))
model.add(Activation('relu'))
# Add Dropout
model.add(Dropout(0.2))
# Output Layer
model.add(Dense(1081))
model.add(Activation('softmax'))
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
print(model.summary())
model.fit(train, epochs=100)
# Save the retrained model
model.save('retrained_model.keras')
print('done')
1 Like
Hi @Killua_Zoldyck, I have a couple of changes that need to made in your code
For transfer learning you have to only remove the last layer from the model and add new layers you want. You can do that by
model = tf.keras.models.load_model('/content/model.h5',compile=False)
model.pop()
Then you can make the layers non trainable using
for layer in model.layers:
layer.trainable = False
As you want to train the model on single class the last layer activation should be sigmoid
model.add(tf.keras.layers.Dense(1,activation='sigmoid'))
and then compile the model, the loss should be binary_crossentropy
model.compile(optimizer='adam', loss='binary_crossentropy',metrics=['accuracy'])
Could you please try with the above mentioned changes and let us know how it works. Thank You.
1 Like
While I was waiting for reply, I modified my program as below and also accuracy was 1.00 with loss at last epoch was 0.0342
But the issue I got that all the pretrained classes data was not there in the new retrained model
Here’s my new program(It also includes all your suggestions too)
Edit: Additional Info: My old model had trained on 1080 classes and I am training it for 1081th class. Added early stopping.
from keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.models import load_model
from tensorflow.keras.layers import Dense
from keras.layers import *
from tensorflow.keras.callbacks import EarlyStopping
# Load your custom model
model = load_model('model.h5', compile=False)
model.layers.pop()
# Add a new dense layer with a single unit for binary classification
model.add(Dense(1, activation='sigmoid', name='binary_output'))
# Freeze the weights of the pre-existing layers
for layer in model.layers[:-1]:
layer.trainable = False
# Compile the model with binary cross-entropy loss
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
# Prepare your new dataset
train_data_dir = 'training'
validation_data_dir = 'validation2'
target_size = (64, 64)
train_datagen = ImageDataGenerator(
rescale=1/255.0,
horizontal_flip=True,
rotation_range=0.2,
shear_range=0.2,
height_shift_range=0.2,
width_shift_range=0.2,
zoom_range=0.2
)
train_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size=target_size,
batch_size=32,
class_mode='binary', # Use 'binary' for binary classification
shuffle=True
)
validation_generator = train_datagen.flow_from_directory(
validation_data_dir,
target_size=target_size,
batch_size=32,
class_mode='binary', # Use 'binary' for binary classification
shuffle=False
)
early_stopping = EarlyStopping(monitor='val_loss', patience=10)
# Train the model on the new dataset
model.fit(
train_generator,
epochs=100,
validation_data=validation_generator,
steps_per_epoch=len(train_generator),
validation_steps=len(validation_generator),
callbacks=[early_stopping]
)
# Save the retrained model
model.save('retrained_model.h5')
print('Training and saving the model is done.')
Hi @Killua_Zoldyck, This is expected behavior if you want to make predictions for 1081 classes you have to train the model on the whole 1081 classes dataset. Thank You.