how to use transfer learning and fine tuning correctly?

30 Views Asked by At

I created a model using transfer learning fine tuning for identify snakes using 5 snake breeds with Mobile net. My problem is within the snake breeds it identify the breed almost every time.But when i tried images like worms,lizards it still identify them with nearly 60% score. Even a human was identified as a snake once.

`IM_WIDTH, IM_HEIGHT = 224, 224
NB_EPOCHS = 3
BAT_SIZE = 32
FC_SIZE = 64
NB_MN_LAYERS_TO_FREEZE = 20
dataset_folder = "C:\\Users\\XDD\\FYP\\Dataset"
train_dir = "Dataset/Train"
val_dir = "Dataset/Val"
test_dir = "Dataset/Test"

def get_nb_files(directory):
    count = 0
    for root, dirs, files in os.walk(directory):
        count += len(files)
    return count

def add_new_last_layer_mobilenet(base_model, nb_classes, dropout_rate=0.5):
    x = base_model.output
    x = GlobalAveragePooling2D()(x)
    x = Dense(FC_SIZE, activation='relu')(x)
    x = Dropout(dropout_rate)(x)  # Add dropout layer
    predictions = Dense(nb_classes, activation='softmax')(x)
    model = Model(inputs=base_model.input, outputs=predictions)
    return model

def setup_to_transfer_learn_mobilenet(model, base_model):
    for layer in base_model.layers:
        layer.trainable = False
    model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])

def setup_to_finetune_mobilenet(model):
    for layer in model.layers[:NB_MN_LAYERS_TO_FREEZE]:
        layer.trainable = False
    for layer in model.layers[NB_MN_LAYERS_TO_FREEZE:]:
        layer.trainable = True
    model.compile(optimizer=SGD(learning_rate=0.0001, momentum=0.9), loss='categorical_crossentropy',metrics=['accuracy'])

def plot_training(history):
    acc = history.history['accuracy']
    val_acc = history.history['val_accuracy']
    loss = history.history['loss']
    val_loss = history.history['val_loss']
    epochs = range(len(acc))

    plt.plot(epochs, acc, 'b', label='Training acc')
    plt.plot(epochs, val_acc, 'r', label='Validation acc')
    plt.title('Training and validation accuracy')
    plt.legend()
    plt.figure()
    plt.plot(epochs, loss, 'b', label='Training loss')
    plt.plot(epochs, val_loss, 'r', label='Validation loss')
    plt.title('Training and validation loss')
    plt.legend()
    plt.show()

def train_mobilenet(train_dir, val_dir, nb_epoch=NB_EPOCHS, batch_size=BAT_SIZE, output_model_file="mobilenet-ft.model", plot=True):
    nb_train_samples = get_nb_files(train_dir)
    nb_classes = len(glob.glob(train_dir + "/*"))
    nb_val_samples = get_nb_files(val_dir)

    train_datagen = ImageDataGenerator(
        preprocessing_function=preprocess_input_tf_mobilenet,
        width_shift_range=0.2,
        height_shift_range=0.2,
        shear_range=0.2,
        zoom_range=0.2,
        fill_mode='nearest',  # Filling strategy for rotated images
    )

    val_datagen = ImageDataGenerator(
        preprocessing_function=preprocess_input_tf_mobilenet,
        width_shift_range=0.2,
        height_shift_range=0.2,
        shear_range=0.2,
        zoom_range=0.2,
        fill_mode='nearest',
    )
    
    train_generator = train_datagen.flow_from_directory(
        train_dir,
        target_size=(IM_WIDTH, IM_HEIGHT),
        batch_size=batch_size,
        class_mode='categorical'
    )

    validation_generator = val_datagen.flow_from_directory(
        val_dir,
        target_size=(IM_WIDTH, IM_HEIGHT),
        batch_size=batch_size,
        class_mode='categorical'
    )

    base_model = MobileNet(weights='imagenet', include_top=False, input_shape=(IM_WIDTH, IM_HEIGHT, 3))
    model = add_new_last_layer_mobilenet(base_model, nb_classes)

    setup_to_transfer_learn_mobilenet(model, base_model)

    history_tl = model.fit(
        train_generator,
        epochs=nb_epoch,
        steps_per_epoch=nb_train_samples // batch_size,
        validation_data=validation_generator,
        validation_steps=nb_val_samples // batch_size,
        
    )

    setup_to_finetune_mobilenet(model)

    history_ft = model.fit(
        train_generator,
        steps_per_epoch=nb_train_samples // batch_size,
        epochs=nb_epoch,
        validation_data=validation_generator,
        validation_steps=nb_val_samples // batch_size,
        
    )

    model.save(output_model_file)

    if plot:
        plot_training(history_ft)

    return model

trained_mobilenet_model = train_mobilenet(train_dir=train_dir, val_dir=val_dir, nb_epoch=NB_EPOCHS, batch_size=BAT_SIZE, output_model_file="mobilenet-ft.model", plot=True)


trained_mobilenet_model.summary()`

This is the confusion matrix and classification report with test result

Accuracy: 0.9271523178807947

Confusion Matrix:
[[28  0  0  0  1]
 [ 1 30  0  0  0]
 [ 0  2 24  2  2]
 [ 0  0  0 27  3]
 [ 0  0  0  0 31]]

Classification Report:
                  precision    recall  f1-score   support

           Cobra       0.97      0.97      0.97        29
    Common_Crait       0.94      0.97      0.95        31
Hump_Nosed_Viper       1.00      0.80      0.89        30
  Russells_Viper       0.93      0.90      0.92        30
Saw_Scaled_Viper       0.84      1.00      0.91        31

        accuracy                           0.93       151
       macro avg       0.93      0.93      0.93       151
    weighted avg       0.93      0.93      0.93       151

I wanted to classify the snake breed correctly within training.It is working with snake images but i was expecting to get a lower accuracy for outside data like lizards and objects and animals which has shape of snake.

0

There are 0 best solutions below