Monday, January 22, 2024

ML: Image classification via fine-tuning with EfficientNet

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
# https://keras.io/examples/vision/image_classification_efficientnet_fine_tuning/

import numpy as np
import tensorflow_datasets as tfds
import tensorflow as tf
import matplotlib.pyplot as plt
import keras
from keras import layers
from keras.applications import EfficientNetB0

IMG_SIZE=224 # IMG_SIZE is determined by EfficientNet Model choice
BATCH_SIZE=64

# Loading data
dataset_name="stanford_dogs"
(ds_train, ds_test), ds_info=tfds.load(
dataset_name, split=["train", "test"], with_info=True, as_supervised=True
)
NUM_CLASSES=ds_info.features["label"].num_classes


# When the dataset include images with various size, we need to resize them into a shared size. The Stanford Dogs dataset includes only images at least 200x200 pixels in size. Here we resize the images to the input size needed for EfficientNet.
size=(IMG_SIZE, IMG_SIZE)
ds_train=ds_train.map(lambda image, label:(tf.image.resize(image, size), label))
ds_test=ds_test.map(lambda image, label:(tf.image.resize(image, size), label))

def format_label(label):
    string_label=label_info.int2str(label)
    return string_label.split("-")[1]

label_info=ds_info.features["label"]
for i, (image, label) in enumerate(ds_train.take(9)):
    ax=plt.subplot(3, 3, i+1)
    plt.imshow(image.numpy().astype("uint8"))
    plt.title("{}".format(format_label(label)))
    plt.axis('off')


% Data augmentation
img_augmentation_layers=[
    layers.RandomRotation(factor=0.15),
    layers.RandomTranslation(height_factor=0.1, width_factor=0.1),  # A preprocessing layer which randomly translates images during training. 
    layers.RandomFlip(),  # A preprocessing layer which randomly flips images during training.
    layers.RandomContrast(factor=0.1),  # A preprocessing layer which randomly adjusts contrast during training.
]


def img_augmentation(images):
    for layer in img_augmentation_layers:
        images=layer(images)
    return images

# Here we plot 9 examples of augmentation result of a given figure.
for image, label in ds_train.take(1):
    for i in range(9):
        ax=plt.subplot(3, 3, i+1)
        aug_img=img_augmentation(np.expand_dims(image.numpy(), axis=0))
        aug_img=np.array(aug_img)
        plt.imshow(aug_img[0].astype("uint8"))
        plt.title("{}".format(format_label(label)))
        plt.axis('off')



def input_preprocess_train(image, label):  # One-hot/categorical encoding
    image=img_augmentation(image)
    label=tf.one_hot(label, NUM_CLASSES)  # Returns a one-hot tensor.
    return image, label


def input_preprocess_test(image, label):
    label=tf.one_hot(label, NUM_CLASSES)  # Returns a one-hot tensor.
    return image, label

ds_train=ds_train.map(input_preprocess_train, num_parallel_calls=tf.data.AUTOTUNE)
ds_train=ds_train.batch(batch_size=BATCH_SIZE, drop_remainder=True)
ds_train=ds_train.prefetch(tf.data.AUTOTUNE)

ds_test=ds_test.map(input_preprocess_test, num_parallel_calls=tf.data.AUTOTUNE)
ds_test=ds_test.batch(batch_size=BATCH_SIZE, drop_remainder=True)

# Training a model from scratch
model=EfficientNetB0(
    include_top=True,
    weights=None,
    classes=NUM_CLASSES,
    input_shape=(IMG_SIZE, IMG_SIZE, 3),
)

model.compile(optimizer='adam', loss="categorical_crossentropy", metrics=["accuracy"])
model.summary()

# all model.summary() to print a useful summary of the model, which includes:
# Name and type of all layers in the model.
# Output shape for each layer.
# Number of weight parameters of each layer.
# If the model has general topology (discussed below), the inputs each layer receives
# The total number of trainable and non-trainable parameters of the model.

epochs=20

hist=model.fit(ds_train, epochs=epochs, validation_data=ds_test)

No comments:

Post a Comment