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 (opens in a new tab) 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 (opens in a new tab). 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 (opens in a new tab) / tensorflow fine tunning (opens in a new tab) a technique that used other computer vision models to train on other classification problems. On this problem inception v3 model (opens in a new tab) 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,)