my-llama2-finetune / lora_qlora_deep_dive.md
RianLi's picture
Upload 8 files
fe4323b verified
# LoRA 与 QLoRA 深度解析
本文档旨在提供对 LoRA (Low-Rank Adaptation) 和 QLoRA (Quantized Low-Rank Adaptation) 的深入理解,涵盖其核心原理、技术细节、优势对比及应用场景。
## 1. LoRA (Low-Rank Adaptation) 深度解析
### 1.1 核心思想
大型语言模型(LLM)的微调通常需要更新模型的所有参数,这在计算和存储上都非常昂贵。LoRA 的核心思想是,我们不需要调整整个权重矩阵,而只需要调整一个低秩的“更新矩阵” `ΔW`
根据线性代数的原理,任何矩阵都可以通过低秩分解来近似。LoRA 假设模型在适应新任务时,其权重的变化是低秩的。因此,它将这个大的更新矩阵 `ΔW` 分解为两个小的、低秩的矩阵 `A``B` 的乘积 (`ΔW = BA`)。
- **原始权重 `W`**:保持冻结,不参与训练。
- **低秩矩阵 `A` 和 `B`**:可训练的参数。
通过这种方式,需要训练的参数量从数十亿急剧减少到数百万甚至更少。
### 1.2 工作原理
LoRA 的工作流程分为训练和推理两个阶段。
#### 训练阶段 (Training)
在训练时,输入数据会并行流经两条路径:
1. **主路径**:通过原始的、被冻结的模型权重 `W₀`
2. **LoRA 旁路**:通过可训练的低秩矩阵 `A``B`
最终的输出是这两条路径结果的简单相加。只有矩阵 `A``B` 的参数会被梯度更新。
```mermaid
graph TD
subgraph "训练阶段 (Training)"
direction LR
Input[Input x] --> W0["Frozen W₀"]
Input --> LoRA_A["LoRA A"]
W0 --> Add["+"]
LoRA_A --> LoRA_B["LoRA B"]
LoRA_B --> Add
Add --> Output[Output h]
end
style W0 fill:#f8f9fa,stroke:#adb5bd,stroke-width:2px
style LoRA_A fill:#e6f7ff,stroke:#91d5ff,stroke-width:2px
style LoRA_B fill:#e6f7ff,stroke:#91d5ff,stroke-width:2px
```
#### 推理阶段 (Inference)
训练完成后,为了实现最高的推理效率,LoRA 模块可以被“吸收”回原始权重中。
1. 计算两个低秩矩阵的乘积,得到更新矩阵 `ΔW = BA`
2.`ΔW` 加到原始权重上,得到新的合并权重 `W' = W₀ + ΔW`
在部署时,我们只使用这个合并后的新权重 `W'`,模型的结构和原始模型完全一样,因此**不会引入任何额外的推理延迟**
```mermaid
graph TD
subgraph "推理阶段 (Inference)"
direction LR
subgraph "1. Merge Weights (Offline)"
W0["Frozen W₀"] --> Add["+"]
subgraph "Trained LoRA"
B["LoRA B"] --> Multiply["*"]
A["LoRA A"] --> Multiply
end
Multiply --> Add
end
Add --> W_prime["New Merged Weight W'"]
subgraph "2. Deploy"
Input[Input x] --> W_prime_deploy["Use W' for Inference"]
W_prime_deploy --> Output[Output h = W' * x]
end
W_prime --> W_prime_deploy
end
```
### 1.3 优势总结
- **参数高效**:仅需训练极少数参数,大大降低了硬件门槛和训练成本。
- **无推理延迟**:训练后权重可以合并,推理速度与原始模型完全相同。
- **易于切换任务**:可以为不同任务训练不同的 LoRA 模块,并根据需要即时切换,而无需替换整个模型。
## 2. QLoRA (Quantized Low-Rank Adaptation) 详解
QLoRA 是 LoRA 的进一步优化,旨在将微调的内存消耗降至最低,甚至可以在单张消费级显卡上微调大型模型。
### 2.1 核心思想
QLoRA 的核心思想是:**用 4-bit 量化的、冻结的基础模型 + LoRA 模块**
它在 LoRA 的基础上引入了量化技术,将基础模型的权重从 16-bit (FP16) 或 32-bit (FP32) 压缩到 4-bit,从而极大地减少了内存占用。
### 2.2 关键技术
为了在如此低的精度下保持模型性能,QLoRA 引入了三项关键技术:
1. **4-bit NormalFloat (NF4)**:一种新的 4-bit 数据类型,理论上对于正态分布的权重数据是最优的。它能比传统的 4-bit 整数或浮点数量化方法更好地保留信息。
2. **双重量化 (Double Quantization)**:为了节省存储量化常数(用于将 4-bit 数据反量化回高精度)所需的内存,QLoRA 对这些常数本身再次进行量化。这是一种“量化的量化”,进一步压缩了内存。
3. **分页优化器 (Paged Optimizers)**:利用 NVIDIA 统一内存的特性,防止在处理长序列时可能出现的显存不足(OOM)问题。当显存不足时,它会自动将优化器状态从 GPU 内存分页到 CPU 内存。
### 2.3 优势与权衡
- **极致的内存效率**:能够在单张 24GB 或 48GB 显卡上微调 65B 参数的模型,这是前所未有的。
- **保持高性能**:通过上述技术,QLoRA 在 4-bit 精度下微调的模型性能可以媲美 16-bit 全参数微调的水平。
- **权衡**:训练速度会比标准的 LoRA 慢一些,因为涉及到量化和反量化的计算开销。
## 3. LoRA vs. QLoRA 对比
| 特性 | LoRA | QLoRA |
| :--- | :--- | :--- |
| **基础模型精度** | 通常为 FP16 / BF16 | FP4 (使用 NF4) |
| **主要优化目标** | 减少可训练参数量 | 极致压缩总内存占用 |
| **内存消耗** | 中等 | 非常低 |
| **训练速度** | 较快 | 相对较慢 |
| **推理性能** | 无损(合并后) | 无损(合并后) |
| **适用场景** | 资源相对充足,追求训练速度 | 资源极其有限,追求最大模型微调 |
## 4. 应用场景
- **选择 LoRA**
- 当你有足够的 VRAM(例如,A100 40GB/80GB)来加载 16-bit 模型时。
- 当你对训练速度有较高要求时。
- 快速迭代和实验不同任务的微调。
- **选择 QLoRA**
- 当你的 VRAM 非常有限(例如,RTX 3090/4090 24GB)但仍想微调大型模型时。
- 对内存效率的要求高于对训练速度的要求。
- 在个人电脑或消费级硬件上进行模型微调。
通过理解这两者的原理和差异,您可以根据自己的硬件资源和项目需求,做出最合适的微调策略选择。