Paper Deep Dive — LoRA: Low-Rank Adaptation of Large Language Models: Why Low Rank Is Enough
A re-reading of the LoRA paper (Hu et al., 2021) grounded strictly in its own text: what BA actually means, the 21x amplification factor the authors measured, why r=1 sufficed, and the questions they left open.
LoRA: Low-Rank Adaptation of Large Language Models
Primary source — what this article is built on
undefined2021-06-17→undefined2026-08-035y 2mo later
LoRA: Low-Rank Adaptation of Large Language ModelsEdward J. Hu, Yelong Shen, Phillip Wallis et al. · 2021-06-17 · v2arXiv:2106.09685Paper page·PDFundefined
An important paradigm of natural language processing consists of large-scale pre-training on general domain data and adaptation to particular tasks or domains. As we pre-train larger models, full fine-tuning, which retrains all model parameters, becomes less feasible. Using GPT-3 175B as an example -- deploying independent instances of fine-tuned models, each with 175B parameters, is prohibitively expensive. We propose Low-Rank Adaptation, or LoRA, which freezes the pre-trained model weights and injects trainable rank decomposition matrices into each layer of the Transformer architecture, greatly reducing the number of trainable parameters for downstream tasks. Compared to GPT-3 175B fine-tuned with Adam, LoRA can reduce the number of trainable parameters by 10,000 times and the GPU memory requirement by 3 times. LoRA performs on-par or better than fine-tuning in model quality on RoBERTa, DeBERTa, GPT-2, and GPT-3, despite having fewer trainable parameters, a higher training throughput, and, unlike adapters, no additional inference latency. We also provide an empirical investigation into rank-deficiency in language model adaptation, which sheds light on the efficacy of LoRA. We release a package that facilitates the integration of LoRA with PyTorch models and provide our implementations and model checkpoints for RoBERTa, DeBERTa, and GPT-2 at https://github.com/microsoft/LoRA.
Can you keep a hundred copies of a 175B model?
You want one large pre-trained model adapted to many downstream tasks. The obvious route is full fine-tuning, and its central defect is that the new model has as many parameters as the original (§1). What was a mere inconvenience for GPT-2 or RoBERTa large becomes a critical deployment problem for GPT-3 at 175 billion parameters. That is where the paper starts.
Its numbers are concrete. Full fine-tuning GPT-3 175B consumes 1.2TB of VRAM during training. With and only the query and value projection matrices adapted, the checkpoint you have to store drops from 350GB to 35MB — roughly a 10,000x reduction (§4.2). Footnote 4 is refreshingly blunt about what this does and doesn't buy you: you still need the 350GB base model at deployment, but hosting 100 adapted models costs rather than .
As an analogy, full fine-tuning rewrites the whole dictionary; LoRA seals the original and writes only the diff on a separate sheet. But that analogy only explains the storage bill. Why the diff can be so thin is the paper's real subject.
The intuition: adaptation amplifies directions that are already there
The hypothesis runs like this. Prior work (Li et al. 2018a; Aghajanyan et al. 2020) showed that over-parametrized models actually reside on a low intrinsic dimension. From that, the authors hypothesize that the change in weights during adaptation, , also has a low "intrinsic rank" (§1).
Section 7.3 then measures it. For in the 48th layer of GPT-3, Table 7 compares Frobenius norms after projecting onto the subspace spanned by the singular vectors of . At , while — an amplification factor of roughly 21. Projecting onto 's own top directions instead gives 21.67 (with ), so is not simply repeating the dominant directions of . A random matrix projection gives 0.02, so it isn't uncorrelated either. (For singular vectors, projections and low-rank approximation themselves, see Singular Value Decomposition and Low-Rank Approximation.)
The paper's conclusion: "amplifies the important features for specific downstream tasks that were learned but not emphasized in the general pre-training model" (§7.3). Fine-tuning, on this reading, isn't building capability from nothing — it's pushing up a handful of equalizer sliders. Which is exactly why you don't need many sliders.
What was wrong with the existing options
Parameter-efficient adaptation predates LoRA. Section 3 sorts it into two families: adding adapter layers, and optimizing input-layer activations (prefix/prompt methods).
Adapters add inference latency. Adapter layers sit in sequence with the base model, so their compute is always on the critical path, and while you can prune layers, "there is no direct way to bypass the extra compute in adapter layers" (§3). Table 1 reports single forward passes on GPT-2 medium, averaged over 100 trials on an NVIDIA Quadro RTX8000. At batch 32 / sequence 512 the penalty is a modest +2.2% to +3.0%. At batch 1 / sequence 128, 19.8ms becomes 23.9ms (+20.7%) and 25.8ms (+30.3%). In online inference with small batches this is not negligible (§3, Appendix B). Sharding makes it worse, since the added depth needs more synchronous GPU operations like AllReduce and Broadcast.
Prefix methods are hard to optimize and eat your context. The paper observes that prefix tuning "is difficult to optimize and that its performance changes non-monotonically in trainable parameters," and adds the more fundamental objection: reserving part of the sequence length for adaptation necessarily reduces the sequence length available to the downstream task (§3).
LoRA's core claim — the update is low rank — is faster to feel than to read. Slide the rank and find where the error collapses.
The full mathematical floor — eigenvalues, SVD, dot products — is laid out in The linear algebra under LoRA and RAG.
The mechanism: freeze , train only
For a pre-trained weight matrix , the update is constrained to a low-rank decomposition (§4.1):
Spelled out in words: whatever fine-tuning would have written into the weight matrix, LoRA forces you to write as one tall thin matrix times one short wide one. squeezes the input down to numbers and opens it back out, so every change has to pass through a waist values wide — and is deliberately chosen far smaller than either side of .
and the forward pass is Equation (3):
The same line in words: the layer's output is what the frozen original would have produced, plus a correction computed from the very same input . The two paths sit side by side rather than one after the other — and that is precisely what later lets you fold back into and pay nothing for it at inference time.
Comments
Sign in to comment