Skip to main content

Implementations

Lets Jump In

First we need to understand the given dataset and what problem classification problem are we trying to solve. As in the introdction we are dealing with pictures so this jumps in to computer vision classification problem. As for image classification problems neural networks have been proven to be the right solution, without wasting anytime let start coding 🔥.

Data Preparation

In any machine learning problem data plays a big part. So first with need to prepare the data to be in the right order. We have being given image zipfile images.zip, a train label file train_label.csv and sample submission file SampleSubmission.csv. So we need to extract the data from image.zip file and filter the data from train and for submission.

1. Import Libraries

import cv2
import numpy as np
import os
import pandas as pd
from PIL import Image
import tensorflow as tf

from tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.utils import img_to_array
from tensorflow.keras.optimizers import RMSprop
import matplotlib.pyplot as plt

from tensorflow.keras import layers
from tensorflow.keras import Model
from tensorflow.keras.preprocessing.image import ImageDataGenerator

import shutil

With a google search you can learn what each libray does. I strong recommend to read the documentation from more information. After importing the libraries we start preparing the data.

2. Import the csv datasets By using the csv dataset train_labels and SampleSubmission it will enable to filter out the train set for the images.

df_train_labels = pd.read_csv("./csv_dataset/train_labels.csv")
df_submission = pd.read_csv("./csv_dataset/SampleSubmission.csv")

It adivise to view the dataset and to take a look that all the dataset are correct.

By using the train label it will help us to split the training and testing dataset. By the following the function that reading all the images from the directory then if it is not in the train_label file then it is a test data the rest are the training dataset. For the SampleSubmission file will be used later on filtering the images that will be used for inference and submission.

def train_test(dataset):
# From the dir of the total images or after unziping the folder

nameImage = os.listdir('./dataset/')

# Creating image file name and its target (0,1)
train_list = []
test_list =[]

for i in range(len(dataset)):
name = dataset.loc[i, "image"]
label = dataset.loc[i, "target"]

if (nameImage[i].replace(" ", "") in np.array(dataset["image"].replace(" ", ""))):
train_list.append([name, label])

else:
test_list.append([name, label])

return train_list , test_list

This function will return two list train and test that have the file name and its label.

# Get the train data and test data

train , test = train_test(df_train_labels)

print(f"The training dataset are {len(train)} and the test dataset are len(test) in totally")

The training dataset are 950 and the test dataset are 358 in totally

After filtering the data it important to storage the images in the respective label as it will help in dataloader function when its need to train the model. The file folders are consist of training and validation for both withmask and nomask. The test list from above will be store on the validation folder. And the sub folder will be used to store the submission images for inferences.

# Create the directory
os.makedirs("image", exist_ok=True)
os.makedirs("./image/train", exist_ok=True)
os.makedirs("./image/valid", exist_ok=True)

os.makedirs("./image/train/withMask", exist_ok=True)
os.makedirs("./image/train/noMask", exist_ok=True)

os.makedirs("./image/valid/withMask", exist_ok=True)
os.makedirs("./image/valid/noMask", exist_ok=True)

os.makedirs("./image/sub", exist_ok=True)
os.makedirs("./image/sub/sub", exist_ok=True)

After making directories images are needed to be stored in their corresponding labels

# Inserting the images to their respetive folders.
for i in train:

if i[1] == 1:

image = "./dataset/" + i[0]
target = "./image/train/withMask"
shutil.copy(image, target)

else:
image = "./dataset/" + i[0]
target = "./image/train/noMask"
shutil.copy(image, target)

for i in test:

if i[1] == 1:

image = "./dataset/" + i[0]
target = "./image/valid/withMask"
shutil.copy(image, target)

else:
image = "./dataset/" + i[0]
target = "./image/valid/noMask"
shutil.copy(image, target) # shutil.copy is used to copy file from one dir to another.

Training and Validation Generators

Generators will enable the fetching of images in their files and a batch and also a place to perform data augmentation. Data Augmentation is a techniques to make tranformation on the dataset to create more data and reduce overfiting.


TRAINING_DIR = "./image/train/"
VALIDATION_DIR = "./image/valid/"

def train_val_generators(TRAINING_DIR, VALIDATION_DIR):
"""
Creates the training and validation data generators

Args:
TRAINING_DIR (string): directory path containing the training images
VALIDATION_DIR (string): directory path containing the testing/validation images

Returns:
train_generator, validation_generator: tuple containing the generators
"""

# Instantiate the ImageDataGenerator class
train_datagen = ImageDataGenerator(rescale=1./255,
rotation_range=30,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest')

train_generator = train_datagen.flow_from_directory(directory=TRAINING_DIR,
batch_size=16,
class_mode="binary",
target_size=(256, 256))

validation_datagen = ImageDataGenerator(rescale=1./255)

validation_generator = validation_datagen.flow_from_directory(directory=VALIDATION_DIR,
batch_size=16,
class_mode="binary",
target_size=(256, 256))

return train_generator, validation_generator

The train_val_generators function helps in transforming the data and create a dataloader or data generator for the directory with a batch size of 16 and target size of 256. After this our dataset is read now lets jump on creating a model.

Creating a model

This is what you where waching for, on creating neural networks its important to understand different techniques that are used to create a more accuracy model. On this part we will take a look on tranfer learning / tensorflow fine tunning a technique that used other computer vision models to train on other classification problems. On this problem inception v3 model will be used.

1. Download the model

# Get the Invception_V3 model

!wget --no-check-certificate \
https://storage.googleapis.com/mledu-datasets/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5 \
-O /tmp/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5

2. Import the InceptionV3

# Import the inception model
from tensorflow.keras.applications.inception_v3 import InceptionV3

# Create an instance of the inception model from the local pre-trained weights
local_weights_file = '/tmp/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5'

3. Create a pre-trained model

This is done by using the InceptionV3 weightss

# Create the pretrain model from the imported model

def create_pre_trained_model(local_weights_file):

"""
Initializes an InceptionV3 model.

Args:
local_weights_file (string): path pointing to a pretrained weights H5 file

Returns:
pre_trained_model: the initialized InceptionV3 model

"""

pre_trained_model = InceptionV3(input_shape = (256, 256, 3),
include_top = False,
weights = None
)

pre_trained_model.load_weights(local_weights_file)

# Make all the layers in the pre-trained model non-trainable
for layer in pre_trained_model.layers:
layer.trainable = False

return pre_trained_model

4. Create an ouput layer

This is the layer that will be used to feed its output to the next neural networks.

def output_of_last_layer(pre_trained_model):
"""
Gets the last layer output of a model

Args:
pre_trained_model (tf.keras Model): model to get the last layer output from

Returns:
last_output: output of the model's last layer

"""

last_desired_layer = pre_trained_model.get_layer('mixed7')
print('last layer output shape: ', last_desired_layer.output_shape)
last_output = last_desired_layer.output
print('last layer output: ', last_output)


return last_output

5. Creating the final model

This combines the output layer, pre-train weights and the classification layer.

def create_final_model(pre_trained_model, last_output):
"""
Appends a custom model to a pre-trained model

Args:
pre_trained_model (tf.keras Model): model that will accept the train/test inputs
last_output (tensor): last layer output of the pre-trained model

Returns:
model: the combined model
"""
# Flatten the output layer to 1 dimension
x = layers.Flatten()(last_output)

# Add a fully connected layer with 1024 hidden units and ReLU activation
x = layers.Dense(512, activation='relu')(x)
x = layers.Dropout(0.4)(x)
x = layers.Dense(1024, activation='relu')(x)
# Add a dropout rate of 0.2
x = layers.Dropout(0.4)(x)
# Add a final sigmoid layer for classification
x = layers.Dense(1, activation='sigmoid')(x)

# Create the complete model by using the Model class
model = Model(inputs=pre_trained_model.input, outputs= x)

# Compile the model
model.compile(optimizer = RMSprop(learning_rate=0.001),
loss = 'binary_crossentropy',
metrics = [['accuracy', 'AUC', 'binary_accuracy']])



return model

6. Viewing the total parameter and the trainable parameters

model = create_final_model(pre_trained_model, last_output)

# Inspect parameters
total_params = model.count_params()
num_trainable_params = sum([w.shape.num_elements() for w in model.trainable_weights])

print(f"There are {total_params:,} total parameters in this model.")
print(f"There are {num_trainable_params:,} trainable parameters in this model.")

7. Training the model

This is the part that will be used to fit the dataset

history = model.fit(train_generator,
validation_data = validation_generator,
epochs = 100,
verbose = 2,
batch_size=10,)