Level 3 — ProductionPretraining & Fine-Tuning LLMs

Pretraining & Fine-Tuning LLMs

45 minutes60 marksprintable — key stays hidden on paper

Level: 3 (Production — from-scratch derivations, code-from-memory, explain-out-loud) Time limit: 45 minutes Total marks: 60


Question 1 — LoRA math & memory (12 marks)

A linear layer has weight W0Rd×kW_0 \in \mathbb{R}^{d \times k} with d=4096d = 4096, k=4096k = 4096. You apply LoRA with rank r=16r = 16, decomposing the update as ΔW=BA\Delta W = BA where BRd×rB \in \mathbb{R}^{d \times r}, ARr×kA \in \mathbb{R}^{r \times k}, and scaling α=32\alpha = 32.

(a) Write the modified forward pass h=f(x)h = f(x) and state which matrices are trainable. (2)

(b) Compute the number of trainable parameters introduced per layer, and express it as a percentage of the frozen W0W_0 parameters. (4)

(c) LoRA uses effective scaling αr\frac{\alpha}{r}. Give the numeric value here and explain why AA is initialised from a random Gaussian while BB is initialised to zero. (3)

(d) At inference, how can you eliminate the LoRA latency overhead entirely? Show the algebra. (3)


Question 2 — Self-supervised objectives from memory (10 marks)

(a) Write the training objective (loss) for GPT-style causal language modelling over a sequence x1,,xTx_1,\dots,x_T. (3)

(b) Write BERT's masked language modelling objective and state the classic masking recipe (the 80/10/10 rule). (4)

(c) In one or two sentences each, explain why a causal LM cannot use bidirectional context, and why T5's span-corruption objective is more sample-efficient than single-token masking. (3)


Question 3 — QLoRA memory budget derivation (12 marks)

You fine-tune a 7-billion-parameter model.

(a) Compute the memory (in GB) to store the frozen base weights in FP16 vs INT4. Use 1 GB=1091\text{ GB} = 10^9 bytes. (4)

(b) With full fine-tuning in FP16 using the Adam optimizer, estimate total training memory for weights + gradients + optimizer states (Adam keeps 2 moment buffers). Assume master weights and states in FP32. State your per-parameter byte accounting. (5)

(c) Explain in 2–3 sentences the two key innovations QLoRA adds beyond plain LoRA (name them and say what each does). (3)


Question 4 — Knowledge distillation loss (10 marks)

A teacher produces logits zTz^T, a student produces logits zSz^S, over CC classes, with temperature τ\tau.

(a) Write the softened probability pi(τ)p_i(\tau) and the combined distillation loss L\mathcal{L} mixing soft-target KL and hard-label cross-entropy with weight λ\lambda. (4)

(b) Derive LsoftziS\frac{\partial \mathcal{L}_{soft}}{\partial z^S_i} for the soft KL term Lsoft=τ2KL(pTpS)\mathcal{L}_{soft} = \tau^2 \, \mathrm{KL}(p^T \Vert p^S), and explain why the gradient is multiplied by τ2\tau^2. (4)

(c) State one reason high τ\tau transfers more "dark knowledge." (2)


Question 5 — Catastrophic forgetting & design (8 marks)

You fine-tune a general instruction-tuned LLM on a narrow medical QA dataset and observe its general reasoning degrades.

(a) Define catastrophic forgetting in the context of sequential fine-tuning. (2)

(b) List and one-line-justify three mitigation strategies, at least one of which must be a PEFT-based approach. (6)


Question 6 — Code from memory: minimal LoRA layer (8 marks)

Write, from memory, a PyTorch nn.Module called LoRALinear that wraps a frozen nn.Linear. It must: freeze the base weight, add trainable low-rank matrices A and B of rank r, apply scaling alpha/r, and implement forward. Initialise correctly. (8)


Answer keyMark scheme & solutions

Question 1 (12)

(a) h=W0x+αrBAxh = W_0 x + \frac{\alpha}{r} B A x. Trainable: AA and BB only; W0W_0 frozen. (2: forward 1, trainable 1)

(b) Params per LoRA pair =r(d+k)=16(4096+4096)=16×8192=131072= r(d+k) = 16(4096+4096) = 16 \times 8192 = 131072. Frozen params =d×k=40962=16,777,216= d\times k = 4096^2 = 16{,}777{,}216. Percentage =13107216777216×100=0.78125%= \frac{131072}{16777216}\times100 = 0.78125\%. (4: formula 1, LoRA count 1, frozen count 1, % 1)

(c) αr=3216=2\frac{\alpha}{r} = \frac{32}{16} = 2. BB is initialised to zero so that at the start ΔW=BA=0\Delta W = BA = 0, meaning the fine-tuned model exactly equals the pretrained model at step 0 (stable start, no shock to activations). AA is Gaussian so gradients can flow and break symmetry; if both were zero no learning signal would propagate. (3: value 1, B=0 reason 1, A random reason 1)

(d) Since ΔW=αrBA\Delta W = \frac{\alpha}{r}BA is just another d×kd\times k matrix, merge it: W=W0+αrBAW' = W_0 + \frac{\alpha}{r}BA. Then h=Wxh = W'x is a single matmul with no extra latency; the adapter is folded into the base weight. (3: merge idea 1, algebra 1, zero-overhead statement 1)


Question 2 (10)

(a) LCLM=t=1TlogPθ(xtx<t)\mathcal{L}_{CLM} = -\sum_{t=1}^{T} \log P_\theta(x_t \mid x_{<t}) (autoregressive negative log-likelihood; each token conditioned only on preceding tokens). (3)

(b) LMLM=iMlogPθ(xixM)\mathcal{L}_{MLM} = -\sum_{i \in M} \log P_\theta(x_i \mid x_{\setminus M}) where MM is the masked set. Recipe: choose ~15% of tokens; of those, 80% → [MASK], 10% → random token, 10% → unchanged. This reduces train/inference mismatch (no [MASK] at inference). (4: loss 2, recipe 2)

(c) Causal LM is trained with a triangular attention mask so position tt cannot attend to t+1Tt{+}1\dots T — needed to prevent label leakage during autoregression. T5 span corruption masks contiguous spans replaced by a single sentinel, so one forward pass predicts multiple tokens per example (more supervised signal per token/step) → higher sample efficiency. (3: causal 1.5, span 1.5)


Question 3 (12)

(a) FP16 = 2 bytes/param: 7×109×2=14×1097\times10^9 \times 2 = 14\times10^9 B =14= 14 GB. INT4 = 0.5 bytes/param: 7×109×0.5=3.5×1097\times10^9 \times 0.5 = 3.5\times10^9 B =3.5= 3.5 GB. (4: FP16 2, INT4 2)

(b) Per-parameter FP32 (4 bytes) accounting for full FT + Adam:

  • weights (master) FP32: 4 B
  • gradients FP32: 4 B
  • Adam mm: 4 B
  • Adam vv: 4 B Total = 16 B/param. 7×109×16=112×1097\times10^9 \times 16 = 112\times10^9 B =112= 112 GB. (Accept ~112 GB; if FP16 weights+grads + FP32 states counted as 2+2+4+4+4=16 with FP32 master copy, still ≈112 GB.) (5: byte accounting 3, arithmetic 2)

(c) (1) 4-bit NormalFloat (NF4) quantization of the frozen base weights — information-theoretically optimal for normally-distributed weights, cutting base memory ~4×. (2) Double quantization — quantizing the quantization constants themselves to save further memory; plus paged optimizers to handle memory spikes. LoRA adapters are trained in FP16/BF16 on top of the frozen NF4 base. (3: NF4 1.5, double-quant/paged 1.5)


Question 4 (10)

(a) pi(τ)=exp(zi/τ)jexp(zj/τ)p_i(\tau) = \dfrac{\exp(z_i/\tau)}{\sum_{j} \exp(z_j/\tau)}. L=λτ2KL ⁣(pT(τ)pS(τ))+(1λ)CE(y,pS(1))\mathcal{L} = \lambda \,\tau^2\, \mathrm{KL}\!\big(p^T(\tau)\,\Vert\,p^S(\tau)\big) + (1-\lambda)\,\mathrm{CE}(y, p^S(1)). (4: softmax 2, combined loss 2)

(b) For KL with soft targets the well-known result: LsoftziS=τ21τ(piS(τ)piT(τ))=τ(piSpiT).\frac{\partial \mathcal{L}_{soft}}{\partial z^S_i} = \tau^2 \cdot \frac{1}{\tau}\big(p^S_i(\tau) - p^T_i(\tau)\big) = \tau\,\big(p^S_i - p^T_i\big). Because differentiating softmax w.r.t. logits brings a 1/τ1/\tau factor, and the leading τ2\tau^2 cancels one power → net τ(piSpiT)\tau(p^S_i-p^T_i). The τ2\tau^2 multiplier is included so that gradient magnitudes stay comparable to the hard-label CE term (whose gradients scale as 11), keeping the two losses balanced as τ\tau changes. (4: derivative 2, τ² rationale 2)

(c) High τ\tau softens the distribution so relative probabilities of incorrect classes (the "dark knowledge" about class similarity) become non-negligible and are transferred to the student. (2)


Question 5 (8)

(a) Catastrophic forgetting: when a neural network trained sequentially on a new task overwrites weights important for previously learned tasks, causing sharp performance loss on the old task/distribution. (2)

(b) Any three (2 each = 6):

  • PEFT (LoRA/adapters) — freeze base weights, so original knowledge in W0W_0 is preserved; only small modules change.
  • Rehearsal / data mixing — mix general-instruction data into the medical fine-tuning set so gradients don't drift entirely.
  • Lower LR + fewer epochs / early stopping — smaller weight movement reduces overwriting.
  • Regularisation (EWC / L2-to-pretrained) — penalise moving weights important to old tasks.
  • Knowledge distillation from the original model — keep student close to teacher's general behaviour. (≥1 must be PEFT-based.) (6)

Question 6 (8)

import torch
import torch.nn as nn
import math
 
class LoRALinear(nn.Module):
    def __init__(self, base: nn.Linear, r=8, alpha=16):
        super().__init__()
        self.base = base
        for p in self.base.parameters():   # freeze base
            p.requires_grad = False
        in_f, out_f = base.in_features, base.out_features
        self.r = r
        self.scaling = alpha / r
        # A: (r, in), B: (out, r)
        self.A = nn.Parameter(torch.randn(r, in_f) / math.sqrt(in_f))
        self.B = nn.Parameter(torch.zeros(out_f, r))   # zero init
 
    def forward(self, x):
        base_out = self.base(x)
        lora_out = (x @ self.A.t()) @ self.B.t()
        return base_out + self.scaling * lora_out

Mark scheme: freeze base 2; A random init 1; B zero init 1; correct shapes 2; forward with scaling 2. (8)

[
  {"claim":"LoRA trainable params r(d+k)=131072","code":"r,d,k=16,4096,4096; result = (r*(d+k)==131072)"},
  {"claim":"LoRA percentage of frozen ~0.78125%","code":"r,d,k=16,4096,4096; result = (Rational(r*(d+k),d*k)*100 == Rational(78125,100000))"},
  {"claim":"7B FP16 = 14GB and INT4 = 3.5GB","code":"n=7*10**9; result = (n*2==14*10**9 and n*Rational(1,2)==Rational(35,10)*10**9)"},
  {"claim":"Full FT Adam FP32 memory 16 bytes/param = 112GB for 7B","code":"n=7*10**9; result = (n*16==112*10**9)"},
  {"claim":"LoRA effective scaling alpha/r=2","code":"result = (Rational(32,16)==2)"}
]