LoRA (Low-Rank Adaptation) 的原理?为什么它能减少显存占用?
LoRA (Low-Rank Adaptation) 是一种用于高效微调大型语言模型(LLM)的技术。简单来说,它通过冻结预训练模型的权重,并在模型的各层中注入可训练的低秩分解矩阵,从而大大减少了下游任务的可训练参数数量。
以下是关于 LoRA 原理及其为何能减少显存占用的详细解释:
一、 LoRA 的基本原理
LoRA 的核心思想基于一个假设:模型在适应特定任务时,其权重的更新量()具有“低秩”(Low-Rank)特性。 也就是说,虽然模型参数矩阵很大,但真正起作用的、需要改变的参数其实可以用两个很小的矩阵相乘来近似。
1. 数学表达
假设预训练模型中的某个权重矩阵为 (维度为 )。在全量微调中,我们需要更新整个 ,即 。
在 LoRA 中,我们将 分解为两个低秩矩阵 和 的乘积:
- :维度为
- :维度为
- :秩(Rank),是一个远小于 和 的超参数(例如 )。
2. 训练过程
- 前向传播:输入数据 同时经过原始权重 和 LoRA 支路 ()。
输出是两者的叠加。 - 反向传播:冻结 (不计算梯度,不更新),只计算 和 的梯度并更新这两个小矩阵。
3. 初始化
通常, 使用高斯分布随机初始化, 初始化为全 0。这样在训练开始时,,保证了模型初始状态与预训练模型完全一致。
二、 为什么 LoRA 能大幅减少显存占用?
显存(VRAM)在训练过程中主要被以下四部分占用:
- 模型权重(Model Weights)
- 梯度(Gradients)
- 优化器状态(Optimizer States)
- 激活值(Activations)
LoRA 主要通过减少梯度和优化器状态的存储需求来降低显存。
1. 极少的“优化器状态”占用(最关键点)
在现代大模型训练中(通常使用 AdamW 优化器),优化器状态是显存占用的“大头”。Adam 优化器需要为每一个可训练参数维护两个状态(一阶动量和二阶动量)。
- 全量微调:如果模型有 个参数,优化器状态需要保存 个浮点数。对于一个 7B 的模型(FP16),光优化器状态就需要约 28GB 显存。
- LoRA 微调:由于冻结了 ,我们只需要为 和 维护优化器状态。因为 很小,LoRA 的参数量通常只有原模型的 0.1% 到 1%。这意味着优化器状态占用的显存几乎可以忽略不计。
2. 减少了“梯度”存储
- 全量微调:需要计算并存储所有参数的梯度(与模型权重大小相同)。
- LoRA 微调:只需要计算并存储 和 的梯度,原始大矩阵 不需要梯度。这又节省了大量的显存。
3. 模型权重本身的显存(部分节省)
虽然在推理时我们需要加载完整的 ,但在训练时,由于 是冻结的,我们可以将其量化(例如使用 QLoRA 技术量化为 4-bit),进一步大幅降低 占用的显存,而 和 保持高精度(FP16/BF16)进行训练。
三、 举个直观的例子
假设你有一个 的权重矩阵(100万参数)。
全量微调:
- 你需要更新 1,000,000 个参数。
- Adam 优化器需要存 2,000,000 个状态值。
- 总负担:极重。
LoRA ():
- 矩阵是 = 8,000 参数。
- 矩阵是 = 8,000 参数。
- 总共只需更新 16,000 个参数。
- 对比:1.6万 vs 100万。参数量减少了 98.4%,显存占用随之大幅下降。
四、 总结 LoRA 的优势
- 显存占用低:单卡即可微调 7B、13B 甚至更大的模型。
- 训练速度快:计算梯度的参数变少了,反向传播计算量减少(尽管前向传播略微增加了一点点计算量,但总体训练通常更快)。
- 推理无延迟:训练完成后,可以将 的结果加回到 中,得到一个新的 。推理时直接使用 ,结构与原模型完全一样,没有任何额外的推理耗时。
- 易于切换:保留一个底座模型 ,可以为不同的任务训练不同的 LoRA 模块(几十 MB 大小),运行时根据任务动态替换 LoRA 模块即可。