Create your own
Lesson illustration

LoRA Parameter Counts and Adapter Rank Effects

Good to see you again. In the previous lesson, you built the SFT training artifact: a model-specific token sequence with labels that charge loss only to assistant-response tokens. That loss still backpropagates through the whole transformer, but it does not require every base-model weight to be updated.

This lesson examines LoRA’s central systems bargain: keep the pretrained weights frozen and train a small, low-rank correction for selected weight matrices. You will be able to calculate the exact trainable-parameter count from a model’s layer dimensions, target modules, and adapter rank, then explain what increasing rank buys—and costs.


The object LoRA trains

Consider a linear transformation in a transformer block:

where is a frozen pretrained weight matrix with shape . Here, is the input width and is the output width. A full fine-tune would make all entries of trainable.

LoRA instead preserves and learns an additive update:

Rather than materializing a full matrix for , LoRA parameterizes it as:

with:

The forward computation can therefore be written as:

The trainable path first projects the activation down to an -dimensional bottleneck through , then projects it back to output dimension through . The base path remains intact.

This matters directly for the SFT job you just studied. The assistant-only cross-entropy loss produces gradients as usual, but the optimizer updates only the LoRA matrices and , not . Thus, the base model still needs to be resident for the forward and backward computation, but it does not need trainable gradients or optimizer state.

For a visual walkthrough of the dimensions and the basic arithmetic, watch this short segment.

Low-rank Adaption of Large Language Models: Explaining the Key Concepts Behind LoRA

In “Low-rank Adaption of Large Language Models,” Chris Alexiuk shows why a full update matrix can be replaced by two narrow trainable matrices.

Watch the factorization example. Track the shapes d \times r and r \times k, then verify why their product has the same shape as the original d \times k weight update.


Counting parameters for one adapted matrix

The count is simply the number of entries in plus the number of entries in :

For comparison, a full update to the same weight matrix contains:

So the LoRA parameter fraction, relative to full fine-tuning of that same matrix, is:

The corresponding percentage is .

A rectangular example

Suppose an adapted projection has:

Full fine-tuning of the weight update would train:

parameters.

LoRA instead trains:

parameters:

  • has parameters.
  • has parameters.

The LoRA adapter is therefore about times smaller for this matrix:

The key mechanical rule is worth committing to memory:

For every adapted linear weight of shape , add trainable LoRA parameters.

Read the following sections for the mathematical intuition behind this rule and the engineering interpretation of rank.

LoRA Concept: Low-Rank Adaptation for Efficient LLM Fine-Tuning ...

“LoRA Concept” explains the low-rank bottleneck and connects adapter rank to both parameter count and adaptation capacity.

In “What Rank Means for Matrices,” read from the factorized representation through the numerical 4096 \times 4096, rank-8 example just before the visualization. Focus on why the two factor matrices contain r(d+k), not dk, entries. Then, in “LoRA's Decomposition Strategy,” begin at the structural definition. Continue through the explanation that the pretrained weights remain frozen; distinguish the frozen base path from the trainable correction path. Finally, in “Rank as an Expressiveness Knob,” read from the rank tradeoff and the four following bullets. Treat the suggested rank ranges as starting hypotheses, not universal defaults.


From one matrix to a transformer-wide count

A real LoRA configuration targets a set of linear modules, repeated across transformer layers. The total count is the sum across every adapted matrix:

This is the safest production formula because it handles:

  • non-square MLP projections;
  • different ranks for different modules;
  • different layer types;
  • adapters applied only to selected layers;
  • extra trainable components such as an output head.

If all target matrices share the same dimensions and rank, the calculation can be compressed. For layers, adapted matrices per layer, and matrices shaped :

For the common square-projection case, where :

Here is the model hidden size.

Worked transformer example: adapting and

Consider a decoder-only model with:

  • transformer layers,
  • hidden size ,
  • rank ,
  • LoRA applied to the query and value projections only.

Each or projection is a square matrix. One adapter therefore contains:

trainable parameters.

There are two target matrices in each layer and 32 layers, so:

Thus, the configuration trains about 4.19 million parameters.

A useful audit table is:

QuantityCalculationResult
One or adapter65,536
Both adapters in one layer131,072
All 32 layers4,194,304

Compare against a like-for-like baseline

There is a common interview and capacity-planning mistake here: comparing a LoRA configuration applied to only and against full fine-tuning of some other set of parameters.

For a fair matrix-level comparison, compare LoRA on and against full tuning of those same and weights:

The LoRA fraction is:

or approximately:

That is also what the square-matrix formula predicts:

You may also compare the 4.19 million trainable parameters to the entire approximately 7-billion-parameter model, yielding roughly . Both percentages are valid, but they answer different questions:

DenominatorWhat the percentage means
Corresponding targeted weightsCompression of the adapted matrices
All attention projectionsShare relative to a full attention-only fine-tune
Entire modelFraction of the whole model made trainable

State the denominator whenever you report a LoRA percentage.


Rank is a capacity and cost knob

The product has rank at most :

So rank bounds the complexity of the update LoRA can express for a particular weight matrix. A rank-4 adapter can alter the base transformation along at most four independent update directions; rank 32 permits up to 32.

Increasing rank has two certain effects:

  1. It increases the maximum rank of the possible update.
  2. It increases adapter parameter count linearly.

For a fixed target matrix, doubling doubles:

It does not guarantee that task quality doubles, or even improves. Rank is an upper bound on update capacity, not a measure of useful learned behavior.

This graph plots LoRA trainable parameters as a percentage of a full square weight-matrix update as adapter rank increases. The steeper lines for smaller hidden sizes reflect the square-matrix ratio \(2r/h\): a fixed rank consumes a larger fraction of a smaller projection matrix.

For a square projection:

This explains two patterns in the graph:

  • Every line is straight because parameter count is linear in .
  • At the same rank, a model with larger hidden size has a lower percentage because its full projection matrix grows with , while its LoRA adapter grows only with .

For example, at :

for a BERT-base-style projection, while:

for an LLaMA-70B-style projection.

Choosing rank in practice

Rank interacts with the task, data, model, and operational constraints.

SituationRank implication
Narrow task, modest dataset, strong base modelLower rank may be sufficient and can regularize the update
Broad behavior change or complex generation taskHigher rank may provide useful capacity
Evidence of underfitting after data and optimization checksConsider increasing rank or targeting more modules
Small or noisy fine-tuning datasetVery high rank can make memorization easier
Tight optimizer-memory or adapter-storage budgetLower rank reduces trainable state and checkpoint size linearly

A strong experimental plan changes one variable at a time. For instance, keep target modules, data, token budget, learning-rate schedule, and evaluation suite fixed; compare ranks such as , , and . Then inspect held-out task quality, safety behavior, regressions, and overfitting—not merely training loss.

Two configuration details should remain separate from parameter counting:

  • LoRA alpha scales the adapter update, often through a factor related to . It affects update magnitude, but does not change the number of trainable parameters.
  • LoRA dropout regularizes the adapter path during training, but does not change parameter count.

When sweeping rank, hold the scaling convention deliberately. Otherwise, an apparent “rank effect” may partly be a change in effective update scale.


Counting correctly in an actual training configuration

On a model diagram, it is easy to say “apply LoRA to attention.” In an implementation, count the concrete modules.

A practical inventory might look like this:

Adapted module typeBase weight shapeLoRA parameters per occurrence
Attention query projection
Attention value projection
MLP up projection
MLP down projection

Here, is the MLP intermediate width. Notice that each MLP projection has the same LoRA count even though their shapes are transposes of each other.

For system design, calculate the expected count before launching the job, then verify the training framework’s actual count. A simple model-level audit is:

def count_trainable_parameters(model):
    return sum(
        parameter.numel()
        for parameter in model.parameters()
        if parameter.requires_grad
    )

def list_trainable_parameters(model):
    for name, parameter in model.named_parameters():
        if parameter.requires_grad:
            print(f"{name:70} {parameter.numel():,}")

The printed names matter. They reveal configuration surprises such as:

  • LoRA applied to more projections than intended.
  • A classification or language-model head left trainable.
  • Bias terms configured as trainable.
  • “Modules to save” included alongside adapters.
  • A target-module pattern matching an unexpected architecture-specific layer.

If any of those extra tensors are trainable, add them to the theoretical LoRA count. The formula counts the two low-rank matrices only; it does not automatically include trainable biases, heads, embeddings, or other saved modules.

One final precision point: and contain allocated, trainable scalar parameters, which is the count relevant to optimizer-state memory and checkpoint size. The factorization is not unique, so its abstract degrees of freedom are lower than this raw scalar count. Do not subtract that redundancy when sizing a training job: the optimizer still stores state for every element of and .


Key takeaways

LoRA freezes a base weight and trains a low-rank update:

For a target matrix of shape and LoRA rank , the adapter has:

trainable parameters, versus for full fine-tuning of that same matrix.

For repeated transformer modules, sum the count over every targeted projection. In the common square case, each adapted projection contributes parameters. Rank increases both trainable footprint and the maximum rank of the update linearly, but higher rank is not a guaranteed quality improvement.

Next, we will use these calculations to compare full fine-tuning, general adapter-based PEFT, LoRA, and QLoRA under memory, quality, and deployment constraints.

Can't find a good explanation? Sign up and we'll make it for you

Sign up