Sitemap
Muhammadsufian

Muhammadsufian

DenseNet201 Explained from Scratch: Learn Dense Convolutional Networks the Easy Way (Complete Beginner Guide)

10 min readJul 20, 2026

--

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.

Press enter or click to view image in full size

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
↓
Conv4

This 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
↓
Conv4

DenseNet connects layers like this:

Press enter or click to view image in full size

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.

Press enter or click to view image in full size

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
Press enter or click to view image in full size

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
Press enter or click to view image in full size

Its responsibilities are:

  • Reduce the number of feature maps.
  • Reduce the spatial dimensions (height and width).
  • Lower memory usage.
  • Speed up training
Press enter or click to view image in full size

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.

Press enter or click to view image in full size

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.
Press enter or click to view image in full size

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 Sequential

What does each library do?

TensorFlow

TensorFlow is the deep learning framework that helps us build and train neural networks.

import tensorflow as tf

image_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.

DenseNet201

This 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 0
dogs → Label 1

image_size=(224,224)

DenseNet201 expects input images of size

224 × 224

TensorFlow 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 = False

Why?

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_model

Extracts 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 → Cat
1 → Dog

Step 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:

  1. Image is loaded.
  2. Image is resized to 224 × 224.
  3. Converted into a NumPy array.
  4. Batch dimension is added.
  5. DenseNet201 extracts features.
  6. The classifier predicts the probability.
  7. 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.

--

--