DL0088 PEFT: Parameter-Efficient Fine-Tuning

Compare Parameter-Efficient Fine-Tuning (PEFT) methods: LoRA, adapters, and prompt/prefix tuning. When would you choose each?

Answer

All three families freeze the pretrained weights and train a tiny set of new parameters, but they differ in where those parameters live, and that single structural choice decides inference cost, serving flexibility, and achievable quality. LoRA adds a low-rank update in parallel to existing weight matrices, so after training the update folds back into W and costs exactly zero extra latency. Serial adapters insert a small bottleneck MLP inside the block’s forward path, which keeps task modules cleanly composable but adds depth, so every decoded token pays for them. Prefix and prompt tuning touch no weight matrix at all: prefix tuning prepends trainable key/value vectors at every layer, prompt tuning prepends trainable vectors only at the input embeddings, which is the cheapest option in parameter count but the least stable and it consumes context length. In practice LoRA is the default (paired with 4-bit quantization as QLoRA when GPU memory is the binding constraint), adapters win when modular composition matters more than latency, and prefix/prompt tuning wins when the base weights must stay byte-identical or when you want per-request conditioning.

(1) Where The Parameters Live: LoRA sits parallel to chosen projections, adapters sit serially between sublayers, prefix tuning sits in the KV cache rather than in any weight tensor.
(2) Mergeability Decides Latency: only LoRA is exactly mergeable into W_0; adapters add two matmuls and a nonlinearity per sublayer that cannot be folded away, which is a 10-25% decode overhead at batch 1 on a 7B model.
(3) Capacity Is A Knob, Except For Prompts: rank r and bottleneck width b scale capacity smoothly, while prompt tuning’s capacity saturates and only becomes competitive with full fine-tuning above roughly 10B parameters.
(4) Multi-Tenant Serving: unmerged LoRA and prefix tuning both support heterogeneous batching (per-request low-rank gather, or per-request KV prefix) from one frozen base copy; merged LoRA needs a separate weight copy per task and adapters need a weight swap per request.

Diagram of one transformer block: input, LayerNorm, self-attention, LayerNorm, FFN, output. A blue LoRA box below attention taps the same input and adds its output back in parallel, a green prefix-tuning box above attention prepends trainable key and value vectors, and an orange serial adapter box sits in the path between the FFN and the block output

Figure 1: The three injection sites in one block. LoRA is parallel and therefore mergeable, the adapter is serial and therefore always in the critical path (real adapter recipes place one after attention and one after the FFN), and prefix tuning changes only K and V, leaving every weight untouched.

Two consequences are worth stating precisely because interviewers probe them. First, the merge is algebraically exact, not an approximation: W_0 + (\alpha/r)BA is just another matrix of the same shape, so a merged LoRA checkpoint is indistinguishable from a normally fine-tuned one at serving time, and the price is that you can no longer swap tasks without unmerging. Second, PEFT saves optimizer and gradient memory, not activation memory: with Adam you drop from roughly 12-16 bytes per trainable parameter of state to almost none, which is why a 7B model fine-tunes on a single 24GB card, but activations still scale with batch size and sequence length, and QLoRA’s 4-bit NF4 base plus paged optimizers is what pushes a 65B model onto one 48GB GPU. Prefix tuning has a third quirk: because the prefix occupies KV slots, a 20-token prefix at every layer permanently shortens the usable context and its quality is non-monotonic in prefix length, which is why the original work needed a reparameterization MLP to train stably at all.

Mathematical Formulation:
h = W_0 x + \frac{\alpha}{r} B A x
W' = W_0 + \frac{\alpha}{r} B A
h = x + W_{\mathrm{up}} \sigma(W_{\mathrm{down}} x)
\tilde{K} = \mathrm{concat}(P_k, K)
\tilde{V} = \mathrm{concat}(P_v, V)

Where:

  • h is the sublayer output and x the input; W_0 is the frozen pretrained matrix of shape d_{out} \times d_{in}.
  • B \in \mathbb{R}^{d_{out} \times r} and A \in \mathbb{R}^{r \times d_{in}} are the LoRA factors with rank r \ll \min(d_{in}, d_{out}); A is Gaussian-initialized and B is zero-initialized so training starts from the pretrained function.
  • \alpha is a scaling constant, and the ratio \alpha/r keeps the effective update magnitude roughly stable when you sweep r; W' is the merged weight used at inference.
  • W_{\mathrm{down}} \in \mathbb{R}^{b \times d} and W_{\mathrm{up}} \in \mathbb{R}^{d \times b} form the adapter bottleneck of width b, with nonlinearity \sigma; the residual term x plus near-zero initialization makes the adapter an approximate identity at step 0.
  • P_k, P_v \in \mathbb{R}^{p \times d_k} are the per-layer, per-head prefix key and value vectors of length p; K, V are the ordinary projected keys and values, so attention runs over p + n positions for a sequence of length n.
Two-panel bar chart. Left panel, log scale: trainable parameters for full fine-tuning 6738M, adapters 33.6M, LoRA 8.4M, prefix tuning 5.2M. Right panel: added per-token decode latency at batch 1, merged LoRA 0 percent, unmerged LoRA 6 percent, serial adapters 18 percent, prefix tuning 4 percent

Figure 2: Illustrative budgets for a 7B decoder with d = 4096 and 32 layers. Parameter counts span three orders of magnitude, yet the latency picture is unrelated to them: the smallest method is not the fastest, and merged LoRA is free.

DimensionLoRASerial AdaptersPrefix / Prompt Tuning
Insertion pointParallel to chosen linear layers (q,v by default; all attention and FFN projections for hard tasks)Serial bottleneck after the attention and FFN sublayersExtra K/V vectors at every layer (prompt tuning: input embeddings only)
Trainable share (7B)0.05-0.5% (8.4M at r=16 on q,v)0.5-3% (33.6M at b=64, two per layer)Under 0.1% (5.2M for a 20-token prefix)
MergeableYes, algebraically exactNo, extra depth is irreducibleNo, but no weight is modified either
Inference cost0% merged; roughly 5-10% unmerged at batch 1Roughly 10-25% at batch 1, worst at small batchSmall KV cost, but the prefix permanently shortens usable context
Many tasks, one baseStrong: keep unmerged and batch a per-request low-rank gatherWeak: needs a per-request module swap, though AdapterFusion composes trained modulesStrong: a prefix is just cached K/V, trivially per-request
Quality on hard tasksMatches full fine-tuning closely at adequate rank; underfits at very low r on large domain shiftsComparable to LoRA, with a well-studied bottleneck-width knobLags on generation and reasoning; unstable below roughly 10B parameters
Choose it whenDefault choice; memory-bound runs pair it with 4-bit QLoRA; hundreds of task variants over one baseYou want modular, composable, independently versioned task modules and have latency headroomBase weights must stay immutable, or you need cheap per-request conditioning at very large scale

Login to view more content


Log in to track your progress

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *