DenseNet201 Explained from Scratch: Learn Dense Convolutional Networks the Easy Way (Complete Beginner Guide)
In this article, we’ll learn DenseNet201 from scratch in a simple and beginner-friendly way. We will understand the intuition behind DenseNet first, then learn its architecture, and finally build a complete image classification implementation using TensorFlow and a pre-trained DenseNet201 model.
What is DenseNet?
DenseNet stands for:
Dense Convolutional Network
Despite the new name, DenseNet is still a Convolutional Neural Network (CNN).
It performs image classification just like a normal CNN.
The main difference is not the operations performed, but how information flows between layers.
DenseNet is Still a CNN
Since DenseNet is a CNN, all the familiar components are still present.
It still contains:
- Convolution Layers
- ReLU Activation Function
- Pooling Layers
- Batch Normalization
- Global Average Pooling (or sometimes Flatten)
- Fully Connected (Dense) Layer
- Softmax Activation for Classification
Nothing has been removed.
Instead, DenseNet introduces a smarter way for convolution layers to communicate with one another.
Why Was DenseNet Created?
Before understanding DenseNet, let’s first look at how a normal CNN works.
Imagine a CNN with four convolution layers.
Image
↓
Conv1
↓
Conv2
↓
Conv3
↓
Conv4This is called a sequential architecture because every layer only receives information from the layer immediately before it.
For example:
- Conv2 only receives the output of Conv1.
- Conv3 only receives the output of Conv2.
- Conv4 only receives the output of Conv3.
Notice something important.
As we move deeper into the network, the information learned by earlier layers becomes less directly accessible.
The fine details extracted in the first few layers gradually become diluted as information passes through many intermediate layers.
This is one of the major limitations of traditional CNN architectures.
The Main Idea Behind DenseNet
The creators of DenseNet asked a simple question:
Why should a convolution layer receive information from only the previous layer?
Why not allow it to receive information from every earlier layer?
Instead of this:
Image
↓
Conv1
↓
Conv2
↓
Conv3
↓
Conv4DenseNet connects layers like this:
Now every layer receives:
- Output of Conv1
- Output of Conv2
- Output of Conv3
- And so on…
Every new layer has access to all previously learned features.
This is why the architecture is called Dense Convolutional Network. The connections between layers are dense.
Understanding Dense Connections
The most important concept in DenseNet is the Dense Connection.
A dense connection means:
Every convolution layer receives the outputs of all previous convolution layers.
Instead of forgetting earlier features, DenseNet preserves them throughout the entire network.
This makes learning much more efficient.
Why Is This Better?
Think about image classification.
The first convolution layer may detect:
- Edges
- Lines
- Corners
The middle layers may detect:
- Eyes
- Wheels
- Windows
- Fur
The deeper layers may detect:
- Faces
- Cars
- Dogs
- Cats
In a traditional CNN, the final layers mostly receive high-level features.
In DenseNet, the final layers receive:
- Low-level features
- Mid-level features
- High-level features
All together.
This richer feature representation often leads to better performance.
Advantages of DenseNet
Because every layer has access to all previous feature maps, DenseNet offers several important benefits.
1. Better Feature Reuse
Earlier features are never discarded.
Instead of learning similar features repeatedly, later layers simply reuse what earlier layers have already learned.
This reduces unnecessary computation.
2. Stronger Information Flow
Information can travel directly from earlier layers to later layers.
The network does not have to pass everything through many intermediate layers.
This makes learning easier.
3. Better Gradient Flow
During backpropagation, gradients can travel directly through dense connections.
As a result, DenseNet suffers much less from the vanishing gradient problem, especially in very deep networks.
4. Fewer Parameters
One surprising advantage of DenseNet is that it often uses fewer parameters than many other deep CNN architectures.
Since features are reused instead of repeatedly relearned, the network becomes more parameter-efficient.
5. Higher Accuracy
DenseNet usually achieves excellent performance on image classification tasks because it combines information from every previous layer.
What is DenseNet201?
DenseNet comes in several versions.
The number represents the total number of layers.
Popular versions include:
- DenseNet121
- DenseNet169
- DenseNet201
- DenseNet264
Among these, DenseNet201 is one of the most popular choices because it provides an excellent balance between depth and performance.
The “201” simply means the architecture contains approximately 201 layers. A deeper network allows the model to learn more complex visual patterns while still benefiting from dense connections.
Transfer Learning with DenseNet201
Training a DenseNet201 model from scratch requires:
- Millions of images
- Powerful GPUs
- A very long training time
Fortunately, we don’t need to train everything ourselves.
Instead, we use Transfer Learning.
Transfer Learning means using a model that has already been trained on a massive dataset, such as ImageNet, and adapting it to our own classification problem.
The pre-trained DenseNet201 has already learned useful visual features like:
- Edges
- Shapes
- Textures
- Objects
- Patterns
Instead of learning these again, we simply reuse them and train only the final classifier for our dataset. This makes training much faster while achieving excellent accuracy.
Dense Block
Now that we understand the idea of Dense Connections, let’s see how DenseNet is actually organized internally.
DenseNet is not simply a long sequence of convolution layers.
Instead, the network is divided into several groups called Dense Blocks.
A Dense Block is a collection of convolution layers where every layer is connected to every previous layer inside that block.
Transition Layer
After one Dense Block finishes, the feature maps become very large because each layer keeps adding new features.
If we continue growing the feature maps forever, the model would become too large to train.
To solve this problem, DenseNet introduces the Transition Layer.
A Transition Layer sits between two Dense Blocks.
Its main job is to reduce the size of the feature maps before sending them to the next Dense Block.
A Transition Layer typically contains:
- Batch Normalization
- ReLU Activation
- 1×1 Convolution
- Average Pooling
Its responsibilities are:
- Reduce the number of feature maps.
- Reduce the spatial dimensions (height and width).
- Lower memory usage.
- Speed up training
Growth Rate
One unique concept in DenseNet is the Growth Rate.
Let’s understand it with an example. Suppose the input to a Dense Block has 64 feature maps.
If every convolution layer produces 32 new feature maps, then:
- Input = 64 feature maps
- Layer 1 adds 32 → Total = 96
- Layer 2 adds another 32 → Total = 128
- Layer 3 adds another 32 → Total = 160
- Layer 4 adds another 32 → Total = 192
Notice something important.
Each layer does not replace the previous feature maps.
Instead, it creates new feature maps that are concatenated with all previous ones. The number of new feature maps produced by each layer is called the Growth Rate, usually represented by k.
For DenseNet201:
- Growth Rate (k) = 32
This means every convolution layer contributes 32 new feature maps.
As we move deeper into a Dense Block, the total number of feature maps keeps increasing. This gradual increase is called the growth of the network.
Bottleneck Layer
You might notice another problem.
As feature maps continue increasing, every 3×3 convolution would become computationally expensive.
Get Muhammadsufian’s stories in your inbox
Join Medium for free to get updates from this writer.
DenseNet solves this using a Bottleneck Layer.
Instead of directly applying a 3×3 convolution, DenseNet first performs a 1×1 convolution.
The bottleneck performs two important tasks:
- Reduces the number of input feature maps.
- Makes the following 3×3 convolution much faster.
DenseNet201 Implementation in TensorFlow:
Step 1: Import Required Libraries
First, import all the required libraries.
from tensorflow.keras.preprocessing.image import image_dataset_from_directory
from tensorflow.keras.applications import DenseNet201
from tensorflow.keras.layers import GlobalAveragePooling2D
from tensorflow.keras.layers import Dense
from tensorflow.keras.layers import Dropout
from tensorflow.keras.models import SequentialWhat does each library do?
TensorFlow
TensorFlow is the deep learning framework that helps us build and train neural networks.
import tensorflow as tfimage_dataset_from_directory
Loads images directly from folders.
image_dataset_from_directory()Instead of manually reading images one by one, TensorFlow automatically:
- Reads images
- Assigns labels
- Creates batches
- Resizes images
DenseNet201
Loads the pre-trained DenseNet201 model.
DenseNet201This model has already been trained on the ImageNet dataset.
Instead of training from scratch, we’ll reuse its learned features.
GlobalAveragePooling2D
Converts feature maps into a single feature vector.
Instead of using a Flatten layer, DenseNet commonly uses Global Average Pooling because it requires fewer parameters and helps reduce overfitting.
Dense Layer
Creates our custom classifier.
Dropout
Randomly disables neurons during training. This helps prevent overfitting.
Step 2: Load the Dataset
Suppose your dataset is organized like this:
dataset/train/
cats/
dogs/validation/
cats/
dogs/test/
cats/
dogs/
Load the training dataset.
train_dataset = image_dataset_from_directory(
"dataset/train",
image_size=(224,224),
batch_size=32
)Load the validation dataset.
validation_dataset = image_dataset_from_directory(
"dataset/validation",
image_size=(224,224),
batch_size=32
)Load the testing dataset.
test_dataset = image_dataset_from_directory(
"dataset/test",
image_size=(224,224),
batch_size=32
)Understanding Every Parameter
dataset/train
This is the folder containing all training images.
TensorFlow automatically assigns labels based on folder names.
cats → Label 0dogs → Label 1image_size=(224,224)
DenseNet201 expects input images of size
224 × 224TensorFlow resizes every image automatically.
batch_size=32
Instead of training on all images at once,
TensorFlow trains on
32 images↓Update weights↓Next 32 images
This is faster and uses less memory.
Step 3: Load the Pre-trained DenseNet201 Model
base_model = DenseNet201(
weights="imagenet",
include_top=False,
input_shape=(224,224,3)
)Let’s understand each parameter.
weights=”imagenet”
Loads weights already learned from over one million images in the ImageNet dataset.
Instead of starting with random weights, the model already knows how to detect edges, textures, shapes, and objects.
include_top=False
The original DenseNet201 was trained to classify 1,000 ImageNet classes.
We don’t need that classifier.
So we remove it.
We’ll build our own classifier.
input_shape=(224,224,3)
The model expects:
- Height = 224
- Width = 224
- RGB Channels = 3
Step 4: Freeze the Base Model
base_model.trainable = FalseWhy?
The DenseNet201 model already learned useful image features.
We don’t want to destroy that knowledge.
So we freeze all its weights.
Only our new classifier will learn.
This is called Transfer Learning.
Step 5: Build Our Own Classifier
model = Sequential([
base_model,GlobalAveragePooling2D(), Dropout(0.3), Dense(128, activation="relu"), Dropout(0.3), Dense(1, activation="sigmoid")
])
Let’s understand each layer.
Base Model
base_modelExtracts powerful image features.
GlobalAveragePooling2D
Converts feature maps into one feature vector.
This replaces Flatten.
It also reduces the number of trainable parameters.
Dropout
Dropout(0.3)Randomly turns off 30% of neurons during training.
This helps reduce overfitting.
Dense Layer
Dense(128, activation="relu")Learns patterns specific to Cats vs Dogs.
Output Layer
Dense(1, activation="sigmoid")Since we have only two classes,
Sigmoid returns a probability between
0 → Cat1 → DogStep 6: Compile the Model
model.compile(optimizer="adam", loss="binary_crossentropy", metrics=["accuracy"])
Optimizer
Adam updates model weights during training.
Loss Function
Binary Crossentropy is used because we have only two classes.
Accuracy
Measures how many predictions are correct.
Step 7: Train the Model
history = model.fit(train_dataset, validation_data=validation_dataset, epochs=10)
What happens internally?
For every epoch,
TensorFlow:
- Reads one batch.
- Makes predictions.
- Calculates loss.
- Performs Backpropagation.
- Updates weights.
- Repeats until all batches are processed.
This process repeats for 10 epochs.
Step 8: Evaluate the Model
test_loss, test_accuracy = model.evaluate(test_dataset)This checks how well the model performs on unseen images.
If the accuracy is high, it means the model has generalized well.
Step 9: Save the Model
model.save("densenet201_cats_dogs.keras")This saves the trained model so you can use it later without retraining.
Step 10: Predict on a New Image
from tensorflow.keras.preprocessing import image
import numpy as np
img = image.load_img(
"cat.jpg",
target_size=(224,224)
)
img_array = image.img_to_array(img)
img_array = np.expand_dims(img_array, axis=0)
prediction = model.predict(img_array)
if prediction > 0.5:
print("Dog")
else:
print("Cat")The image goes through the same pipeline:
- Image is loaded.
- Image is resized to 224 × 224.
- Converted into a NumPy array.
- Batch dimension is added.
- DenseNet201 extracts features.
- The classifier predicts the probability.
- The final output is displayed as Cat or Dog.
Conclusion
DenseNet is one of the most successful improvements to the traditional Convolutional Neural Network.
It does not replace CNN — it enhances it.
The key innovation is simple yet powerful:
Every convolution layer receives the outputs of all previous convolution layers instead of only the immediately preceding one.
This dense connectivity allows the network to reuse features, preserve information from earlier layers, improve gradient flow, reduce unnecessary parameters, and achieve higher accuracy on image classification tasks.
Now that you understand what DenseNet is, why it was introduced, how it differs from a traditional CNN, and the overall workflow for building a DenseNet201 image classifier, you’re ready for the next step.
In the next article, we’ll start implementing DenseNet201 in TensorFlow by loading the dataset and understanding every line of code in detail — exactly as we did while learning CNN.









