Building MobileNet from Scratch Using TensorFlow | by Arjun Sarkar | Towards Data Science

Previously I have discussed the architecture of MobileNet and its most important layer “Depthwise Separable Convolutions” in the story — Understanding Depthwise Separable Convolutions and the efficiency of MobileNets.
Next, we will see how to implement this architecture from scratch using TensorFlow.
Figure 2 shows the MobileNet architecture that we will implement in code. The network starts with Vonv, BatchNorm, ReLU block, and follows multiple MobileNet blocks from thereon. It finally ends with an Average Pooling and a Fully connected layer, with a Softmax activation.
We see the architecture has the pattern — Conv dw/s1, followed by Conv/s1, and so on. Here dw is the depthwise layer with the number of strides, followed by the Conv layer with the number of strides. These two lines are the MobileNet block.
The ‘Filter Shape’ column gives the details about the kernel size and the number of filters to be used. The last number of the column gives the number of filters. We see the filter number gradually increase from 32 to 64, 64 to 128, 128 to 256, and so on.
The last column shows how the size of the image changes as we go deeper into the network. The input size is chosen as 224*224 pixels, with 3 channels and the output layer classifies 1000 classes.
Few things to keep in mind while constructing the network:
All layers are followed by a Batch Normalization and a ReLU nonlinearity.Unlike normal CNN models which have a Conv2D layer, MobileNet’s have Depthwise Conv layers, as seen in Figure 3. To understand this layer better please refer to — Depthwise Convolutional Blocks.
All layers are followed by a Batch Normalization and a ReLU nonlinearity.
Unlike normal CNN models which have a Conv2D layer, MobileNet’s have Depthwise Conv layers, as seen in Figure 3. To understand this layer better please refer to — Depthwise Convolutional Blocks.
Import all the necessary layers from the TensorFlow libraryWriting a helper function for the MobileNet blockBuilding the stem of the modelUse the helper function to build the main part of the model
Import all the necessary layers from the TensorFlow library
Writing a helper function for the MobileNet block
Building the stem of the model
Use the helper function to build the main part of the model
Importing the layers
import tensorflow as tf#import all necessary layersfrom tensorflow.keras.layers import Input, DepthwiseConv2Dfrom tensorflow.keras.layers import Conv2D, BatchNormalizationfrom tensorflow.keras.layers import ReLU, AvgPool2D, Flatten, Densefrom tensorflow.keras import Model
Keras has a DepthwiseConv layer already built-in, so we do not need to create it from scratch.
MobileNet block
For creating the function for the MobileNet block, we need the following steps:
Input to the function:
Input to the function:
a. A tensor (x)
b. the number of filters for the convolutional layer (filters)
c. the strides for the Depthwise convolutional layer (strides)
2. Run (Figure 3 — right side image):
a. applying a 3x3 Dethwise convolutional layer with strides followed by a Batch Normalization layer and a ReLU activation
b. Applying a 1x1 Convolutional layer with filters followed by a batch normalization layer and a ReLU activation
3. Return the tensor (output)
These 3 steps are implemented in the code blocks below.
# MobileNet blockdef mobilnet_block (x, filters, strides):        x = DepthwiseConv2D(kernel_size = 3, strides = strides, padding = 'same')(x)    x = BatchNormalization()(x)    x = ReLU()(x)        x = Conv2D(filters = filters, kernel_size = 1, strides = 1)(x)    x = BatchNormalization()(x)    x = ReLU()(x)        return x
Building the stem of the Model
As seen in Figure 2, the first layer is Conv/s2 with filter shape 3x3x3x32.
#stem of the modelinput = Input(shape = (224,224,3))x = Conv2D(filters = 32, kernel_size = 3, strides = 2, padding = 'same')(input)x = BatchNormalization()(x)x = ReLU()(x)
The main part of the Model
# main part of the modelx = mobilnet_block(x, filters = 64, strides = 1)x = mobilnet_block(x, filters = 128, strides = 2)x = mobilnet_block(x, filters = 128, strides = 1)x = mobilnet_block(x, filters = 256, strides = 2)x = mobilnet_block(x, filters = 256, strides = 1)x = mobilnet_block(x, filters = 512, strides = 2)for _ in range (5):     x = mobilnet_block(x, filters = 512, strides = 1)x = mobilnet_block(x, filters = 1024, strides = 2)x = mobilnet_block(x, filters = 1024, strides = 1)x = AvgPool2D (pool_size = 7, strides = 1, data_format='channels_first')(x)output = Dense (units = 1000, activation = 'softmax')(x)model = Model(inputs=input, outputs=output)model.summary()
Plotting the Model
#plot the modeltf.keras.utils.plot_model(model, to_file='model.png', show_shapes=True, show_dtype=False,show_layer_names=True, rankdir='TB', expand_nested=False, dpi=96)
import tensorflow as tf#import all necessary layersfrom tensorflow.keras.layers import Input, DepthwiseConv2Dfrom tensorflow.keras.layers import Conv2D, BatchNormalizationfrom tensorflow.keras.layers import ReLU, AvgPool2D, Flatten, Densefrom tensorflow.keras import Model# MobileNet blockdef mobilnet_block (x, filters, strides):        x = DepthwiseConv2D(kernel_size = 3, strides = strides, padding = 'same')(x)    x = BatchNormalization()(x)    x = ReLU()(x)        x = Conv2D(filters = filters, kernel_size = 1, strides = 1)(x)    x = BatchNormalization()(x)    x = ReLU()(x)        return x#stem of the modelinput = Input(shape = (224,224,3))x = Conv2D(filters = 32, kernel_size = 3, strides = 2, padding = 'same')(input)x = BatchNormalization()(x)x = ReLU()(x)# main part of the modelx = mobilnet_block(x, filters = 64, strides = 1)x = mobilnet_block(x, filters = 128, strides = 2)x = mobilnet_block(x, filters = 128, strides = 1)x = mobilnet_block(x, filters = 256, strides = 2)x = mobilnet_block(x, filters = 256, strides = 1)x = mobilnet_block(x, filters = 512, strides = 2)for _ in range (5):     x = mobilnet_block(x, filters = 512, strides = 1)x = mobilnet_block(x, filters = 1024, strides = 2)x = mobilnet_block(x, filters = 1024, strides = 1)x = AvgPool2D (pool_size = 7, strides = 1, data_format='channels_first')(x)output = Dense (units = 1000, activation = 'softmax')(x)model = Model(inputs=input, outputs=output)model.summary()#plot the modeltf.keras.utils.plot_model(model, to_file='model.png', show_shapes=True, show_dtype=False,show_layer_names=True, rankdir='TB', expand_nested=False, dpi=96)
MobileNet is one of the smallest Deep Neural networks that are fast and efficient and can be run on devices without high-end GPUs. Implementation of these networks is very simple when using a framework such as Keras (on TensorFlow).
For learning about how to implement other famous CNN architectures using TensorFlow, kindly visit the links below -
XceptionResNetVGGDenseNet
Xception
ResNet
VGG
DenseNet
Howard, A.G., Zhu, M., Chen, B., Kalenichenko, D., Wang, W., Weyand, T., Andreetto, M., & Adam, H. (2017). MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications. ArXiv, abs/1704.04861.