Vietnam Dong Classifier with Tensor Flow 2

Minh Do
AI³ | Theory, Practice, Business
5 min readSep 2, 2019

This is the second part of VND Classifier with fastai. It discusses modeling with TensorFlow2 and deploying on Google Cloud Platform(GCP).

Before you begin

Modeling

Last time we discussed how to build the model using fastai library. This time, besides the topic of deployment on Google Cloud Platform, I decided to give Google’s Deep Learning Framework TensorFlow 2 a try.

TensorFlow 2.0 Beta was released in June 2019. And right after I finished building this model, TensorFlow 2.0 RC was released.

The model was trained on 1675 images:

+----------------+------------+
| Note Value | #image |
+----------------+------------+
| 1.000 VND | 68 |
| 10.000 VND | 164 |
| 100.000 VND | 200 |
| 2.000 VND | 176 |
| 20.000 VND | 185 |
| 200.000 VND | 203 |
| 5.000 VND | 253 |
| 50.000 VND | 219 |
| 500.000 VND | 217 |
+----------------+------------+

The dataset is quite small, so it doesn’t make sense to train a model from scratch. So I used the transfer learning from a pre-trained model (A pre-trained model is a saved network that was previously trained on a large dataset).

Another requirement of the model is portability. We want a model running on free tier environment of GCP (unless you can convince me that we can do business with this). So I chose MobileNetV2 from tf.keras.applications.

Model summary:

Model: “sequential_18”
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
mobilenetv2_1.00_192 (Model) (None, 6, 6, 1280) 2257984
_________________________________________________________________
global_average_pooling2d_18 (None, 1280) 0
_________________________________________________________________
dense_18 (Dense) (None, 9) 11529
=================================================================
Total params: 2,269,513
Trainable params: 1,051,529
Non-trainable params: 1,217,984

To generate batches of tensor images with real-time data augmentation, I used ImageDataGenerator. So intuitively it takes a bunch of images (a mini-batch) then applies a series of random transformations to each image in the batch and passes this randomly transformed batch to the model for training. The purpose of using ImageDataGenerator is that for every training step, the model will be trained with “new” data instead of the same origin data again and again.

Then I split the data into a training set (90%) and a test set (10%). Because I had a quite small dataset, so I wanted to train the model with as much data as I can. After ten epochs (an epoch is one complete run through all of our data points):

Validation accuracy: 69.79%

You can see the validation loss start to rise, and the gap between validation accuracy and training accuracy is bigger from time to time. This type of behavior is indicative of overfitting.

So far, we were only training two last layers on top of the base model MobileNetV2. One way to increase performance is to train (or “fine-tune”) the weights of the top layers of the pre-trained model. All you need to do is unfreeze the base model and set the bottom layers to be un-trainable. The base model MobileNetV2 has 155 layers, and I decided to start fine-tuning at layer 140. After ten more epochs:

Validation accuracy: 88.54%

We’re now up to 88.54%, an increase from our previous 69.79%. The gap between training accuracy and validation accuracy is smaller. By using fine-tuning, we were able to increase the performance of the model.

This solution may not be the best, and it looks like we can train the model longer. But I’m happy with this performance on the small dataset that we have. Let’s bring it online, share with friends, and hope we can get more data.

Deployment

Last time, I have tried to deploy the app on App Engine. But it was so slow, and I guessed that it’s too heavy for a free tier environment to handle with Flask and TensorFlow. And it’s also not a good practice to wrap everything in one place.

This demo app was deployed on the Google Cloud Platform, using

Before you begin:

  • Create a Google Cloud Platform project with billing enabled and install Google Cloud SDK.
  • Create a Cloud Storage Bucket and upload your model.
  • Create a folder `uploaded/` to store uploaded images

Set up the project:

gcloud auth login
gcloud config set project PROJECT_ID

Deploy to App Engine:
Open a terminal and switch to the `app/` directory:

gcloud app deploy

Deploy Cloud Function:
Open a terminal and switch to directory functions/classifier:

gcloud functions deploy classifier \
— runtime python37 \
— trigger-http \
— set-env-vars GCS_BUCKET=BUCKET_ID \
— region REGION \
— memory 2048

Summary

In this part, we discussed building the same model using TensorFlow 2 Beta 1. This time we had a validation set to evaluate the model better. We also discussed fine-tuning to improve the model’s performance. Last but not least, we split the app into components for easier and faster deployment.

Even there are still a lot of things to improve; I’m quite happy with this result for a toy project like this. I hope this can inspire you to build another app on your own idea or to beat me by training your better model. Good luck, and have fun!

--

--