Transformer Architecture
Time limit: 90 minutes Total marks: 60 Instructions: Answer all three questions. Show full derivations. Code may be written in Python/NumPy pseudocode but must be dimensionally correct.
Question 1 — Scaled Dot-Product Attention: Scaling, Gradients, Complexity (22 marks)
Consider single-head scaled dot-product attention over a sequence of length with model dimension :
where , .
(a) Assume each component of the query and key vectors is drawn i.i.d. with mean and variance , and queries and keys are independent. Compute the mean and variance of a raw dot-product score . Hence justify why the factor (rather than ) is the correct normalisation. (6)
(b) Let where . Derive the Jacobian in closed form. Then explain, using the magnitude of this Jacobian, the vanishing-gradient failure mode that the scaling factor mitigates when is large. (8)
(c) Give the time and memory complexity of computing the full attention matrix for one head, as functions of , , . State separately the cost of the product, the softmax, and the multiplication by . (4)
(d) FlashAttention achieves the same output with memory (excluding inputs/outputs) instead of . State the single algorithmic idea that makes this possible and name the numerical technique used to keep the streaming softmax stable. (4)
Question 2 — Multi-Head Attention & Positional Encoding (20 marks)
(a) A multi-head attention layer has heads, model dimension , and per-head dimension . Count the total number of parameters (weights only, no biases) in the four projection matrices . Show that this count is independent of and equals . (6)
(b) The sinusoidal positional encoding is Prove that for any fixed offset , is a linear function of — i.e. there exists a matrix (independent of ) such that for each frequency pair. Give the explicit rotation block. (8)
(c) Rotary Positional Embeddings (RoPE) apply a position-dependent rotation directly to and . Show that the attention score between rotated query at position and rotated key at position depends only on the relative position . Use a single 2-D frequency block with rotation matrix and the property . (6)
Question 3 — Building & Reasoning About a Decoder Block (18 marks)
(a) Write NumPy-style pseudocode for a causal (masked) self-attention forward pass on input for a single head. Explicitly construct the causal mask and show where is inserted before the softmax. Explain why the mask must be applied before softmax rather than after. (8)
(b) Contrast Post-LN ( is not used; instead ) with Pre-LN (). Explain, in terms of the residual stream and gradient flow, why Pre-LN trains more stably at large depth without learning-rate warmup. (6)
(c) In a standard encoder-decoder Transformer, identify the three distinct attention operations and, for each, state which sequence supplies the queries and which supplies the keys/values. (4)
Answer keyMark scheme & solutions
Question 1
(a) [6 marks] Each term : since independent, mean . (1) Variance of one term: . (2) Sum of independent terms: , . (2) To restore unit variance divide by standard deviation , not (which would over-shrink to variance ). Hence scaling keeps logits . (1)
(b) [8 marks] Softmax: . For : . (2) For : . (2) Compactly: . (1) Failure mode: without scaling, grows, so softmax inputs become large in magnitude → softmax saturates → one , others . Then and , so the whole Jacobian : vanishing gradients, no learning signal through attention weights. (2) Scaling by keeps logits , keeping the softmax in its non-saturated regime and the Jacobian well away from zero. (1)
(c) [4 marks]
- : times → time, memory. (1.5)
- Softmax over matrix: time and memory. (1)
- : times → time, output . (1.5) Overall time, memory (dominant).
(d) [4 marks] Idea: tiling / blockwise computation — never materialise the full score matrix; process in blocks and accumulate the output using an online (streaming) softmax so only statistics (running max and running sum/output) are kept in fast SRAM. (2) Numerical technique: the online softmax with running max subtraction (log-sum-exp / max-rescaling), rescaling accumulated partial outputs as new blocks arrive to avoid overflow. (2)
Question 2
(a) [6 marks] Each of maps , so each is = params. (3) maps concatenated back to : . (1) Total , independent of because cancels the dependence. (2)
(b) [8 marks] Let . The pair is . (2) Using angle addition: . (3) Hence independent of — a rotation by angle . (3)
(c) [6 marks] Rotate query at position : ; key at : . (2) Score . (2) Using : , depending only on . (2)
Question 3
(a) [8 marks]
def causal_self_attention(X, Wq, Wk, Wv, dk):
Q = X @ Wq # (n, dk)
K = X @ Wk
V = X @ Wv
scores = (Q @ K.T) / np.sqrt(dk) # (n, n)
n = X.shape[0]
mask = np.triu(np.ones((n, n)), k=1).astype(bool) # True above diagonal
scores[mask] = -np.inf # future positions masked
A = softmax(scores, axis=-1) # row-wise
return A @ VMarks: Q/K/V projection (2), scaled scores (1), correct upper-triangular mask (2), before softmax (1). (6) Why before softmax: softmax normalises over all positions; inserting makes so masked positions get exactly zero weight and the remaining weights renormalise to sum to 1. Masking after softmax (zeroing) would leave the denominator including future tokens, so probabilities would not sum to 1 and would leak information about future magnitudes. (2)
(b) [6 marks] Post-LN: — the residual is inside the normalisation, so gradients must pass through every LN, and the identity path is not clean; at large depth this causes gradient magnitudes to explode/vanish, requiring warmup. (3) Pre-LN: — the residual stream is an unnormalised identity highway; gradients flow additively/unimpeded from top to bottom (each layer contributes an term), keeping gradient norms bounded and stable, so training proceeds without warmup. (3)
(c) [4 marks]
- Encoder self-attention: Q, K, V all from the encoder input sequence. (1)
- Decoder masked self-attention: Q, K, V all from the (partial) decoder sequence, causally masked. (1.5)
- Encoder-decoder cross-attention: Q from the decoder, K and V from the encoder output. (1.5)
[
{"claim":"Raw dot-product of two iid unit-variance d_k-dim vectors has variance d_k",
"code":"dk=symbols('d_k',positive=True); var=dk*1; result = (var==dk)"},
{"claim":"Softmax Jacobian diagonal is a_i(1-a_i)",
"code":"z1,z2=symbols('z1 z2'); a1=exp(z1)/(exp(z1)+exp(z2)); J=diff(a1,z1); expr=a1*(1-a1); result = simplify(J-expr)==0"},
{"claim":"MHA total projection params = 4*d_model^2 independent of h",
"code":"dm,h=symbols('d_model h',positive=True); dk=dm/h; per=dm*(h*dk); total=3*per+ (h*dk)*dm; result = simplify(total-4*dm**2)==0"},
{"claim":"Rotation composition R(a)^T R(b) = R(b-a) gives relative dependence",
"code":"a,b=symbols('a b'); R=lambda t: Matrix([[cos(t),-sin(t)],[sin(t),cos(t)]]); lhs=simplify(R(a).T*R(b)); rhs=R(b-a); result = simplify(lhs-rhs)==zeros(2,2)"}
]