LoRA (Low-Rank Adaptation) and DoRA (Weight-Decomposed Low-Rank Adaptation) are two parameter-efficient fine-tuning methods for large neural networks. LoRA freezes the original weights and injects trainable low-rank matrices, while DoRA decomposes weights into magnitude and direction, applying LoRA only to the direction component. This article explains the mathematics behind both, compares their memory footprints, and outlines the practical trade-offs so you can choose the right one for your project.
Formula
LoRA’s core idea is to constrain the weight update ΔW to a low-rank decomposition. For a linear layer with weight matrix Wâ‚€ of shape (d_out, d_in), the modified forward pass is:
W = W₀ + ΔW = W₀ + (B × A) / r
where A is (r, d_in) and B is (d_out, r), with r ≪ min(d_in, d_out). The rank r is a hyperparameter. In practice, most implementations use a scaling factor α/r, but the parameter count is independent of α.
DoRA starts by decomposing the pretrained weight into magnitude and direction:
W₀ = m · (V / ‖V‖_c)
where m is a per-column magnitude vector (d_out, 1) and V is the direction matrix (d_out, d_in). During fine-tuning, DoRA keeps the magnitude vector m trainable and applies LoRA to the direction V:
W’ = (m + Δm) · (V + BA) / ‖V + BA‖_c
The extra parameters compared to LoRA are exactly the magnitude vector m per layer: d_out parameters. For a square layer (d_out = d_in = d), that’s d extra parameters per layer.
Worked Example
Using the default values from the calculator: rank r = 8, hidden dim d = 4096, layers n = 48.
LoRA trainable parameters per layer = 2 × d × r = 2 × 4096 × 8 = 65,536. Total = 65,536 × 48 = 3,145,728 ≈ 3.15M.
DoRA adds one magnitude vector per layer: d = 4096 parameters per layer, total extra = 4096 × 48 = 196,608 ≈ 0.2M.
Memory in MB (fp32, 4 bytes per param): LoRA = 3,145,728 × 4 / 1e6 ≈ 12.58 MB. DoRA = (3,145,728 + 196,608) × 4 / 1e6 ≈ 13.37 MB. The difference is about 0.79 MB — negligible for most models.
Background: Why Parameter-Efficient Fine-Tuning?
Full fine-tuning of large language models (LLMs) like Llama 2 70B or Mistral 7B requires storing the entire model’s gradients and optimizer states. For a 70B model, that’s roughly 280 GB of GPU memory just for optimizer states (Adam uses 8 bytes per parameter). Most researchers and small teams don’t have that hardware. Parameter-efficient fine-tuning (PEFT) methods train only a tiny fraction of the parameters, dramatically reducing memory and storage requirements. LoRA, introduced in 2021, became the de facto standard. DoRA, published in early 2024, builds on LoRA to improve accuracy, particularly at low ranks.
How LoRA Works Mathematically
LoRA is based on the observation that fine-tuning updates have a low intrinsic rank. Instead of updating the full weight matrix W₀, LoRA freezes W₀ and learns two small matrices A and B. The product BA is a low-rank matrix that approximates the full update ΔW. The rank r controls the expressiveness: a higher r allows more complex updates but uses more memory. A typical r is 8, 16, or 32.
Key properties:
- Wâ‚€ is frozen, so no gradients are computed for it.
- Only A and B are trainable, so the optimizer state is tiny.
- At inference, you can merge BA into Wâ‚€, so there’s no speed penalty.
The initialization matters: A is usually initialized with random Gaussian values, and B with zeros, so ΔW = 0 at the start.
How DoRA Improves on LoRA
DoRA’s insight is that weight updates can be separated into magnitude (scale) and direction (orientation). The authors observed that LoRA tends to change both simultaneously, which can be less effective. DoRA explicitly models them separately:
- Magnitude vector m: trainable, one parameter per output neuron.
- Direction matrix V: frozen, with LoRA applied to it.
This decomposition allows DoRA to match or exceed LoRA’s accuracy, especially with low ranks (r = 4 or 8). The paper reports that DoRA outperforms LoRA on commonsense reasoning and math benchmarks, and is more stable during training.
The cost: the direction must be re-normalized at every forward pass, which adds a small computational overhead. The extra memory is just the magnitude vector — d_out parameters per layer, which is negligible compared to the LoRA matrices themselves.
Memory and Computational Trade-offs
Let’s compare the actual numbers for a typical LLM layer (d = 4096, r = 8):
- LoRA trainable params per layer: 2 × 4096 × 8 = 65,536 (0.26 MB in fp32).
- DoRA extra params per layer: 4096 (0.016 MB).
- Total for 48 layers: LoRA ≈ 3.15M params; DoRA ≈ 3.34M params — about 6% more.
In terms of VRAM, the difference is usually under 1 MB. The real trade-off is computational: DoRA requires computing the column-wise norm ‖V + BA‖_c at every forward pass. This adds a small latency, typically 5-15% depending on the layer size and implementation. For inference, DoRA cannot be fully merged back into W₀ because the magnitude and direction are separate; you must keep the decomposition. This complicates deployment and may slow inference slightly.
How to Choose Between LoRA and DoRA
There is no universal winner; the choice depends on your constraints:
- Accuracy at low rank: If you want to use r = 4 or 8 to save memory, DoRA tends to perform better than LoRA at the same rank.
- Training speed: LoRA is faster per step because it has no normalization overhead. If your dataset is large and you have limited compute, LoRA may be preferable.
- Deployment simplicity: LoRA can be merged into the base weights, so you serve one model. DoRA requires keeping both the magnitude vector and the LoRA matrices, which complicates serving.
- Existing ecosystem: LoRA is supported everywhere (Hugging Face PEFT, QLoRA, etc.). DoRA is newer and may require custom code.
Practical advice: if you’re fine-tuning a model for a specialized task and you have enough memory for r = 16 or 32, LoRA is often sufficient. If you need to push accuracy with minimal memory, try DoRA.
Common Problems and Misconceptions
Misconception: DoRA doubles the memory. No, the extra magnitude vector is tiny (d_out per layer). The total parameter increase is typically less than 10%.
Problem: DoRA training is slower. Yes, the normalization adds overhead. On a single GPU, you might see 10-20% slower training steps compared to LoRA.
Misconception: Higher rank always better. Not necessarily. Higher rank increases capacity but also overfitting risk. DoRA’s advantage is that it can match higher-rank LoRA performance with lower rank.
Problem: Merging DoRA weights. You can’t simply add BA to Wâ‚€ because the direction is normalized. You must store m and V separately, or bake the normalization into the inference graph.
Frequently Asked Questions
Is DoRA always better than LoRA? No. DoRA usually matches or beats LoRA on accuracy, but it’s slower to train and harder to deploy. For many tasks, LoRA is perfectly adequate.
Can I use DoRA with QLoRA (quantized base model)? Yes, DoRA works with quantized base models. The decomposition applies to the frozen weights, which can be in 4-bit or 8-bit format.
What rank should I use? Start with r = 8 for LoRA. For DoRA, you can often use r = 4 and get similar results. If the task is complex, try r = 16.
Does DoRA work for computer vision models? Yes, the method is architecture-agnostic. It has been tested on vision transformers and convolutional networks, with similar improvements.
How much VRAM do I save compared to full fine-tuning? Huge. Full fine-tuning of a 7B model needs ~112 GB for optimizer states alone. LoRA/DoRA typically need less than 16 GB for a 7B model, depending on batch size and sequence length.
Can I merge DoRA into the base weights for inference? Not directly, because the normalization is nonlinear. You can either keep the decomposition or write a custom kernel that applies the magnitude and normalized direction at inference time.
Related
Formula used
in r | LoRA rank r | - | 8 | 1 | 64 in d | Model hidden dim d | - | 4096 | 16 | 100000 in n | Number of adapted layers | - | 48 | 1 | 1000 out lora_params | LoRA trainable params | - | 2 * d * r * n | 0 out dora_extra | DoRA extra params (per layer) | - | d | 0 out lora_mem | LoRA memory (MB, fp32) | - | lora_params * 4 / 1e6 | 2 out dora_mem | DoRA memory (MB, fp32) | - | (lora_params + dora_extra * n) * 4 / 1e6 | 2
Each line is one input (in, sel, list) or one result (out: label, unit, formula, decimals). How the calculators work
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.
More cards in this drawer
- Blockchain vs Database: When Does Distributed Trust Win?
- GTA 6 and Call of Duty on Same Console?
- MCP in Production: Security Failures Behind the Backdoor Label
- Nothing Phone 2 Waterproof? IP54 Rating Explained
- Satellite Internet Equipment & Installation Guide
- Infinix GT 20 Pro vs AI Nova 2 Ultra 5G: Which Fits?