DenseNet Architecture Explained with Code Examples
Using Keras and TensorFlow
Densenet is the last architecture we will explore in this series of articles about convolutional networks and image classification. If you already have some knowledge about classic Machine Learning, you can start here, and read all articles in the same order they were published. If you are a total beginner, don’t worry, you can buy my book from Amazon where you will find a complete guide to start with Classic Machine Learning, even if you don’t know how to code.
DenseNet, short for Densely Connected Convolutional Networks, is a deep learning architecture for image classification tasks introduced in 2017 with a paper with the same name.
The core idea behind DenseNet is the Dense Blocks, where the output of a layer is connected to each other layer that follows it in the same block. Therefore, a Dense Block consists of multiple layers, where each layer receives inputs from all previous layers and passes its own feature map to all subsequent layers.
Each layer within the Dense Block can also include a Bottleneck Layer, which is a 1x1 convolution used to reduce the number of channels, and this way reduces the computational cost. It helps in dimensionality reduction before the subsequent 3x3 convolution.
Let’s take a look at a DenseBlock schema, in this example with 4 layers, but it can include as many layers as you want:
The previous image can be further simplified as:
Where each layer is:
We can transform this schema into Python code:
def dense_block(x, num_layers, growth_rate):
# Create a dense block with 'num_layers' layers
for _ in range(num_layers):
#Store the initial values of x to be concatenated
x_input = x
# BatchNormalization and ReLU activation
x = BatchNormalization()(x)
x = ReLU()(x)
# 1x1 bottleneck convolution
x = Conv2D(growth_rate, (1, 1), padding='same')(x)
# 3x3 convolution
x = Conv2D(growth_rate, (3, 3), padding='same')(x)
# Concatenate with the input
x = Concatenate(axis=-1)([x_input, x])
return x
To build a full DenseNet model we just need to include the DenseBlocks in our desired architecture. We can see a simple neural Dense Network example with only two Dense Blocks as follows:
Which we can transform into Python code:
import tensorflow as tf
from tensorflow.keras.layers import Input, Conv2D, BatchNormalization, ReLU, Concatenate, AveragePooling2D, GlobalAveragePooling2D, Dense
from tensorflow.keras.models import Model
def dense_block(x, num_layers, growth_rate):
# Create a dense block with 'num_layers' layers
for _ in range(num_layers):
#Store the initial values of x to be concatenated
x_input = x
# BatchNormalization and ReLU activation
x = BatchNormalization()(x)
x = ReLU()(x)
# 1x1 bottleneck convolution
x = Conv2D(growth_rate, (1, 1), padding='same')(x)
# 3x3 convolution
x = Conv2D(growth_rate, (3, 3), padding='same')(x)
# Concatenate with the input
x = Concatenate(axis=-1)([x_input, x])
return x
# Hyperparameters
input_shape = (224, 224, 3) # Example input shape for RGB images
num_classes = 10 # Number of output classes
growth_rate = 32 # Growth rate controls the number of channels in each layer within a DenseBlock
num_layers_per_block = 4 # Number of layers in each DenseBlock
# Input layer
input_layer = Input(shape=input_shape)
# Initial convolution layer
x = Conv2D(64, (7, 7), strides=(2, 2), padding='same')(input_layer)
x = BatchNormalization()(x)
x = ReLU()(x)
# First DenseBlock
x = dense_block(x, num_layers_per_block, growth_rate)
# Transition layer (reduce spatial dimensions)
x = BatchNormalization()(x)
x = ReLU()(x)
x = Conv2D(128, (1, 1), padding='same')(x)
x = AveragePooling2D((2, 2), strides=(2, 2))(x)
# Second DenseBlock
x = dense_block(x, num_layers_per_block, growth_rate)
# Global Average Pooling
x = GlobalAveragePooling2D()(x)
# Fully connected layer for classification
x = Dense(num_classes, activation='softmax')(x)
# Create the model
model = Model(inputs=input_layer, outputs=x)
# Compile the model
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
# Print the model summary
model.summary()
Thank you for reading! Don’t forget to subscribe to receive notifications about my future publications.
If: you liked this article, don’t forget to follow me and thus receive all updates about new publications.
Else If: you want to read more on the topic, you can buy my book “Data-Driven Decisions: A Practical Introduction to Machine Learning” which will give you all the information you need to start with Machine Learning. It will cost you only a coffee, and give me a small tip!
Else: Thank you!