v9.1.1
Menu

Transformer Block Forward Pass

hardFREETransformer ComponentsLLM 1: Foundations

Implement a single transformer block forward pass.

A transformer block consists of:

  1. Multi-head self-attention with residual connection and layer norm: x = LayerNorm(x + Attention(x))
  2. Feed-forward network with residual connection and layer norm: x = LayerNorm(x + FFN(x))

For simplicity:

  • Single-head attention (h=1), no projection weights: Q=K=V=xQ = K = V = x, and Attention(x)=softmax(xxT/d) x\text{Attention}(x) = \text{softmax}(x x^T / \sqrt{d})\, x with the softmax taken over each row
  • FFN: ReLU(x @ W1) @ W2, where W1W_1 is d×dffd \times d_{ff} and W2W_2 is dff×dd_{ff} \times d. Call np.random.seed(42), then draw W1W_1 first and W2W_2 second from a standard normal distribution, each multiplied by 0.1
  • LayerNorm: (x - mean) / sqrt(var + 1e-5) over each row, no affine params
  • d_ff = 4 * d

Input: X, a NumPy array of shape (n, d) (sequence length n, model dimension d).

Output: The output matrix after one transformer block, shape (n, d). The tests print each value rounded to 4 decimal places.

Example

Input
2 2
1 0
0 1
Output
[1.0000 -1.0000]
[-1.0000 1.0000]
Reasoning
  • Input. XX holds two tokens with d=2d = 2 features: [1,0][1, 0] and [0,1][0, 1].
  • Attention. With Q=K=V=XQ = K = V = X, the scores are XXT/2=I/2XX^T/\sqrt{2} = I/\sqrt{2}: each token scores 0.70710.7071 on itself and 00 on the other. Row-wise softmax gives weights [0.6698, 0.3302][0.6698,\ 0.3302] and [0.3302, 0.6698][0.3302,\ 0.6698]; since X=IX = I, these weights are also the attention output.
  • Residual + LayerNorm 1. X+AttnX + \text{Attn} has rows [1.6698, 0.3302][1.6698,\ 0.3302] and [0.3302, 1.6698][0.3302,\ 1.6698]. Each has mean 11 and variance 0.44860.4486, so normalising gives H≈H \approx rows [1,−1][1, -1] and [−1,1][-1, 1].
  • FFN. With W1W_1 (2×82 \times 8) and W2W_2 (8×28 \times 2) scaled by 0.10.1, ReLU(HW1)W2\text{ReLU}(HW_1)W_2 is tiny: rows [−0.0393, −0.0065][-0.0393,\ -0.0065] and [−0.0088, −0.0091][-0.0088,\ -0.0091].
  • Residual + LayerNorm 2. The sums [0.9607, −1.0065][0.9607,\ -1.0065] and [−1.0088, 0.9909][-1.0088,\ 0.9909] normalise to ±0.99999\pm 0.99999, which rounds to [1.0000 -1.0000] and [-1.0000 1.0000].
  • Notice that with d=2d = 2, LayerNorm sends any row with two different entries to ±1\pm 1 (minus a sliver from ϵ\epsilon), so the output just records which feature is larger.

Constraints

  • 1 <= n <= 5, 2 <= d <= 8
  • Single head attention (no projections)
  • d_ff = 4 * d
  • Layer norm with ε=1e-5, no affine
  • np.random.seed(42) before generating FFN weights
  • Round to 4 decimal places

Learn this in

More from LLM 1: Foundations

solution.py

Test results

Sign in to run your code against the test cases.