LoRA and the Low-Rank Update Hypothesis
A small update is a structural hypothesis to test, not a free guarantee of full fine-tuning quality.
- Authorship
- InterviewsVector
- Published / updated
- 2026-09-19 / 2026-09-19
- Review status
- Artifact tests passing · primary sources recorded
Original InterviewsVector teaching. Executable illustrative contracts are covered by focused tests and primary sources are recorded. No named human review or empirical model improvement is claimed.
The decision in one pass
LoRA freezes a base weight matrix and learns a factored update ΔW = (α/r)BA with rank at most r. For a target matrix with input width d_in and output width d_out, the adapter has r(d_in + d_out) trainable parameters instead of d_in·d_out. Sum this over actual named target matrices and active adapters; then budget weights, gradients, master copies, and optimizer states under explicit dtypes. Frozen base weights still occupy memory, and activations and runtime workspaces remain. Parameter savings do not establish runtime peak memory, speed, or task quality. Bind held-out evidence to the exact rank, targets, base, data, and policy; block the low-rank configuration when that evidence is insufficient.
Why this matters
A rank knob is easy to turn, but an adapter's target coverage, dtype, optimizer, residency, and evaluation identity decide what it costs and what it can change. Teams otherwise ship attractive spreadsheets that omit base weights and activations, or reuse an evaluation from a different adapter configuration.
You will be able to
- Derive LoRA parameter counts from the shapes of A and B and distinguish update rank from base-model rank.
- Calculate a deterministic global memory lower bound under explicit precision, optimizer, and adapter-residency assumptions.
- Validate target identities, unique adapter IDs, dimension bounds, sharding divisibility, and evaluation configuration bindings.
- Explain why quantization, activations, runtime buffers, and distributed placement require separate accounting.
- Use held-out behavior evidence to decide whether low rank is sufficient and what experiment should follow a failure.
Prerequisite contract
Your Vector Loop for this lab
- 01
Model
Name the frozen base, target matrices, adapter identities, ranks, dtypes, optimizer, sharding assumptions, and quality requirement.
- 02
Derive
Derive r(d_in+d_out) and separate frozen weights from trainable state and unmodeled runtime memory.
- 03
Build
Compute an integer lower-bound budget bound to a concrete target manifest and evaluation configuration.
- 04
Stress
Change target identity, introduce duplicate adapters, violate divisibility, poison numeric inputs, and miss the quality gate.
- 05
Operate
Measure runtime peaks separately, track adapter/base compatibility, and reevaluate every rank or target change.
- 06
Defend
Explain the low-rank hypothesis, the evidence boundary, and why a feasible budget is not permission to ship.
Factor the update, not the frozen base
W′ = W + (α/r)BA; A ∈ ℝ^(r×d_in), B ∈ ℝ^(d_out×r)
The base W remains frozen. The learned update has rank at most r; this does not claim that W, the hidden states, or the complete task are low rank. Scaling α/r changes update magnitude, not parameter count.
The factorization constrains which matrix changes training can express. Multiplying the two factors gives a full-shaped update, but its columns and rows are coupled through r latent directions. This can be effective when the necessary adaptation lies in a small subspace. It is not a theorem that every domain shift, behavior change, or modality transition fits that subspace. The useful hypothesis is narrower: this base, these targets, this rank, and this objective may be sufficient for the measured task.
A common initialization makes one factor random and the other zero so the initial update vanishes, preserving the base function at the start. Training changes the factors, not the frozen base. At deployment a compatible unquantized update may be merged into a base copy, or the factors may remain separate for adapter switching. Merging, quantization, and routing change operational behavior and require their own parity tests; this budget does not perform them.
Count actual target matrices, not architectural nicknames
P_adapter = Σ_targets r_i(d_in,i + d_out,i); P_all = N_trainable_adapters × P_adapter
The teaching contract gives every named adapter the same target manifest and assumes all are resident and trained simultaneously. Heterogeneous adapters or only one active training adapter require a different explicit manifest.
For an illustrative 128×128 matrix and rank 8, A has 1,024 parameters and B has 1,024: 2,048 trainable parameters rather than 16,384 full-matrix entries. Applying this to two named projections gives 4,096 parameters. Biases, embeddings, output heads, or other fully trainable modules must be counted separately if enabled; the fixture excludes them. A phrase such as 'attention targets' is not precise enough because architectures differ in projection shapes and sharing.
Resolve target paths against the actual base checkpoint. Enforce unique IDs, exact dimensions, ordered manifests, and rank bounds. A stale path that selects no module can appear wonderfully cheap while adapting nothing. A duplicated target can double-count state or misconfigure training. The contract checks named target identity and total target entries against the declared base size; an integration must additionally verify those identities against a real model manifest.
Keep a memory ledger with explicit exclusions
| Term | Illustrative accounting | Important boundary |
|---|---|---|
| Frozen base weights | P_base × bytes(base dtype) | Frozen does not mean absent from memory |
| Adapter weights and gradients | P_all × 2 × bytes(adapter dtype) | Assumes gradient dtype equals adapter dtype |
| AdamW moments | P_all × 8 bytes | Two FP32 states under this declared optimizer policy |
| Master weights | P_all × 4 bytes for half-precision AdamW | Policy-specific; do not add blindly to another optimizer |
| Activations and runtime | Excluded from the lower bound | Measure sequence, batch, kernels, checkpointing, buffers, and allocator |
Integer byte accounting avoids rounding a small adapter into an apparently zero cost. The artifact returns a global lower bound, not a per-device budget: sharding divisibility is checked, but placement, replication, optimizer partitioning, and communication buffers are not modeled. Dividing the final number by the GPU count would invent an unsupported distribution policy. Peak memory must be measured in the actual runtime with the intended sequence lengths, batch sizes, optimizer, and checkpointing configuration.
Predict the cost and the quality gate separately
Increasing rank increases the count linearly for fixed target shapes, but quality need not increase monotonically. Adding a target changes which transformations can adapt, not merely how many parameters exist. Predict the count before revealing the budget, then ask whether the bound evaluation establishes sufficiency. A configuration can be comfortably below a memory limit and still fail the task.
Budget the update, then check sufficiency
Predict how rank and target coverage change trainable parameters and the memory lower bound, then distinguish a feasible budget from a configuration that passes held-out quality evidence.
Account for low-rank training state
A bounded projection-bank model, not a GPU sizing estimate. Compare the current full-weight and adapter costs, then predict whether doubling rank fits a declared training-state budget.
Whole number 1–64. Invalid drafts restore the last valid value on blur or Escape.
Whole number 1–4. Invalid drafts restore the last valid value on blur or Escape.
Whole number 16–1024. Invalid drafts restore the last valid value on blur or Escape.
Current state: rank 8
There are L = 12 layers. Every selected weight is d × d. Each adapter adds B (d × r) and A (r × d); all 1 adapters train concurrently against one frozen bank.
P = L × t × d² = 6,291,456
A = a × L × t × 2dr = 196,608
s = weights + gradients + moments = 2b + o = 12 bytes
Full copies: a × P × s = 72.00 MiB
Adapters: P × b + A × s = 14.25 MiB
- Full trainable parameters (1 copies)
- 6,291,456
- Adapter trainable parameters
- 196,608
- Shared frozen bank
- 12.00 MiB
This accounts only for selected projections, weights, same-dtype gradients, and the declared optimizer states. No FP32 master copy, activations, other layers, allocator overhead, quantization, or runtime workspace is included. Full tuning needs an independent bank per adaptation; adapters share one frozen bank. MiB = 2²⁰ bytes. Parameter savings do not guarantee quality or total-device fit.
Choose a prediction, then check it. Changing evidence clears the prediction.
Bind the estimate to its evaluated configuration
The fixture uses a one-million-parameter synthetic base, two 128×128 projections, rank 8, BF16 weights, and the declared FP32-state AdamW policy. Its 4,096 adapter parameters require 65,536 bytes of trainable state; adding two million base-weight bytes gives a 2,065,536-byte lower bound. Its invented quality score of 0.8 misses the invented requirement of 0.9. The report blocks sufficiency despite the small budget and explicitly excludes activations, workspaces, and runtime memory.
1def main():2 result = audit(example_contract())3 print("example=illustrative_only")4 print(f"trainable_parameters={result.trainable_parameters}")5 print(f"lower_bound_bytes={result.lower_bound_bytes}")6 print("decision=" + result.decision)7 print("claim=" + result.claim)Expected output
example=illustrative_only
trainable_parameters=4096
lower_bound_bytes=2065536
decision=BLOCK_LOW_RANK_INSUFFICIENT
claim=LOWER_BOUND_EXCLUDES_ACTIVATIONS_WORKSPACES_RUNTIMEVerify: python3 -m unittest discover courses/ai-engineering/reference-impl/low_rank_adaptation
Frozen target records and copied identity tuples are revalidated at audit entry. A configuration digest binds rank, target shapes and order, adapter IDs, precision, optimizer, base count, version, and sharding assumptions. Evaluation also binds model, data, scope, case count, and external result content identity. Changing rank without new evaluation evidence is therefore not a valid reuse of the old sufficiency claim. The artifact validates these attestations; it does not execute a model or authenticate the referenced run.
When low rank fails, run a discriminating experiment
A failed quality gate does not identify rank as the cause. First rule out data defects, wrong target paths, incompatible templates, optimization instability, and an inadequate base model. Then compare controlled rank and target sweeps under the same data and evaluation protocol. If increasing rank or broadening target coverage repairs a stable failure, you have evidence about the constraint. If every rank fails similarly, buying more low-rank parameters may not address the actual deficit.
Compare against a stronger base and, where justified and feasible, a full-fine-tuning control. Watch for forgetting outside the tuned domain and failures on underrepresented cohorts. Stop treating low rank as sufficient when qualified evidence says it misses requirements; choose a new experiment or intervention through the adaptation decision process. Do not relabel a failed requirement as acceptable merely because the adapter is convenient to deploy.
Operate at three altitudes
Production lens
- — Compare the lower-bound ledger with measured runtime peaks; retain the exclusions and workload shape beside every number.
- — Validate adapter/base compatibility and target resolution against the real checkpoint, not only human-readable architecture names.
- — Retest quality after changing rank, targets, quantization, optimizer, base version, or adapter routing; keep rollback and merge-parity fixtures.
Staff lens
- — Separate parameter-efficient experimentation from a claim that low rank is universally adequate; require controlled evidence for sufficiency.
- — Budget storage, resident adapters, training state, activations, distributed overhead, and operational routing as distinct ownership surfaces.
- — Maintain an adapter registry with immutable content identity, compatible base revisions, approved scopes, and withdrawal/rollback policies.
Interview defense
Derive LoRA's parameter savings and explain why they do not directly predict GPU memory or task success.
For W of shape d_out by d_in, LoRA learns B of shape d_out by r and A of shape r by d_in, so the update has r(d_in+d_out) parameters and rank at most r. I sum over actual targets and adapters, then count base weights, adapter weights, gradients, master copies, and optimizer states under explicit dtypes. That is only a lower bound without activations and runtime buffers. Sufficiency is empirical and configuration-specific: I bind held-out evidence to rank, targets, base, data, and policy, and block a configuration that misses quality gates even if its memory estimate is attractive.
Expect the interviewer to press on
- — Does low-rank adaptation imply the base weight matrix is low rank?
- — Why can't you divide this global ledger by GPU count?
- — What experiment distinguishes rank limitation from bad data?
Misconceptions to remove
“LoRA makes the whole model low rank.”
It constrains the learned update to selected matrices; the frozen base remains full-shaped and may be full rank.
“A small trainable parameter count predicts peak GPU memory.”
Base weights, activations, temporary buffers, optimizer policy, placement, and allocator behavior all matter.
“Increasing rank always improves the task.”
Quality depends on data, optimization, targets, base capability, and evaluation; rank increases expressive capacity but does not guarantee improvement.
Check your model
1. How many adapter parameters does rank 8 add to one 128×128 target?
8×(128+128)=2,048. Two such targets with one adapter contain 4,096 trainable parameters.
2. Why does the example block even though its lower bound is small?
Its illustrative held-out quality is below the bound requirement. Feasibility and sufficiency are separate gates.
3. Can evaluation for rank 8 automatically qualify rank 16?
No. The configuration changed, so the old evaluation no longer binds the proposed candidate; a new run and identity are required.
Prove the mechanism
Add a second synthetic adapter and verify that trainable state doubles while frozen base bytes do not. Test duplicate IDs, stale target names, unsupported quantization, nondivisible dimensions, and constructor-bypassed ranks.
Add a production constraint
Design a controlled rank/target experiment with fixed data, base model, optimizer budget, and independent evaluation. Specify how runtime peak memory will be measured separately and what result would justify full fine-tuning or a different base.
Artifact: Low-rank adaptation budget
courses/ai-engineering/reference-impl/low_rank_adaptation/low_rank_budget.py
Download reference implementationPrimary references and next links
References
- 1. LoRA: Low-Rank Adaptation of Large Language Models
Hu et al.. Primary derivation and evaluation of low-rank parameter updates.
- 2. QLoRA: Efficient Finetuning of Quantized LLMs
Dettmers et al.. Primary quantized-base adaptation work; motivates separating quantization from simple dtype accounting.
- 3. Scaling Instruction-Finetuned Language Models
Chung et al.. Primary study of instruction-tuning factors and evaluation breadth, not a guarantee for the illustrative adapter.
Continue through the graph
- Prompt, Retrieve, Fine-Tune, or Train? →
Return to the intervention decision when low rank is insufficient.
- Supervised Fine-Tuning as Behavior Shaping →
Check the data and objective before attributing a failure to rank.
- Matrices as Small Programs →
Trace the factor shapes and composed update as a linear program.
Glossary: LoRA · low-rank update · adapter · trainable parameter · optimizer state · master weights · memory lower bound · quantization