Architecture Hyperparameters › Feed-Forward Network Dimensions

Michael BrenndoerferUpdated June 18, 20257 min read
Language AI HandbookAll chapters
Part 16 of 67Transformer Architectures
Chapter 116Architecture Hyperparameters › Feed-Forward Network Dimensions
Reading section 5 of 10 · Feed-Forward Network Dimensions · 7 minSection 5 of 10 · 7 min

Book contents

Section 5 of 10 · 7 min read

Architecture Hyperparameters › Feed-Forward Network DimensionsOne section · Sections in this chapter5 / 10 ↓
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

While attention layers decide which tokens to combine, the feed-forward network (FFN) performs the actual transformation of each token's representation. This division of labor has a surprising consequence: the FFN contains far more parameters than attention, making it the dominant factor in model size.

Understanding why requires examining what each component does. Attention computes weighted averages of value vectors, a fundamentally linear operation (the only nonlinearity is softmax for computing weights). The FFN, by contrast, applies a nonlinear transformation that can reshape the representation space, activate or suppress features, and encode factual associations. Research has shown that specific FFN neurons activate for particular concepts: "Eiffel Tower," "Python programming," or "past tense verbs." The FFN is where the model stores much of its learned knowledge.

This knowledge-storage role explains why FFNs need large capacity. The original transformer paper established the convention dff=4×dmodeld_{\text{ff}} = 4 \times d_{\text{model}}. This provides the FFN with four times more hidden dimensions than the model's representation size. This 4x expansion gives each layer a wide intermediate space for computation before projecting back to dmodeld_{\text{model}} dimensions.

The Standard Expansion Ratio

Let's derive exactly how this expansion affects parameter counts and understand why FFNs dominate model size.

For a standard two-layer FFN, the computation applies an up-projection and activation before the down-projection:

FFN(x)=GELU(xW1+b1)W2+b2\text{FFN}(\mathbf{x}) = \text{GELU}(\mathbf{x} \mathbf{W}_1 + \mathbf{b}_1) \mathbf{W}_2 + \mathbf{b}_2

where:

  • x∈Rdmodel\mathbf{x} \in \mathbb{R}^{d_{\text{model}}}: the input vector (one token's representation)
  • W1∈Rdmodel×dff\mathbf{W}_1 \in \mathbb{R}^{d_{\text{model}} \times d_{\text{ff}}}: the up-projection weight matrix
  • W2∈Rdff×dmodel\mathbf{W}_2 \in \mathbb{R}^{d_{\text{ff}} \times d_{\text{model}}}: the down-projection weight matrix
  • b1∈Rdff\mathbf{b}_1 \in \mathbb{R}^{d_{\text{ff}}}, b2∈Rdmodel\mathbf{b}_2 \in \mathbb{R}^{d_{\text{model}}}: bias vectors
  • GELU(⋅)\text{GELU}(\cdot): the Gaussian Error Linear Unit activation function

The total parameter count includes both weight matrices and bias vectors:

FFN parameters=2×dmodel×dff+dff+dmodel\text{FFN parameters} = 2 \times d_{\text{model}} \times d_{\text{ff}} + d_{\text{ff}} + d_{\text{model}}

The first term accounts for the two weight matrices (each with dmodel×dffd_{\text{model}} \times d_{\text{ff}} parameters), while the remaining terms count the bias vectors. With the standard expansion ratio dff=4×dmodeld_{\text{ff}} = 4 \times d_{\text{model}} and ignoring the relatively small bias terms:

FFN parameters≈2×dmodel×4×dmodel=8×dmodel2\text{FFN parameters} \approx 2 \times d_{\text{model}} \times 4 \times d_{\text{model}} = 8 \times d_{\text{model}}^2

Compare this to attention parameters for standard multi-head attention (MHA), which has four projection matrices (QKV and output), each of size dmodel×dmodeld_{\text{model}} \times d_{\text{model}}:

Attention parameters=4×dmodel2\text{Attention parameters} = 4 \times d_{\text{model}}^2

The FFN has twice as many parameters as attention. This 2:1 ratio is consistent across most transformer architectures and explains why FFN optimization is so important for efficiency.

Out[16]:
Visualization
Horizontal bar chart comparing attention and FFN parameters per layer across different model configurations.
Per-layer parameter distribution between attention and FFN components. The FFN consistently dominates, containing roughly two-thirds of each layer's parameters regardless of model architecture.

The visualization confirms that regardless of architecture choice, FFN parameters dominate. Even with SwiGLU's reduced expansion ratio, the FFN still accounts for roughly twice the parameters of attention. This consistent 2:1 ratio has practical consequences for optimization techniques like mixture-of-experts, which specifically target FFN layers.

SwiGLU and Adjusted Ratios

The standard FFN applies a simple pattern: project up, apply nonlinearity, project down. But research has shown that adding a gating mechanism can improve performance significantly. The gating idea comes from LSTMs and GRUs: instead of passing all information through uniformly, learn which dimensions to emphasize and which to suppress.

SwiGLU (SiLU-Gated Linear Unit) implements this by computing two parallel projections of the input. One projection becomes the "content" that might pass through. The other projection, after applying the SiLU activation, becomes the "gate" that controls how much of each dimension passes. The element-wise product of content and gate creates a selective filtering effect.

This gating mechanism requires three weight matrices instead of two:

SwiGLU(x)=(SiLU(xWgate)⊙xWup)Wdown\text{SwiGLU}(\mathbf{x}) = (\text{SiLU}(\mathbf{x}\mathbf{W}_{\text{gate}}) \odot \mathbf{x}\mathbf{W}_{\text{up}}) \mathbf{W}_{\text{down}}

where:

  • x∈Rdmodel\mathbf{x} \in \mathbb{R}^{d_{\text{model}}}: the input vector
  • Wgate∈Rdmodel×dff\mathbf{W}_{\text{gate}} \in \mathbb{R}^{d_{\text{model}} \times d_{\text{ff}}}: the gate projection matrix
  • Wup∈Rdmodel×dff\mathbf{W}_{\text{up}} \in \mathbb{R}^{d_{\text{model}} \times d_{\text{ff}}}: the up-projection matrix
  • Wdown∈Rdff×dmodel\mathbf{W}_{\text{down}} \in \mathbb{R}^{d_{\text{ff}} \times d_{\text{model}}}: the down-projection matrix
  • SiLU(⋅)\text{SiLU}(\cdot): the Sigmoid Linear Unit activation (also called Swish)
  • ⊙\odot: element-wise multiplication

With three matrices each containing dmodel×dffd_{\text{model}} \times d_{\text{ff}} parameters, the total count is:

SwiGLU parameters=3×dmodel×dff\text{SwiGLU parameters} = 3 \times d_{\text{model}} \times d_{\text{ff}}

To maintain the same parameter count as a standard FFN with 4x expansion, we can solve for the required SwiGLU expansion ratio. Setting the SwiGLU parameter count equal to the standard FFN count:

3×dmodel×dffSwiGLU=2×dmodel×4×dmodel3 \times d_{\text{model}} \times d_{\text{ff}}^{\text{SwiGLU}} = 2 \times d_{\text{model}} \times 4 \times d_{\text{model}}

Dividing both sides by 3×dmodel3 \times d_{\text{model}} gives the required FFN dimension:

dffSwiGLU=83×dmodel≈2.67×dmodeld_{\text{ff}}^{\text{SwiGLU}} = \frac{8}{3} \times d_{\text{model}} \approx 2.67 \times d_{\text{model}}

In practice, dffd_{\text{ff}} is often rounded to a multiple of 256 for efficient GPU computation. LLaMA uses dff=2.6875×dmodeld_{\text{ff}} = 2.6875 \times d_{\text{model}} (specifically 11008 for dmodel=4096d_{\text{model}} = 4096), which is close to the theoretical value of 83×4096=10923\frac{8}{3} \times 4096 = 10923.

In[17]:
Code
def ffn_parameters(d_model, d_ff, ffn_type="standard"):
    """
    Calculate FFN parameters for different architectures.

    Args:
        d_model: Model dimension
        d_ff: Feed-forward hidden dimension
        ffn_type: "standard" (2 matrices) or "swiglu" (3 matrices)
    """
    if ffn_type == "standard":
        # W1: d_model -> d_ff, W2: d_ff -> d_model
        return 2 * d_model * d_ff
    else:  # SwiGLU
        # gate, up, down: each d_model <-> d_ff
        return 3 * d_model * d_ff


# Compare FFN configurations
d_model = 4096

configs = {
    "Standard (4x)": {"d_ff": 4 * d_model, "type": "standard"},
    "SwiGLU (2.67x)": {"d_ff": int(8 / 3 * d_model), "type": "swiglu"},
    "SwiGLU (LLaMA)": {"d_ff": 11008, "type": "swiglu"},  # Actual LLaMA config
}

ffn_params = {
    name: ffn_parameters(d_model, cfg["d_ff"], cfg["type"])
    for name, cfg in configs.items()
}
Out[18]:
Console
FFN parameter comparison (d_model = 4096):

Configuration            d_ff    Ratio   Parameters
-------------------------------------------------------
Standard (4x)           16384     4.00x      134.22M
SwiGLU (2.67x)          10922     2.67x      134.21M
SwiGLU (LLaMA)          11008     2.69x      135.27M

The three configurations have nearly identical parameter counts. This shows that SwiGLU's third matrix is compensated by the smaller expansion ratio. This equivalence is intentional: it allows fair comparisons between architectures and predictable parameter budgets.