Fun with Learning Technology
LearnCoursesQuestionsTracksToolsNewsExplorePractice
Fun with Learning Technology

A new problem, explained clearly, every day.

Subscribe
Learn
  • Lessons
  • Topics
  • News
  • Tools
  • Courses
  • Career tracks
  • Everything
Site
  • About
  • Contact
  • Support
  • Privacy
  • Terms
Get the daily one

One email per new problem. No spam.

Request a tutorial

Requests shape what gets made next.

© 2026 Fun with Learning TechnologyRSS
Home›Courses›Generative AI›LoRA and QLoRA — Parameter Efficient Fine-tuning

Fine-tuning and Model Training

LoRA and QLoRA — Parameter Efficient Fine-tuning

LoRA and QLoRA are parameter-efficient fine-tuning techniques that adapt large pre-trained models to specific tasks by training only a tiny fraction of the original weights. These methods allow you to customize massive models on consumer-grade hardware by freezing the core architecture and injecting trainable low-rank adapters. You should reach for these techniques whenever full parameter fine-tuning becomes computationally prohibitive due to VRAM constraints or when maintaining the integrity of the original model weights is a functional requirement.

The Core Problem: Full Fine-Tuning Limitations

Full fine-tuning involves updating every parameter in a neural network during backpropagation, which is inherently expensive. For a model with billions of parameters, this requires storing gradients and optimizer states for every single weight, quickly exceeding the memory capacity of even the most powerful enterprise GPUs. Beyond hardware constraints, full fine-tuning poses the risk of 'catastrophic forgetting,' where the model overwrites the generalized knowledge it acquired during pre-training to satisfy the specific patterns of a small target dataset. This loss of general competence often renders the model brittle, failing on tasks outside the narrow fine-tuning scope. By updating all parameters, we create a massive optimization landscape that is difficult to navigate effectively without massive amounts of data. Understanding that the intrinsic dimension of neural network updates is often much lower than the full parameter space allows us to seek more surgical, efficient alternatives that prioritize stability over total weight re-calibration.

import torch
# Simulating the parameter count of a large model
params = torch.nn.Parameter(torch.randn(10000, 10000))
# A full gradient update would require storing 100M values
optimizer = torch.optim.Adam([params], lr=1e-5)
# In reality, this would require 400MB just for the gradients!

Understanding LoRA (Low-Rank Adaptation)

LoRA (Low-Rank Adaptation) operates on the hypothesis that the change in weights during fine-tuning exhibits a low intrinsic rank. Instead of updating a large weight matrix W, we freeze W and introduce two smaller matrices, A and B, such that their product forms the delta update: W + BA = W'. If W is of dimension (d x k), we constrain A to (r x k) and B to (d x r), where the rank 'r' is much smaller than 'd' or 'k'. During training, we keep W frozen and update only A and B. Because 'r' is tiny, the number of trainable parameters is reduced by orders of magnitude. Mathematically, this captures the most important directional changes in the weight landscape without requiring the massive compute of full matrix multiplication. This architectural design ensures that the pre-trained weights remain pristine, effectively allowing us to store multiple specialized adapters for different tasks while keeping one shared backbone.

import torch.nn as nn
class LoRALayer(nn.Module):
    def __init__(self, d, k, r=8):
        super().__init__()
        self.w = nn.Parameter(torch.randn(d, k), requires_grad=False) # Frozen
        self.a = nn.Parameter(torch.randn(r, k)) # Trainable
        self.b = nn.Parameter(torch.randn(d, r)) # Trainable
    def forward(self, x):
        return x @ self.w.T + (x @ self.a.T) @ self.b.T # Original + LoRA

Quantized LoRA (QLoRA) for Memory Efficiency

QLoRA takes the concept of parameter efficiency further by quantizing the base model weights to 4-bit precision before loading them into memory. A standard 16-bit weight matrix requires significant VRAM, but 4-bit NormalFloat (NF4) quantization compresses this footprint drastically while maintaining model accuracy. The key innovation is the use of 'double quantization,' which quantizes the quantization constants themselves to save additional memory, and a 'paged optimizer' that utilizes CPU RAM to manage gradient spikes. By quantizing the backbone to 4-bit and attaching LoRA adapters in 16-bit, we achieve a memory profile that allows a multi-billion parameter model to fit onto a single consumer GPU. This layering approach ensures that the high-precision updates required for learning occur in the LoRA adapters, while the compressed base model provides a stable, intelligent foundation for those updates to refine.

import bitsandbytes as bnb
# Using NF4 quantization for the base weights
linear_4bit = bnb.nn.LinearNF4(input_features=1024, output_features=1024)
# The base weight is now stored in 4 bits, drastically reducing VRAM usage

Implementation Strategy: The Adapter Pattern

In practice, implementing these adapters requires carefully selecting which layers to target. Usually, targetting the query (Q) and value (V) projection matrices in the transformer attention blocks yields the best performance-to-parameter ratio. Because the adapters are separate, modular components, they can be saved and swapped out on the fly. This design enables 'multi-tenancy,' where one large base model can serve dozens of different applications by dynamically loading lightweight adapters based on the incoming request. When deploying, we perform a 'merge' operation, where the weights of A and B are multiplied and added to the base weight matrix W. This process results in a model that performs exactly like the original but with fine-tuned parameters, eliminating any inference-time latency overhead. Properly managing the adapter configuration is essential to ensure that the model capacity remains sufficient for complex, high-reasoning tasks while remaining small enough for efficient deployment pipelines.

# Merging the LoRA weights into the base weights for inference
base_w = original_weights
updated_w = base_w + (b_matrix @ a_matrix)
# The final model now runs at full speed without extra overhead

Navigating Hyperparameters in PEFT

While LoRA and QLoRA simplify training, they introduce new hyperparameter sensitivities, specifically the rank 'r' and the scaling factor 'alpha.' A larger rank provides more 'learning capacity' but risks overfitting if the training dataset is small or noisy. 'Alpha' acts as a scaling constant that determines the contribution of the adapter weights to the final output; common practice involves setting alpha to double the rank to ensure stable gradients. It is also crucial to consider the 'dropout' rate within the LoRA layers to prevent overfitting to specific phrasing in the training data. Because the adapter parameters are small, they are prone to overfitting very quickly; therefore, monitoring validation loss and using techniques like early stopping are mandatory. Effectively tuning these variables involves balancing the desired adaptation depth against the limited parameter budget allocated to the adapter layers, ensuring that the model retains its core capability while successfully learning the target domain.

rank = 16
alpha = 32
dropout = 0.05
# Applying scaling to keep training stable during the weight update
scaling = alpha / rank
# Update rule: W_new = W_old + (b @ a) * scaling

Key points

  • Full fine-tuning of large language models is often impractical due to the massive VRAM requirements of storing gradients for all parameters.
  • LoRA reduces the number of trainable parameters by injecting low-rank matrices into the transformer layers instead of updating the full weight matrices.
  • The core pre-trained weights are kept frozen during LoRA training to preserve the model's original knowledge and prevent catastrophic forgetting.
  • QLoRA further optimizes memory by quantizing the backbone model weights to 4-bit, allowing training on standard consumer GPUs.
  • Double quantization in QLoRA helps minimize memory usage by quantizing the constants used to quantize the model weights.
  • LoRA adapters can be merged into the base model at inference time to ensure zero latency overhead for production deployments.
  • The rank hyperparameter determines the expressivity of the adapter, where higher ranks allow for more complex weight changes at the cost of memory.
  • Alpha scaling is a critical hyperparameter used to balance the influence of the adapter weights against the base model during the learning process.

Common mistakes

  • Mistake: Freezing the wrong layers during fine-tuning. Why it's wrong: Fine-tuning requires locking the base model parameters; updating them defeats the efficiency of LoRA. Fix: Ensure the base model is loaded in 4-bit or 8-bit precision with requires_grad set to False.
  • Mistake: Incorrect rank (r) selection. Why it's wrong: Setting the rank too high increases the number of trainable parameters significantly, leading to overfitting and negating the computational savings. Fix: Start with a small rank like 8 or 16 and increase only if the model fails to capture necessary domain-specific nuances.
  • Mistake: Ignoring target modules. Why it's wrong: Applying LoRA only to specific projection layers (like query/value) while ignoring others can result in poor convergence. Fix: Target all linear layers or at least all attention-related projections (q, k, v, o) to maximize adaptation efficacy.
  • Mistake: Misconfiguring the alpha parameter. Why it's wrong: Setting alpha too high or too low relative to the rank causes the weight updates to become unstable or ineffective. Fix: A common best practice is to set alpha to double the value of the rank (e.g., r=8, alpha=16) to stabilize scaling.
  • Mistake: Applying QLoRA without proper quantization storage. Why it's wrong: Quantizing the model but failing to store the adapters in higher precision leads to rounding errors during inference. Fix: Always save adapter weights in FP32 or BF16, even if the base model is stored in 4-bit.

Interview questions

What is the primary motivation behind using Parameter Efficient Fine-tuning (PEFT) techniques like LoRA?

The primary motivation for using PEFT techniques like LoRA is to overcome the extreme computational and memory costs associated with full fine-tuning of large models. When you perform full fine-tuning, you must update and store gradients for every single weight parameter in the model, which becomes prohibitively expensive as models scale into billions of parameters. LoRA provides a solution by freezing the pre-trained weights and injecting small, trainable rank-decomposition matrices into the network layers. This allows us to achieve performance comparable to full fine-tuning while only training a tiny fraction—often less than 1%—of the original weights, significantly reducing the hardware requirements and storage footprint.

Can you explain the core mechanism of how LoRA works during the fine-tuning process?

LoRA works based on the hypothesis that the update to the weights during adaptation has a low intrinsic rank. Instead of updating a weight matrix 'W' directly, LoRA keeps 'W' frozen and introduces two smaller matrices, A and B, such that their product forms the update: delta_W = B * A. During the forward pass, the output is calculated as 'h = Wx + BAx'. We only update A and B during training. If the original weight matrix is d-by-d, and the rank is r, we reduce the number of parameters from d^2 to r*(d1+d2). Because r is typically very small, like 8 or 16, the parameter reduction is massive, which leads to much faster training.

What is the specific innovation introduced by QLoRA, and why is it important?

QLoRA is an extension of LoRA that introduces quantization to further reduce memory usage, making it possible to fine-tune massive models on consumer-grade hardware. It uses a 4-bit NormalFloat (NF4) data type to compress the pre-trained weights of the base model, significantly reducing memory footprint while maintaining high performance. Furthermore, it incorporates double quantization, which quantizes the quantization constants themselves to save even more memory, and a paged optimizer feature to manage memory spikes. This is critical for Generative AI development because it democratizes fine-tuning, allowing researchers to adapt models that would otherwise require expensive, enterprise-level GPU clusters.

How does LoRA compare to full fine-tuning in terms of deployment and inference latency?

When comparing LoRA to full fine-tuning, the differences during inference are minimal, which is a major advantage. In full fine-tuning, you are left with a new, modified set of weight matrices that are the same size as the original. With LoRA, you can actually merge the learned low-rank matrices back into the original weights by calculating W' = W + BA. This means that after merging, the model architecture is identical to the original base model, resulting in zero additional inference latency. Unlike adapters that add new layers to the inference path, a merged LoRA model performs exactly like a standard fine-tuned model, providing a seamless deployment experience.

In the context of PEFT, what is the significance of the 'rank' hyperparameter, and how does selecting it affect model behavior?

The rank 'r' is the most significant hyperparameter in LoRA because it dictates the capacity of the model to learn new information. If the rank is too low, the model may not have enough representational capacity to learn the nuances of the downstream task, leading to underfitting. Conversely, setting the rank too high increases the number of trainable parameters, which negates some of the memory benefits and risks overfitting to the fine-tuning dataset. In practice, choosing the rank is an empirical balancing act. For most complex language generation tasks, a rank between 8 and 32 is often sufficient to capture the necessary parameter shifts without creating unnecessary overhead.

Why would you choose to use QLoRA over standard LoRA, and are there any trade-offs involved?

You would choose QLoRA when you are constrained by GPU VRAM, as it allows you to fit significantly larger models into the same memory space compared to standard LoRA. For example, using 4-bit quantization allows a 70-billion parameter model to fit on a single high-end consumer GPU, whereas standard LoRA would require much more VRAM to store the model weights in 16-bit precision. The trade-off is a slight potential decrease in predictive accuracy due to the precision loss inherent in 4-bit quantization, and slightly longer training times because of the dequantization steps performed during the forward and backward passes. However, for most generative applications, these minor accuracy trade-offs are outweighed by the gain in accessibility.

All Generative AI interview questions →

Check yourself

1. What is the fundamental mechanism that allows LoRA to be computationally efficient?

  • A.It replaces the attention mechanism with a lower-dimensional linear layer.
  • B.It decomposes the weight updates into low-rank matrices to minimize the number of trainable parameters.
  • C.It prunes the model by removing redundant neurons during the fine-tuning phase.
  • D.It uses a larger learning rate to force the model to converge within fewer iterations.
Show answer

B. It decomposes the weight updates into low-rank matrices to minimize the number of trainable parameters.
Option 2 is correct because LoRA approximates weight updates using the product of two smaller matrices, drastically reducing parameters. Option 1 is wrong because the attention mechanism remains intact. Option 3 is incorrect because LoRA is an additive method, not a pruning one. Option 4 is wrong because learning rates must stay small to maintain stability, regardless of parameter count.

2. Why does QLoRA represent an improvement over standard LoRA for large models?

  • A.It eliminates the need for LoRA adapters by fine-tuning the base model directly.
  • B.It increases the rank of the matrices to capture more complex features during training.
  • C.It reduces the memory footprint of the base model via 4-bit quantization, allowing larger models on consumer hardware.
  • D.It automatically adjusts the learning rate based on the quantization error of the gradients.
Show answer

C. It reduces the memory footprint of the base model via 4-bit quantization, allowing larger models on consumer hardware.
Option 3 is correct because QLoRA leverages 4-bit NormalFloat quantization to store the base model, which drastically reduces VRAM usage. Option 1 is wrong because QLoRA still uses adapters. Option 2 is incorrect because rank selection is independent of quantization. Option 4 is wrong because QLoRA does not include an automated learning rate optimizer based on quantization error.

3. If you increase the 'r' value in your LoRA configuration from 8 to 64, what is the primary architectural trade-off?

  • A.The model will train significantly faster due to higher rank parallelism.
  • B.The risk of overfitting increases because the trainable parameter count grows substantially.
  • C.The model will require less VRAM because the gradients become smaller.
  • D.The base model's weights will be modified more permanently, reducing portability.
Show answer

B. The risk of overfitting increases because the trainable parameter count grows substantially.
Option 2 is correct because higher rank allows for more capacity, which can lead to memorization of training data rather than generalization. Option 1 is wrong because higher parameters increase compute time. Option 3 is wrong because higher parameter counts consume more memory. Option 4 is wrong because LoRA weights are separate, so they do not modify the base model weights permanently.

4. How should the scaling factor 'alpha' be utilized in relation to 'r' when fine-tuning?

  • A.Alpha should be kept at 1 regardless of the rank to ensure stability.
  • B.Alpha acts as a constant multiplier for the gradients; it should always be equal to the rank.
  • C.Alpha serves as a scaling factor, and is typically set to 2*r to balance the update magnitude.
  • D.Alpha is only used during inference to sharpen the output distribution.
Show answer

C. Alpha serves as a scaling factor, and is typically set to 2*r to balance the update magnitude.
Option 3 is correct because alpha scales the weights to ensure the update magnitude remains consistent as you experiment with different ranks. Option 1 is wrong because 1 is often too small to produce meaningful change. Option 2 is wrong because 'r' is not the only factor. Option 4 is wrong because alpha is a training-time hyperparameter, not an inference-time sharpening tool.

5. What happens to the base model weights during a typical LoRA training process?

  • A.The base model weights are updated via backpropagation every step.
  • B.The base model weights are frozen and remain unchanged.
  • C.The base model weights are quantized to 4-bit and updated alongside the adapters.
  • D.The base model weights are discarded after the adapters are trained.
Show answer

B. The base model weights are frozen and remain unchanged.
Option 2 is correct; the core premise of LoRA is 'parameter efficiency' via freezing the base model. Option 1 is wrong as that would be standard fine-tuning. Option 3 is wrong because even if the base is quantized, it is frozen in QLoRA. Option 4 is wrong because the adapters require the base model for inference.

Take the full Generative AI quiz →

← PreviousSupervised Fine-tuning (SFT)Next →RLHF and DPO

Generative AI

41 lessons, free to read.

All lessons →

Track your progress

Sign in to mark lessons done, score quizzes and keep notes.

Open in the app