PEFT Comparison › Parameter Efficiency Comparison
Language AI HandbookAll chapters PEFT Comparison › Parameter Efficiency ComparisonOne section · Sections in this chapter2 / 13 ↓
Reading tools Definitions & inline links
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
PEFT methods adapt large models by updating only a small fraction of parameters. To make a useful comparison, we need concrete metrics rather than qualitative descriptions. Examining the parameter counts reveals how methods differ in memory and storage requirements, and these numbers connect directly to the hardware constraints you'll face in practice.
The central question is not just "how few parameters can a method use?" but "how efficiently do those parameters capture the necessary adaptation?" A method that uses 1% of parameters but reaches only 80% of full fine-tuning performance is less parameter-efficient in a practical sense than a method that uses 0.3% of parameters and reaches 97% performance. Throughout this section, keep in mind that parameter count is a proxy for what we care about: the combination of hardware requirements, storage costs, and training time that determines whether a method is practical for your situation.
We will work through the parameter calculations for each method applied to a common reference model, establishing a shared baseline that allows direct comparison. The numbers we derive here are not just theoretical exercises. They explain the real-world constraints you encounter when choosing between a 16GB GPU and a 48GB GPU, or between running five experiments in parallel versus two.
Absolute Parameter Counts
Let's establish concrete numbers for a typical 7B parameter model like LLaMA-2-7B with hidden dimension , 32 layers, and 32 attention heads. Calculating the parameters for each method shows the tradeoffs and suitability for different hardware constraints.
LoRA approximates weight updates by decomposing them into two low-rank matrices, and , such that . This design relies on the hypothesis that weight updates have a low "intrinsic rank," meaning the necessary adaptations exist in a low-dimensional subspace. The key insight motivating this approach is that while the original weight matrices are enormous, the changes needed to adapt a model to a new task may be far simpler in structure. If we can capture these changes using matrices with reduced dimensionality, we reach large parameter savings without sacrificing the model's ability to learn the task. For a layer with hidden dimension and rank , the number of parameters is . When applied to all four attention projections (), we sum across all layers to get the total trainable parameter count.
The total number of trainable parameters for LoRA is calculated by summing the parameters of the low-rank matrices and across all target modules and layers. This calculation reveals how the rank parameter is a direct control knob for the tradeoff between model capacity and parameter count:
where:
- : the number of target modules per layer (Query, Key, Value, Output)
- : parameters for matrices and in one module (since each has size or )
- : hidden dimension ()
- : rank of the low-rank adapters ()
- : number of layers ()
For our LLaMA-2-7B setup, this yields:
This result is striking: we can adapt a 7 billion parameter model by training only 16.8 million parameters, a reduction of over 400 times. The rank of 16 is deliberately chosen to be small enough to give substantial parameter savings while still giving sufficient capacity for most adaptation tasks. If the task proves to be complex, increasing the rank to 32 or 64 gives more capacity while still training only a small fraction of the model's parameters.
Adapters insert bottleneck modules, consisting of a down-projection and an up-projection, after both the attention and feed-forward (FFN) layers. This bottleneck architecture compresses inputs into a lower-dimensional representation before expanding them back, reducing parameter count while letting non-linear adaptation. The basic idea behind adapters is that task-specific information can be "filtered" through a narrow bottleneck, forcing the model to learn only the most needed transformations. This compression-expansion pattern also introduces non-linearity through activation functions, giving adapters additional representational power compared to linear methods like LoRA. With bottleneck dimension , we calculate the parameters for one adapter:
We calculate the parameter count by summing the weights of the down-projection and up-projection matrices for each adapter. The symmetry of this calculation, with equal contributions from each projection direction, shows the balanced nature of the bottleneck design:
where:
- : the number of adapters per layer (one inserted after Attention, one after FFN)
- : the hidden dimension of the model ()
- : the size of the bottleneck dimension ()
- : the number of parameters in the down-projection matrix
- : the number of parameters in the up-projection matrix
- : the number of layers in the model ()
Plugging in the values:
Adapters require roughly twice as many parameters as LoRA with rank 16. This increased parameter count buys additional expressiveness through the non-linear activation function between the down and up projections, but comes at the cost of both storage and, as we'll see later, inference overhead. The bottleneck dimension of 64 was chosen here to be illustrative; in practice, practitioners often tune this value just as they would tune LoRA's rank.
Prefix Tuning prepends learnable vectors to the keys and values at every layer. These virtual tokens effectively "steer" the attention mechanism at every depth, guiding the model's internal processing without modifying any weights. Rather than modifying the model's weights directly, prefix tuning modifies the context that the model attends to at every layer. Optimizing key-value pairs at every layer influences attention flow without changing the transformation matrices. With prefix length , we can calculate the total parameter count.
The trainable parameters consist of the virtual token embeddings added to the Key and Value matrices at each layer. This formulation makes clear why prefix tuning affects only the attention mechanism: we're adding content for the model to attend to, not modifying how it processes that content:
where:
- : the prefix length (number of virtual tokens, set to )
- : the hidden dimension ()
- : a factor accounting for application to both Key and Value matrices
- : the number of layers ()
Substituting the values:
The parameter count for Prefix Tuning is lower than LoRA despite operating at every layer. This efficiency comes from the method's focused scope: it only influences the attention mechanism through the key-value channel, leaving all other computations unchanged. However, this scope also explains one of Prefix Tuning's key weaknesses, which we'll analyze when we examine task performance.
Prompt Tuning adds learnable embeddings only at the input layer. Unlike discrete text prompts, these continuous embeddings are optimized directly via backpropagation to find the most effective task trigger. This approach is perhaps the simplest possible form of model adaptation: we're in effect learning a better way to "ask" the model to perform our task. The continuous nature of these embeddings allows optimization to find representations that may have no natural language equivalent, potentially discovering more effective task specifications than any human-written prompt could give. With prompt length :
The parameters come solely from the learnable embeddings prepended to the input layer. This single-layer application is what gives Prompt Tuning its remarkable parameter efficiency, though it also limits the method's ability to influence deep model computations:
where:
- : the prompt length (number of virtual tokens, set to )
- : the embedding dimension ()
Calculating the total:
With fewer than half a million parameters, Prompt Tuning reaches the smallest footprint of any method we've examined. This extreme efficiency makes it ideal for scenarios where storage or memory is at an absolute premium, though as we'll see in the performance analysis, this efficiency comes with real tradeoffs.
IA³ introduces learned vectors that scale the activations element-wise. This acts like a feature equalizer, selectively amplifying or suppressing specific activation channels based on what the task requires. IA³ assumes the base model computes useful features and only needs to adjust their relative importance for different tasks. Rather than learning new transformations, IA³ learns which existing computations to emphasize and which to diminish. IA³ is effective because it uses pre-trained representations: the model has already learned to compute real features, and IA³ simply re-weights them for the task at hand. We calculate the parameter count by summing the scaling vectors for the Key, Value, and FFN intermediate activations:
where:
- : the dimension of scaling vectors for attention keys and values (, matching the hidden dimension)
- : the dimension of the scaling vector for the FFN expansion layer ()
- : the number of layers ()
This results in a very small number of parameters:
The parameter count for IA³ is remarkably low, just over half a million for a 7B model. This efficiency stems from the element-wise nature of the scaling operation: we need only one scalar per activation dimension, rather than full transformation matrices. The tradeoff is that IA³ can only rescale existing activations, not compute fundamentally new features.
!uv pip install pandas matplotlib numpy
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
# Model setup (LLaMA-2-7B-like)
hidden_dim = 4096
num_layers = 32
num_heads = 32
head_dim = hidden_dim // num_heads
ffn_dim = 11008 # LLaMA uses ~2.7x expansion
total_params = 7e9
# PEFT parameter calculations
methods = {
'Prompt Tuning': 100 * hidden_dim, # 100 soft tokens
'IA³': (hidden_dim + hidden_dim + ffn_dim) * num_layers, # k, v, ffn scaling
'Prefix Tuning': 20 * hidden_dim * 2 * num_layers, # 20 prefix tokens, K and V
'LoRA (r=16)': 2 * 16 * hidden_dim * 4 * num_layers, # A and B for Q,K,V,O
'LoRA (r=64)': 2 * 64 * hidden_dim * 4 * num_layers,
'Adapters': 2 * hidden_dim * 64 * 2 * num_layers, # bottleneck=64, 2 adapters per layer
'Full Fine-tuning': total_params
}
# Calculate percentages
percentages = {k: (v / total_params) * 100 for k, v in methods.items()}Parameter Efficiency Comparison for 7B Model
============================================================
Method Trainable Parameters % of Model
Prompt Tuning 0.41M 0.0059%
IA³ 0.61M 0.0088%
Prefix Tuning 5.24M 0.0749%
LoRA (r=16) 16.78M 0.2397%
LoRA (r=64) 67.11M 0.9587%
Adapters 33.55M 0.4793%
Full Fine-tuning 7.0B 100.0%The differences are large. Prompt Tuning and IA³ train fewer than 1 million parameters, less than 0.01% of the model. LoRA at typical ranks trains 0.2-0.9% of parameters. Even the "heaviest" PEFT method, Adapters, trains less than 0.5% of the model. These numbers illustrate a basic principle: the large majority of a pre-trained model's knowledge is encoded in its frozen weights, and task-specific adaptation can be achieved with remarkably few additional parameters. This insight, that large pre-trained models contain far more knowledge than any single downstream task requires, underlies the entire PEFT paradigm.


Memory Footprint Analysis
Parameter count alone doesn't tell the full story. During training, memory consumption includes model weights, optimizer states, gradients, and activations. Understanding the complete memory picture is needed for determining which methods will fit on your hardware. A method might train fewer parameters but still require substantial memory for other components of the training process.
Think of memory during training as having four distinct buckets that must all fit simultaneously into GPU VRAM. The first bucket holds the model weights themselves, which you must keep loaded at all times regardless of how many parameters you're updating. The second bucket holds the optimizer states, which for AdamW include two floating-point values per trainable parameter (the first and second moment estimates). The third bucket holds the gradients computed during backpropagation, which require storage for every trainable parameter. The fourth bucket holds the activations saved during the forward pass that are needed for gradient computation during the backward pass. PEFT methods reduce the second and third buckets to near zero for frozen parameters, but the first bucket remains unchanged.
For full fine-tuning with AdamW, memory is consumed by weights, optimizer states, gradients, and activations. Assuming mixed precision training, we can estimate the total memory requirement by analyzing the contribution of each component:
where:
- weights: memory for the model parameters (usually FP16), consuming 2 bytes per parameter
- optimizer: memory for optimizer states (momentum and variance in AdamW), consuming approximately 8 bytes per parameter in FP32
- gradients: memory for storing gradients during backpropagation, consuming approximately 4 bytes per parameter
- activations: memory for intermediate outputs needed for the backward pass, which scales with batch size and sequence length
Using a simplified estimation model:
where:
- : the total number of model parameters
- : FP16 model weights ( bytes per parameter)
- : optimizer states (simplified estimate for AdamW first and second moments)
- : gradients (FP32 or mixed precision)
- : activations (approximate average per layer)
For a 7B model, this works out to approximately GB of VRAM. Full fine-tuning is memory-intensive because requirements scale linearly with parameters, and each parameter needs storage for multiple values. No consumer GPU can come close to fitting these requirements.
PEFT methods drastically reduce memory by freezing the base model and training only the adapter parameters. The key insight is that frozen parameters need only their weights stored, not optimizer states or gradients. This is the most important memory saving PEFT gives: by freezing 99%+ of parameters, we eliminate the need to store optimizer states and gradients for those parameters, reducing the total memory requirement by a factor of 5-6x. With LoRA (rank 16):
For LoRA, we only need to store the optimizer states and gradients for the small set of trainable parameters, while the base model remains frozen in low precision. This separation between frozen and trainable parameters is the basic mechanism through which all PEFT methods reach their memory efficiency:
where:
- : the number of frozen base model parameters ( billion)
- : the number of trainable LoRA parameters ( million)
- : bytes per frozen parameter (FP16 weights only, no optimizer state or gradient needed)
- : the memory factor for trainable parameters (weights + optimizer + gradients + activations)
Applying this to our example:
This is why a 7B model that requires 80+ GB for full fine-tuning can be fine-tuned with LoRA on a single 24GB GPU. Memory savings make fine-tuning accessible; LoRA lets adaptation on hardware unsuitable for full fine-tuning. This shift in memory requirements lets you to adapt large models for your specific needs without expensive compute clusters or cloud GPU instances. The practical implication of this reduction cannot be overstated: it transformed large model fine-tuning from an activity requiring specialized infrastructure into something a graduate student with a gaming GPU can do.
def estimate_training_memory(
total_params,
trainable_params,
batch_size=4,
seq_len=512,
hidden_dim=4096,
num_layers=32,
precision="fp16",
):
"""Estimate GPU memory requirements for training."""
bytes_per_param = 2 if precision == "fp16" else 4
# Model weights (frozen in FP16)
frozen_params = total_params - trainable_params
weight_memory = frozen_params * 2 # FP16 frozen
weight_memory += trainable_params * bytes_per_param # Trainable weights
# Optimizer states (FP32 for stability)
optimizer_memory = trainable_params * 4 * 2 # Adam has 2 states
# Gradients for trainable params only
gradient_memory = trainable_params * 4 # FP32 gradients
# Activation memory (rough estimate)
# Each layer stores attention patterns and intermediate activations
activation_per_layer = (
batch_size * seq_len * hidden_dim * bytes_per_param * 4
)
activation_memory = activation_per_layer * num_layers
total_gb = (
weight_memory + optimizer_memory + gradient_memory + activation_memory
) / 1e9
return {
"weights_gb": weight_memory / 1e9,
"optimizer_gb": optimizer_memory / 1e9,
"gradients_gb": gradient_memory / 1e9,
"activations_gb": activation_memory / 1e9,
"total_gb": total_gb,
}batch_size = 4
seq_len = 512
# Calculate memory for each method
memory_estimates = {}
for method, trainable in methods.items():
if method == "Full Fine-tuning":
trainable = total_params
memory_estimates[method] = estimate_training_memory(
total_params=total_params,
trainable_params=trainable,
batch_size=batch_size,
seq_len=seq_len,
)Memory Estimates (Batch Size=4, Seq Len=512) ====================================================================== Method Weights Optimizer Total ---------------------------------------------------------------------- Prompt Tuning 14.0 GB 0.0 GB 16.2 GB IA³ 14.0 GB 0.0 GB 16.2 GB Prefix Tuning 14.0 GB 0.0 GB 16.2 GB LoRA (r=16) 14.0 GB 0.1 GB 16.3 GB LoRA (r=64) 14.0 GB 0.5 GB 17.0 GB Adapters 14.0 GB 0.3 GB 16.6 GB Full Fine-tuning 14.0 GB 56.0 GB 100.1 GB
The estimated values show the large efficiency gains of PEFT. While full fine-tuning demands over 80GB of VRAM, requiring high-end data center GPUs, all PEFT methods operate comfortably within the memory limits of consumer hardware (14-16GB). This 5-6x reduction in memory footprint makes fine-tuning accessible to individuals, small teams, and educational institutions that do not have data-center GPUs. The gap between PEFT methods themselves is much smaller than the gap between any PEFT method and full fine-tuning, which reinforces the idea that choosing between PEFT methods is primarily a question of performance and workflow rather than hardware constraints.
