<jupyter_start><jupyter_text>Original Images  Loading Data<jupyter_code>img_rows, img_cols = (334,334)
train_batchsize = 16
val_batchsize = 16

train_datagen = ImageDataGenerator(
      rescale=1./255,
      rotation_range=30,
      width_shift_range=0.3,
      height_shift_range=0.3,
      brightness_range=[0.2, 1.2],
      horizontal_flip=True)

validation_datagen = ImageDataGenerator(rescale=1./255)

train_generator = train_datagen.flow_from_directory(
        orig_path + 'train_images/',
        target_size=(img_rows, img_cols),
        batch_size=train_batchsize,
        class_mode='categorical',
        interpolation='bicubic')
 
validation_generator = validation_datagen.flow_from_directory(
        orig_path + 'val_images/',
        target_size=(img_rows, img_cols),
        batch_size=val_batchsize,
        class_mode='categorical',
        shuffle=False,
        interpolation='bicubic')<jupyter_output>Found 1082 images belonging to 20 classes.
Found 103 images belonging to 20 classes.<jupyter_text>Utils<jupyter_code># Swish Activation Function
def swish(x):
    return K.sigmoid(x) * x

get_custom_objects().update({"swish": Activation(swish)})


# Learning Step Decay by 10e-1 after every 4 epochs
def step_decay(epoch):
    initial_lrate = 0.001
    drop = 0.1
    epochs_drop = 4.0
    lrate = initial_lrate * math.pow(drop, math.floor((epoch) / epochs_drop))
    return lrate

# Calculates Precision Accuracy
def precision(y_true, y_pred):
    """Precision metric.
    Computes the precision, a metric for multi-label classification of
    how many selected items are relevant.
    """
    true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
    predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))
    precision = true_positives / (predicted_positives + K.epsilon())
    return precision


# Calculates Recall Accuracy
def recall(y_true, y_pred):
    """Recall metric.
    Computes the recall, a metric for multi-label classification of
    how many relevant items are selected.
    """
    true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
    possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))
    recall = true_positives / (possible_positives + K.epsilon())
    return recall


# Calculates F1 score
def f1(y_true, y_pred):
    def precision(y_true, y_pred):
        true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
        predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))
        precision = true_positives / (predicted_positives + K.epsilon())
        return precision

    def recall(y_true, y_pred):
        true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
        possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))
        recall = true_positives / (possible_positives + K.epsilon())
        return recall

    precision = precision(y_true, y_pred)
    recall = recall(y_true, y_pred)
    return 2 * ((precision * recall) / (precision + recall + K.epsilon()))<jupyter_output><empty_output><jupyter_text>Phase 1 : Trained only on top layer / Inception No Trainable<jupyter_code>base_model = InceptionV3(
        include_top=False,
        weights='imagenet',
        input_tensor=None,
        input_shape=(334,334,3)
    )
# Freeze InceptionResNetV2
for layer in base_model.layers:
  layer.trainable = False

# Add final layers
x = base_model.output
x = AveragePooling2D((8, 8), strides=(8, 8), name="avg_pool")(x)
x = Flatten(name="flatten")(x)
x = Dense(
          512,
          activation="swish",
          name="dense_1",
          kernel_initializer="he_uniform")(x)
x = Dropout(0.3)(x)
predictions = Dense(
    20,
    activation="softmax",
    name="predictions",
    kernel_initializer="he_uniform")(x)
model = Model(inputs=base_model.input, outputs=predictions)

# Compile Model
adam = Adam(0.0001)
model.compile(loss="categorical_crossentropy",
              optimizer=adam,
             metrics=[precision, recall, f1, 'acc'])
lrate = LearningRateScheduler(step_decay)
checkpoint = ModelCheckpoint("/content/drive/My Drive/bird_classification/models/inception_v3_freezed.h5",
                             monitor="val_acc",
                             mode="max",
                             save_best_only = True,
                             verbose=1)

nb_train_samples = 1082
nb_validation_samples= 103
epochs=12
batch_size=16

history = model.fit_generator(train_generator,
                                 steps_per_epoch=nb_train_samples // batch_size,
                                 epochs=epochs,
                                 callbacks=[lrate, checkpoint],
                                 validation_data=validation_generator,
                                 validation_steps=nb_validation_samples // batch_size)
score = model.evaluate(validation_generator, verbose=1)<jupyter_output>7/7 [==============================] - 2s 240ms/step - loss: 0.4786 - precision: 0.8730 - recall: 0.7857 - f1: 0.8233 - acc: 0.8155<jupyter_text>- Loss : 0.4786- Precision : 0.8730- Recall : 0.7857- f1_score : 0.8233- accuracy : 0.8155  Phase 2 : Retrains last layer of inception<jupyter_code>len(base_model.layers)
base_model = InceptionV3(
        include_top=False,
        weights='imagenet',
        input_tensor=None,
        input_shape=(334,334,3)
    )
for layer in base_model.layers[:len(base_model.layers)-22]:
  layer.trainable = False
for layer in base_model.layers[len(base_model.layers)-22:]:
  layer.trainable = True

# Add final layers
x = base_model.output
x = AveragePooling2D((8, 8), strides=(8, 8), name="avg_pool")(x)
x = Flatten(name="flatten")(x)
x = Dense(
          512,
          activation="swish",
          #activation='relu',
          name="dense_1",
          kernel_initializer="he_uniform")(x)
x = Dropout(0.25)(x)
predictions = Dense(
    20,
    activation="softmax",
    name="predictions",
    kernel_initializer="he_uniform")(x)
model_retrain = Model(inputs=base_model.input, outputs=predictions)

# Compile Model
adam = Adam(0.0001)
model_retrain.compile(loss="categorical_crossentropy",
              optimizer=adam,
             metrics=[precision, recall, f1, 'acc'])
lrate = LearningRateScheduler(step_decay)
checkpoint = ModelCheckpoint("/content/drive/My Drive/bird_classification/models/inception_v3_retrained.h5",
                             monitor="val_acc",
                             mode="max",
                             save_best_only = True,
                             verbose=1)

nb_train_samples = 1082
nb_validation_samples= 103
epochs=12
batch_size=16

history = model_retrain.fit_generator(train_generator,
                                 steps_per_epoch=nb_train_samples // batch_size,
                                 epochs=epochs,
                                 callbacks=[lrate, checkpoint],
                                 validation_data=validation_generator,
                                 validation_steps=nb_validation_samples // batch_size)
score = model_retrain.evaluate(validation_generator, verbose=1)<jupyter_output>7/7 [==============================] - 1s 158ms/step - loss: 0.3734 - precision: 0.9004 - recall: 0.8482 - f1: 0.8724 - acc: 0.8641<jupyter_text>- Loss : 0.3717- Precision : 0.9004- Recall : 0.8482- f1_score : 0.8724- accuracy : 0.8641 Well good news, unfrezing the last layers help us improve the performance of the model. but I think it's overfitted a bit, so for this time we will reduce the number of layer to retrain  Phase 3 : Retrain 5 less layers<jupyter_code>base_model = InceptionV3(
        include_top=False,
        weights='imagenet',
        input_tensor=None,
        input_shape=(334,334,3)
    )
for layer in base_model.layers[:len(base_model.layers)-17]:
  layer.trainable = False
for layer in base_model.layers[len(base_model.layers)-17:]:
  layer.trainable = True

# Add final layers
x = base_model.output
x = AveragePooling2D((8, 8), strides=(8, 8), name="avg_pool")(x)
x = Flatten(name="flatten")(x)
x = Dense(
          512,
          #activation="swish",
          activation='relu',
          name="dense_1",
          kernel_initializer="he_uniform")(x)
x = Dropout(0.25)(x)
predictions = Dense(
    20,
    activation="softmax",
    name="predictions",
    kernel_initializer="he_uniform")(x)
model_retrain_v2 = Model(inputs=base_model.input, outputs=predictions)

# Compile Model
adam = Adam(0.0001)
model_retrain_v2.compile(loss="categorical_crossentropy",
              optimizer=adam,
             metrics=[precision, recall, f1, 'acc'])
lrate = LearningRateScheduler(step_decay)
checkpoint = ModelCheckpoint("/content/drive/My Drive/bird_classification/models/inception_v3_relu_retrained_v2.h5",
                             monitor="val_acc",
                             mode="max",
                             save_best_only = True,
                             verbose=1)

nb_train_samples = 1082
nb_validation_samples= 103
epochs=12
batch_size=16

history = model_retrain_v2.fit_generator(train_generator,
                                 steps_per_epoch=nb_train_samples // batch_size,
                                 epochs=epochs,
                                 callbacks=[lrate, checkpoint],
                                 validation_data=validation_generator,
                                 validation_steps=nb_validation_samples // batch_size)
score = model_retrain_v2.evaluate(train_generator, verbose=1)
score = model_retrain_v2.evaluate(validation_generator, verbose=1)<jupyter_output>7/7 [==============================] - 1s 156ms/step - loss: 0.3406 - precision: 0.9249 - recall: 0.8393 - f1: 0.8777 - acc: 0.8738<jupyter_text>- Loss : 0.3406- Precision : 0.9249- Recall : 0.8393- f1_score : 0.8777- accuracy : 0.8738It's better than beforeI just want to add that the model perform well also on the train set (better than the other models)  Cropped Images<jupyter_code>img_rows, img_cols = (224,224)
train_batchsize = 16
val_batchsize = 16

train_datagen = ImageDataGenerator(
      rescale=1./255,
      rotation_range=30,
      width_shift_range=0.3,
      height_shift_range=0.3,
      brightness_range=[0.2, 1.2],
      horizontal_flip=True)

validation_datagen = ImageDataGenerator(rescale=1./255)

train_generator = train_datagen.flow_from_directory(
        orig_path + 'train_images_cropped/',
        target_size=(img_rows, img_cols),
        batch_size=train_batchsize,
        class_mode='categorical',
        interpolation='bicubic')
 
validation_generator = validation_datagen.flow_from_directory(
        orig_path + 'val_images_cropped/',
        target_size=(img_rows, img_cols),
        batch_size=val_batchsize,
        class_mode='categorical',
        shuffle=False,
        interpolation='bicubic')
base_model = InceptionV3(
        include_top=False,
        weights='imagenet',
        input_tensor=None,
        input_shape=(224,224,3)
    )

# Freeze InceptionResNetV2
for layer in base_model.layers:
  layer.trainable = False

# Add final layers
x = base_model.output
x = AveragePooling2D((4, 4), strides=(4, 4), name="avg_pool")(x)
x = Flatten(name="flatten")(x)
x = Dense(
          512,
          activation="swish",
          name="dense_1",
          kernel_initializer="he_uniform")(x)
x = Dropout(0.25)(x)
predictions = Dense(
    20,
    activation="softmax",
    name="predictions",
    kernel_initializer="he_uniform")(x)
model = Model(inputs=base_model.input, outputs=predictions)

# Compile Model
adam = Adam(0.0001)
model.compile(loss="categorical_crossentropy",
              optimizer=adam,
             metrics=[precision, recall, f1, 'acc'])

lrate = LearningRateScheduler(step_decay)
checkpoint = ModelCheckpoint("/content/drive/My Drive/bird_classification/models/inception_v3_cropped_freezed.h5",
                             monitor="val_acc",
                             mode="max",
                             save_best_only = True,
                             verbose=1)

nb_train_samples = 941
nb_validation_samples= 92
epochs=12
batch_size=16

history = model.fit_generator(train_generator,
                                 steps_per_epoch=nb_train_samples // batch_size,
                                 epochs=epochs,
                                 callbacks=[lrate, checkpoint],
                                 validation_data=validation_generator,
                                 validation_steps=nb_validation_samples // batch_size)
score = model.evaluate(train_generator, verbose=1)
score = model.evaluate(validation_generator, verbose=1)<jupyter_output>6/6 [==============================] - 1s 120ms/step - loss: 0.5040 - precision: 0.8746 - recall: 0.7674 - f1: 0.8113 - acc: 0.8370<jupyter_text>- Loss : 0.5040- Precision : 0.8746- Recall : 0.7674- f1_score : 0.8113- accuracy : 0.8370  Last Layer retrainable<jupyter_code>base_model = InceptionV3(
        include_top=False,
        weights='imagenet',
        input_tensor=None,
        input_shape=(224,224,3)
    )
for layer in base_model.layers[:len(base_model.layers)-17]:
  layer.trainable = False
for layer in base_model.layers[len(base_model.layers)-17:]:
  layer.trainable = True

# Add final layers
x = base_model.output
x = AveragePooling2D((4, 4), strides=(4, 4), name="avg_pool")(x)
x = Flatten(name="flatten")(x)
x = Dense(
          512,
          activation="swish",
          name="dense_1",
          kernel_initializer="he_uniform")(x)
x = Dropout(0.25)(x)
predictions = Dense(
    20,
    activation="softmax",
    name="predictions",
    kernel_initializer="he_uniform")(x)
model_retrain = Model(inputs=base_model.input, outputs=predictions)

# Compile Model
adam = Adam(0.0001)
model_retrain.compile(loss="categorical_crossentropy",
              optimizer=adam,
             metrics=[precision, recall, f1, 'acc'])

lrate = LearningRateScheduler(step_decay)
checkpoint = ModelCheckpoint("/content/drive/My Drive/bird_classification/models/inception_v3_cropped_retrained.h5",
                             monitor="val_acc",
                             mode="max",
                             save_best_only = True,
                             verbose=1)

nb_train_samples = 941
nb_validation_samples= 92
epochs=12
batch_size=16

history = model_retrain.fit_generator(train_generator,
                                 steps_per_epoch=nb_train_samples // batch_size,
                                 epochs=epochs,
                                 callbacks=[lrate, checkpoint],
                                 validation_data=validation_generator,
                                 validation_steps=nb_validation_samples // batch_size)
score = model_retrain.evaluate(train_generator, verbose=1)
score = model_retrain.evaluate(validation_generator, verbose=1)<jupyter_output>6/6 [==============================] - 0s 48ms/step - loss: 0.3911 - precision: 0.9194 - recall: 0.8472 - f1: 0.8801 - acc: 0.8804
{'fraction_non_alphanumeric': 0.11712015086206896, 'fraction_numerical': 0.04027478448275862, 'mean_word_length': 2.7928480204342274, 'pattern_counts': {'":': 1, '<': 23, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 25, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '630267', 'license': 'MIT', 'n_tokens_mistral': 5093, 'n_tokens_neox': 4667, 'n_words': 873, 'path': 'inception_v3_finetune.ipynb', 'repo_name': 'omarsou/bird_species_classification', 'size': '14848'}