Multilayer Perceptrons › Architecture Design Guidelines

Michael BrenndoerferApril 29, 20254 min read
Language AI HandbookAll chapters
Part 10 of 67Neural Network Foundations
Chapter 63Multilayer Perceptrons › Architecture Design Guidelines
Reading section 9 of 13 · Architecture Design Guidelines · 4 minSection 9 of 13 · 4 min

Book contents

Section 9 of 13 · 4 min read

Multilayer Perceptrons › Architecture Design GuidelinesOne section · Sections in this chapter9 / 13 ↓
Reading tools Definitions & inline links

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

Designing an MLP architecture involves choosing the number of layers, neurons per layer, activation functions, and regularization techniques. While there is no universal formula, several principles guide these decisions.

Depth vs. Width

Deeper networks can represent more complex hierarchical features. However, they are harder to train due to vanishing or exploding gradients. Wider networks have more parameters per layer but may struggle to learn compositional patterns.

As a starting point:

  • For simple problems, 1-2 hidden layers often suffice
  • For complex patterns, 3-5 hidden layers may be needed
  • Very deep networks (10+ layers) typically require residual connections to avoid gradient issues

Layer Sizes

Common patterns for hidden layer sizes include:

  • Funnel: Decreasing sizes (e.g., 256-128-64) that progressively compress information
  • Constant: Same size throughout (e.g., 128-128-128) for uniform capacity
  • Bottleneck: Narrow middle layer (e.g., 256-32-256) to force compressed representations
Out[34]:
Visualization
Vertical diagram of funnel architecture with decreasing layer widths.
Funnel architecture: progressively compresses from 256 to 64 neurons. Each layer has fewer neurons than the previous, forcing the network to distill information.
Vertical diagram of constant architecture with uniform layer widths.
Constant architecture: uniform capacity of 128 neurons per hidden layer. Useful when you are unsure how much compression to apply.
Vertical diagram of bottleneck architecture with a narrow middle layer.
Bottleneck architecture: forces a compressed 32-neuron representation in the middle, useful for learning compact feature embeddings.

The input and output sizes are determined by your problem. Hidden sizes are hyperparameters to tune based on validation performance.

Activation Functions

ReLU is the default choice for hidden layers due to its simplicity and effectiveness. Alternatives help in specific situations:

  • ReLU: Fast, simple, works well in most cases
  • Leaky ReLU/PReLU: Addresses the dying ReLU problem where neurons output constant zero
  • GELU: Smooth approximation, popular in transformers
  • Tanh/Sigmoid: Rarely used in hidden layers now due to saturation

For output layers:

  • Sigmoid: Binary classification (outputs probability in range (0, 1))
  • Softmax: Multiclass classification (outputs probability distribution)
  • Identity (none): Regression (outputs unbounded values)

Regularization

To prevent overfitting, we use regularization techniques:

  • Dropout: Randomly zeros neurons during training (typical rates: 0.2-0.5)
  • Weight decay: L2 penalty on weights (typical values: 1e-4 to 1e-2)
  • Batch normalization: Normalizes layer inputs, also acts as a regularizer
In[35]:
Code
class WellDesignedMLP(nn.Module):
    """An MLP following best practices for architecture design."""

    def __init__(
        self,
        input_size,
        num_classes,
        hidden_sizes=[256, 128, 64],
        dropout_rate=0.3,
        use_batch_norm=True,
    ):
        super().__init__()

        layers = []
        prev_size = input_size

        for hidden_size in hidden_sizes:
            layers.append(nn.Linear(prev_size, hidden_size))
            if use_batch_norm:
                layers.append(nn.BatchNorm1d(hidden_size))
            layers.append(nn.ReLU())
            layers.append(nn.Dropout(dropout_rate))
            prev_size = hidden_size

        layers.append(nn.Linear(prev_size, num_classes))
        self.network = nn.Sequential(*layers)

    def forward(self, x):
        return self.network(x)
Out[36]:
Console
Well-designed MLP architecture:
WellDesignedMLP(
  (network): Sequential(
    (0): Linear(in_features=100, out_features=256, bias=True)
    (1): BatchNorm1d(256, eps=1e-05, momentum=0.1, affine=True, bias=True, track_running_stats=True)
    (2): ReLU()
    (3): Dropout(p=0.3, inplace=False)
    (4): Linear(in_features=256, out_features=128, bias=True)
    (5): BatchNorm1d(128, eps=1e-05, momentum=0.1, affine=True, bias=True, track_running_stats=True)
    (6): ReLU()
    (7): Dropout(p=0.3, inplace=False)
    (8): Linear(in_features=128, out_features=64, bias=True)
    (9): BatchNorm1d(64, eps=1e-05, momentum=0.1, affine=True, bias=True, track_running_stats=True)
    (10): ReLU()
    (11): Dropout(p=0.3, inplace=False)
    (12): Linear(in_features=64, out_features=10, bias=True)
  )
)

Parameter count:
  Total parameters:     68,554
  Trainable parameters: 68,554

This architecture applies the Linear, BatchNorm, ReLU, Dropout pattern for each hidden layer. The funnel shape (256, 128, 64) progressively compresses the representation, forcing the network to distill the most important features as information flows toward the output.