馃摎 Fine-Tuning Series Articles
Understanding the Development and Evolution of Fine-Tuning Technology
Estimated reading time: 5 minutes
With the widespread application of large-scale Transformer models (such as GPT, LLaMA, ViT), the computational and storage costs of fine-tuning large models have become limiting factors. LoRA, as a Parameter-Efficient Fine-Tuning (PEFT) technique, effectively reduces resource consumption by only fine-tuning the incremental parts through low-rank matrix decomposition.
This article will analyze the training principles and advantages of LoRA step by step, helping you quickly grasp the core mechanisms of LoRA.
1. Introduction to LoRA
LoRA (Low-Rank Adaptation) is a parameter-efficient fine-tuning method for large models, with the core idea being:
路Freezing most of the pre-trained model parameters and only performing incremental training on low-rank matrices, significantly reducing training and storage costs;
路Applicable to large language models (LLM), visual Transformers (ViT), and other large-scale deep models.
2. Detailed Steps for LoRA Training
1. Freeze Pre-trained Model Parameters
Traditional fine-tuning requires adjusting the entire Transformer weights, while LoRA only freezes the original model parameters, avoiding the overhead of full backpropagation.
for param in model.parameters(): param.requires_grad = False # Freeze all parameters
Advantages: Significantly reduces training computation and memory requirements.

2. Replace Fully Connected Layers in Transformer Attention Layers
In Transformers, the computation of queries (Q), keys (K), and values (V) is typically achieved through linear layers:

LoRA does not directly train the original weights
, but performs low-rank decomposition on the increments:

Where:
路
Size is
(low-rank matrix),
路
Size is 

路
Greatly reduces training parameters.

Code example:
import torch.nn as nn
class LoRALinear(nn.Module): def __init__(self, in_features, out_features, rank=4, alpha=32): super().__init__() self.rank = rank self.alpha = alpha
self.W = nn.Linear(in_features, out_features, bias=False) self.W.requires_grad_(False) # Freeze original weights
self.A = nn.Linear(in_features, rank, bias=False) # d 脳 r self.B = nn.Linear(rank, out_features, bias=False) # r 脳 d
nn.init.kaiming_uniform_(self.A.weight, a=5**0.5) nn.init.zeros_(self.B.weight) # B zero initialization to prevent disturbance of original weights
def forward(self, x): return self.W(x) + self.alpha * self.B(self.A(x))
3. Train Only Low-Rank Matrix Parameters
optimizer = torch.optim.AdamW([ {'params': model.lora_A.parameters()}, {'params': model.lora_B.parameters()}], lr=1e-4)
Only train
and
, freezing all parameters of the original model, significantly reducing computation.

4. Merge Weights After Training Completion
After training, the incremental weights can be directly added to the original weights:

Advantages of merging:
路No additional computational overhead during inference;
路Easy deployment without the need to retain additional parameter structures.

5. Selection During Inference Phase
路Maintain LoRA structure: Suitable for dynamic switching of multiple tasks, saving storage;
路Merge weights: Suitable for efficient inference on a single task, avoiding additional computation.
Example merge code:
model.W_Q.weight.data += model.B.weight @ model.A.weight
3. Comparison of LoRA and Traditional Fine-Tuning

LoRA is particularly suitable for:
路Fine-tuning large-scale Transformers (such as GPT, LLaMA, ViT);
路Rapid switching and storage optimization for multi-task models;
路Resource-constrained environments, such as mobile and edge computing.
4. The Role of LoRA in Transformers
LoRA primarily acts on the linear layers of queries (Q), keys (K), and values (V) in Multi-Head Attention, which are the most critical parameters for fine-tuning.
5. Example Code for LoRA Training
import torch
import torch.nn as nn
import torch.optim as optim
class LoRAModel(nn.Module): def __init__(self, d, r=4, alpha=32): super().__init__() self.W = nn.Linear(d, d, bias=False) self.W.requires_grad_(False)
self.A = nn.Linear(d, r, bias=False) self.B = nn.Linear(r, d, bias=False)
nn.init.kaiming_uniform_(self.A.weight, a=5**0.5) nn.init.zeros_(self.B.weight)
self.alpha = alpha
def forward(self, x): return self.W(x) + self.alpha * self.B(self.A(x))
model = LoRAModel(d=512, r=4).cuda()
optimizer = optim.AdamW([ {'params': model.A.parameters()}, {'params': model.B.parameters()}], lr=1e-4)
for epoch in range(10): x = torch.randn(32, 512).cuda() y = model(x).sum() y.backward() optimizer.step() optimizer.zero_grad() print(f"Epoch {epoch}: Loss={y.item()}")
6. Conclusion
LoRA effectively reduces the number of training parameters and computational resource consumption by performing low-rank decomposition on the incremental weights of the Transformer attention layers. It adopts freezing the parameters of large models and only training low-rank matrices, reducing storage and computational overhead. Moreover, LoRA supports efficient fine-tuning of large language models and visual Transformers, balancing multi-tasking and rapid inference.