Most Popular Convolutional Neural Networks Architectures | by Victor Roman | Towards Data Science

The objective of this article is to explore in-depth the concepts of:
Most popular CNN architectures
How to implement them with Keras to perform image classification
There are research teams fully dedicated to developing deep learning architectures for CNN and to training them in huge datasets, so we will take advantage of this and use them instead of creating a new architecture every time we face a new problem.
This will provide us with stability and precision.
The most common deep learning architectures for CNN today are:
VGG
ResNet
Inception
Xception
Let’s explore them.
This architecture, which was one of the first to appear, was introduced by Simonyan and Zisserman in 2014 with their paper entitled Very Deep Convolutional Networks for Large Scale Image Recognition. This paper is available here: https://arxiv.org/abs/1409.1556.
It is a simple architecture, using only blocks composed of an incremental number of convolutional layers with 3x3 size filters. Besides, to reduce the size of the activation maps obtained, max-pooling blocks are interspersed between the convolutional ones, reducing the size of these activation maps by half. Finally, a classification block is used, consisting of two dense layers of 4096 neurons each, and the last layer, which is the output layer, of 1000 neurons.
The 16 and 19 refer to the number of weighted layers that each network has (convolutional and dense layers, pooling layers are not counted). They correspond to columns D and E in the table below.
The rest of the architectures in the table are there because, at that time, Simonyan and Zisserman had a hard time training their architecture to converge. Since they couldn’t do it, what they came up with was to train networks with simpler architectures first, and once these converged and were trained, they took advantage of their weights to initialize the next network, which was a little more complex, and so on until they got to the VGG19. This process is known as “pre-training”.
However, this was in those times, now it is no longer done, as it requires too much time. Now we can achieve the same thing using the initialization of Xavier/Glorot or He et al. You can find more about it in this article.
This network, however, has a couple of disadvantages:
It takes too long to train
It has a very high number of parameters
The ResNet architecture, developed by He et al. in 2015 (you can see their paper called “Deep Residual Learning for Image Recognition” here: https://arxiv.org/abs/1512.03385), was a milestone in introducing an exotic type of architecture based on “modules”, or as it is now known, “networks within networks”.
These networks introduced the concept of “residual connections”, which you can see in the following image:
These blocks allow to reach the layer l+1l+1 part of the previous activation map without modification, and partly modified by the block belonging to the layer ll, as you can see in the image above.
In 2016 they improved this architecture by including more layers in these residual blocks, as you can see in the following image:
There are variations of ResNet with a different number of layers, but the most used is ResNet50, which consists of 50 layers with weights.
It is remarkable that although it has many more layers than the VGG, it needs much less memory, almost 5 times less. This is because this network, instead of dense layers in the classification stage, uses a type of layer called GlobalAveragePooling, which converts the 2D activity maps of the last layer in the feature extraction stage to an n-classes vector that is used to calculate the probability of belonging to each class.
This type of architecture, which was introduced in 2014 by Szegedy et al. in their paper “Going Deeper with Convolutions” (https://arxiv.org/abs/1409.4842), uses blocks with filters of different sizes that are then concatenated to extract features at different scales. Look at the image:
To help you understand this, the goal of the inception block is to calculate activation maps with 1x1, 3x3 and 5x5 convolutions to extract features at different scales. Then you simply concatenate all these activation maps into one.
This architecture requires even less memory than the VGG and ResNet.
This architecture was proposed by François Chollet (the creator of Keras) and the only thing he brings to Inception is that he optimally makes the convolutions so that they take less time. This is achieved by separating the 2D convolutions into 2 1D convolutions. If you are interested in knowing more, here is the paper: “Xception: Deep Learning with Depthwise Separable Convolutions”, https://arxiv.org/abs/1610.02357.
In terms of memory, it is very similar to Xception, and this is the outline of its architecture:
This network is extremely light (its weight is 5MB, compared to the 500MB of the VGG, or the 100MB of the Inception, for example) and achieves an accuracy of ~57% rank-1 or ~80% rank-5 with the ImageNet.
What do rank-1 and rank-5 or top-1 and top-5 mean?
rank-1 accuracy: we compare if the class with the highest probability according to our network matches the real tag
rank-5 accuracy: we compare if one of the 5 classes with higher probation according to our network matches the real label
How does this network manage to occupy so little and yet be so precise? It does so by using an architecture that “compresses” the data and then expands it, as you can see in the following image:
There are infinite architectures, but these are by far the most used. Normally, when we have a problem, we are not going to define our architecture, but we will use one of the previous ones.
Ok, now that you have seen them, let’s see how we can implement them in Keras
As usual, we’ll open up a Google Colaboratory notebook. Choose the code to run on GPUs to improve the speed and execute the following code.
!pip install imageio
# Import the necessary librariesfrom keras.applications import ResNet50from keras.applications import InceptionV3from keras.applications import Xception # solo con el backend de TensorFlowfrom keras.applications import VGG16from keras.applications import VGG19from keras.applications import imagenet_utilsfrom keras.applications.inception_v3 import preprocess_inputfrom keras.preprocessing.image import img_to_arrayfrom keras.preprocessing.image import load_imgimport numpy as npimport urllibimport cv2import matplotlib.pyplot as pltimport imageio as iodef predict_image(model_name, image_source):    # We define a dictionary that maps the network name with the Keras imported model  MODELS = {    "vgg16": VGG16,    "vgg19": VGG19,    "inception": InceptionV3,    "xception": Xception, # TensorFlow solo!    "resnet": ResNet50  }# We stablish the input size and image preprocessing function  input_shape = (224, 224)  preprocess = imagenet_utils.preprocess_input# If we use InceptionV3 or Xception, we need to stablish a different input image size (299x299) and use a different preprocessing function  if model_name in ("inception", "xception"):    input_shape = (299, 299)    preprocess = preprocess_inputprint("[INFO] loading {}...".format(model_name))  Network = MODELS[model_name]  model = Network(weights="imagenet") # We load the network with the weights already trained with the ImageNet, the first time we execute keras it will lead the weights, which size is about 500MB, so it will last a bit# We load the image and make sure it is in the appropiate size  print("[INFO] loading and pre-processing image...")  if type(image_source) == str:    image = load_img(image_source, target_size=input_shape)    image = np.resize(image, (input_shape[0], input_shape[1], 3))    image = img_to_array(image)  else:    image = np.resize(image_source, (input_shape[0], input_shape[1], 3))    image = img_to_array(image)# The image is represented as an array of size: (inputShape[0], inputShape[1], 3) and we need: (1, inputShape[0]. inputShape[1], 3), so we expand the dimensions  image = np.expand_dims(image, axis=0)# we preprocess the image  image = preprocess(image)# We predict the class of the image  print("[INFO] classifying image with '{}'...".format(model_name))  preds = model.predict(image)  P = imagenet_utils.decode_predictions(preds)# We show the predictions rank-5 and their likelihood  for (i, (imagenetID, label, prob)) in enumerate(P[0]):    print("{}. {}: {:.2f}%".format(i + 1, label, prob * 100))img = io.imread(image_source)  (imagenetID, label, prob) = P[0][0]  cv2.putText(img, "Label: {}, {:.2f}%".format(label, prob * 100), (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2)  plt.imshow(img)  plt.axis('off')    return model
# download images!wget https://image.ibb.co/cuw6pd/soccer_ball.jpg!wget https://image.ibb.co/hdoVFJ/bmw.png!wget https://image.ibb.co/h0B6pd/boat.png!wget https://image.ibb.co/eCyVFJ/clint_eastwood.jpg
!ls -la *.*
model = predict_image('resnet', 'soccer_ball.jpg')
model = predict_image('vgg16', 'bmw.png')
model.summary()
model = predidct_image('inception', 'clint_eastwood.jpg')
model.summary()
The result of the network architecture is so big that won’t fit here:
As always, I hope you enjoyed the post, and that you gained an intuition about how to implement and develop a convolutional neural network!
If you liked this post then you can take a look at my other posts on Data Science and Machine Learning here.
If you want to learn more about Machine Learning, Data Science and Artificial Intelligence follow me on Medium, and stay tuned for my next posts!