Building a blood cell classification model using Keras and tfjs | by Narasimha Prasanna HN | Towards Data Science

AI is really a major game changer. Applications of AI are huge and it’s scope in the field of healthcare is vast. Advanced AI tools can assist doctors and lab technicians to diagnose diseases with better accuracy, for example a doctor in Nigeria can use this tool to identify a disease from a sample of blood which he is not at all aware of, this helps him to better understand the disease and thus cures can be developed in a faster way, this is one such advantage of democratizing AI, because AI models and tools are accessible world wide , a doctor in Nigeria can use the same tools and technologies that are being used by research scholars in MIT or any other great universities in the world.
Machine Learning is of course the major ingredient of today’s AI advancements. But democratizing AI means making an infrastructure that allows anyone to build powerful tools using same techniques across the world. The two major problems that might forbid anyone from building AI are Computation Power and unavailability of datasets for training. But these problems are being addressed in interesting ways, they are as follows :
Kaggle (Home of datasets) : Unavailability of datasets is one of the major problem, but Kaggle is the best place where people can create datasets and host them to make it available for others, people have built amazing things using these tools.
Google co-lab : Google co-lab is the major driver of Machine Learning that allows anyone with google account to access a GPU. Without these GPUs it is impossible for anyone to train ML models that require huge computation.
Dataset is like a gold-mine for Data Scientist, if dataset is available for a particular problem , it reduces a lot of effort required by engineering team , because there is no need for developing an infrastructure to collect and store data. Few months back I thought of developing this system , Kaggle helped me a lot to obtain the dataset. This is the dataset I found on Kaggle, thanks to Paul Mooney for making this available.
Dataset Structure : The dataset contains 12,500 augmented images of blood cells. The dataset is comprised of 4 classes as shown below :
Each of the class contains 3000 images. The figure shows sample images from each class:
I reduced the size of each image to (80x80x3) to make it more easier to train.
Kaggle requires you to login before downloading the dataset, since we are using colab, it is not required to download the dataset on our local machine, instead we pull it to our google colab instance.
In simple words Google co-lab provides a cloud based python notebook with a virtual instance tied to a GPU runtime, the GPU runtime of google colab is powered by NVIDIA k-80, a powerful GPU and expensive too. But co-lab allows us to use the GPU for free without having to pay for it. Maximum time of an instance is 12 hours, after 12 hours the instance will be destroyed and new one will be created, so we can perform only those computations that doesn’t last longer than 12 hours. Let’s look at how we can use colab to train our Neural Network.
Authenticate with Kaggle :
Kaggle CLI allows you to download datasets and submit code/notebooks to competitions. Once you register for kaggle, you can download kaggle.json file which contains all credentials, kaggle CLI uses these credentials for authorization.
Create a new cell and create a hidden directory called .kaggle , use the command !mkdir .kaggle
Install Kaggle CLI using pip : In a new cell — !pip install kaggle
Download the dataset: !kaggle datasets download -d paulthimothymooney/blood-cells
Make sure all the directories are present in the downloaded dataset !ls dataset2-master/images
You should see 3 directories : TEST, TEST_SIMPLE and TRAIN
The directory TRAIN contains training images, we will be using this directory for training images.
Pre-processing :
We need to load images as numpy arrays and provide it to the neural network we are training. We will be using Keras to build a neural network, Keras provides a built-in ImageDataGenerator which handles most of the preprocessing tasks.
We import some objects required for developing the model :
from keras.models import Sequentialfrom keras.layers import Dense, Conv2D, Dropout, MaxPool2D, Flattenfrom keras.preprocessing import image
keras.preprocessing provides methods and objects required to handle various types of datasets. from image module we create an ImageDataGenerator with all the required configuration.
generator = image.ImageDataGenerator(        rescale = 1./255,        featurewise_center=False,  # set input mean to 0 over the dataset        samplewise_center=False,  # set each sample mean to 0        featurewise_std_normalization=False,  # divide inputs by std of the dataset        samplewise_std_normalization=False,  # divide each input by its std        zca_whitening=False,  # apply ZCA whitening        rotation_range=10,  # randomly rotate images in the range (degrees, 0 to 180)        width_shift_range=0.1,  # randomly shift images horizontally (fraction of total width)        height_shift_range=0.1,  # randomly shift images vertically (fraction of total height)        horizontal_flip=True,  # randomly flip images        vertical_flip=False)
As stated in the previous section, the training data is present in `dataset2-master/images/TRAIN directory, we provide this path to ImageDataGenerator so that all our configurations and augmentations are applied on the training images.
dataset = generator.flow_from_directory(    shuffle = True,    batch_size = 32,    target_size = (80, 80),    directory = 'dataset2-master/images/TRAIN')
This is all about preprocessing, you can tweak these parameters to make even more better fit by either decreasing or increasing the effect of image augmentation, there is always a scope for improvement.
A CNN (Convolution Neural network) is a Neural network, that contains a set of Convolution layers and a feed forward network attached to it. Convolution operation is not a new one, it is being used in Image Processing since many years. The major role of a Convolution operation is to extract edges from an image, in other terms, they can be used to extract important features of an image, if so called Filter Values are known, it is not possible for anyone to identify optimal filter values for any image , because we are using Convolution along with a Neural network, gradient descent will automatically optimize filter values to extract most important features of an image. Andrew Ng’s course deeplearning.ai helps you to better understand the working of such networks. As it is out of the scope of this article.
CNNs are must required for this task, because it is not possible for a simple feed forward network to learn the unique features present in the each classes of the dataset. The architecture of the CNN we used is as shown below :
I created a function model() that returns a sequential model as shown below:
def model():    model = Sequential()    model.add(Conv2D(80, (3,3), strides = (1, 1), activation = 'relu'))    model.add(Conv2D(64, (3,3), strides = (1, 1), activation = 'relu', input_shape = (80, 80, 3)))    model.add(MaxPool2D(pool_size = (2,2)))    model.add(Conv2D(64, (3,3), strides = (1,1), activation = 'relu'))    model.add(Dropout(0.25))    model.add(Flatten())    model.add(Dense(128, activation = 'relu'))    model.add(Dropout(0.5))    model.add(Dense(4, activation = 'softmax'))    model.compile(loss = 'categorical_crossentropy', optimizer = 'adadelta', metrics = ['accuracy'])        return model
Finally we train the model as shown :
nn = model()nn.fit_generator(dataset, steps_per_epoch = None, epochs = 30, verbose = 1)nn.save('Model.h5')
The model was trained for 30 epochs and accuracy of 92.67% was obtained, well this is a good accuracy, you can add more layers or perform hyperparameter tuning to improve the accuracy.
Once training is done, we need to deploy the model to production, so that everyone can use it, There are various strategies available for deploying a machine learning system. I wanted to run the entire inference on client-machine, so I started building a web app which can do so.
We require following requirements to build a client app , the app has following architecture :
Install node and npm and have an environment set up , install following dependencies in same order :
npm install -g create-react-appcreate-react-app app_namecd app_namenpm install --save @tensorflow/tfjs//on server side:mkdir servercd servernpm init//fill up the details, make sure package.json is creatednpm install express --save
Model Server : This is a express.js REST endpoint, clients can request for the model file by sending a REST GET request. (on server side)
Model Storage : We need to create a model that is compatible with tfjs, tensorflow provides a tool called tensorflowjs, it is a python toolkit that contains utilities, we can use following command to install it: pip install tensorflowjs
once done, we can use tensorflowjs_converter to convert the model to tfjs format using below command :
$tensorflowjs_converter --input_format keras \                        Model.h5 \                        ModelData/model_data// Model.h5 is the downloaded model after training, last argument is the target folder, where we need to store the model files.
Once converted, it will create a group of files called shards, shards are obtained by splitting the model based on layers, each shard contains weights of a particular layer. Using shards is very helpful, as each shard can be stored on different places and can be downloaded when required, so we can build a distributed storage for out machine learning model. model.json is of course the file that contains information of each shard. We can modify this file if in case we change the directory of a shard. On API call we only send model.json file to the client, tfjs will automatically fetch each shard to assemble a model on the client machine, i.e the browser.
In this section, I will not be stressing much on the UI design, instead I will stress upon the inference part, i.e how to run inference using tfjs , we installed. Go the react app directory.
Create a model container class : I first created a wrapper class for our model. An instance of this class represents a model that is ready for inference. The code of this model class is self understandable :
An inference function : I defined a function that can take model object and input image source, the input source can be HTML img , or a URL , or a byte stream of an image.
The code is as shown:
Initializing model object : We now have to create model object that can hold a model for inference.
let modelCache = new ModelContainer(null);modelCache.loadFromURL('http://192.168.0.105:5443/model_metadata')
Running inference : Once we have a model object, we can run inference anytime we want, According to the UI I designed, the inference should be executed whenever user clicks on predict button. So the part of React component which runs prediction is as shown below:
This project was really a great experience for me, I learnt how to use google colab for training ML models on the cloud, I also learnt how to deploy ML models for production.
This is an open source project, feel free to make changes :
REPO URL : react-client
Cloud Notebook (For model training): training.ipynb
Thank you so much for spending your valuable time for reading this article. Kindly start the repo, if you are interested. You can also connect with me on Linkedin.