跳转至

七:模型微调:LoRA 与 AdaLoRA

来源:http://mp.weixin.qq.com/s?__biz=MzYyNTk3Njg1NA==&mid=2247483823&idx=1&sn=22c2c07ea57c98ec76e99ba0f4c0b8ec&chksm=f01eb2d6c7693bc09a76bad40ce902a515709cf080bbc5000cf272074e7958f9c5cb4ea24192#rd

1. 学习定位

模型微调的目标是让预训练模型适配下游任务、领域数据或特定输出格式。大模型参数规模很大,全量微调成本高、显存占用大、保存多个任务版本也昂贵,因此参数高效微调 PEFT 成为常用方案。 第七天重点是 LoRA 和 AdaLoRA。LoRA 是最常见的大模型参数高效微调方法之一,核心是冻结原模型权重,只训练低秩增量矩阵。AdaLoRA 在 LoRA 基础上进一步根据参数重要性自适应分配 rank 预算。 本日知识链路:

预训练模型
-> 下游任务适配需求
-> 全量微调成本高
-> PEFT 只训练少量参数
-> LoRA 用低秩矩阵表示权重增量
-> 冻结 W,只训练 A/B
-> 训练后可合并到原权重
-> AdaLoRA 自适应给重要模块分配更多 rank
面试中 LoRA 常被追问: - LoRA 的公式是什么。

  • 为什么低秩更新有效。

  • LoRA 参数量如何计算。

  • LoRA 的 rank、alpha、dropout 分别是什么。

  • LoRA 应该加到哪些模块。

  • LoRA 和全量微调、Adapter、Prefix Tuning 有什么区别。

  • LoRA 训练和推理时如何处理权重。

  • LoRA merge/unmerge 有什么意义。

  • AdaLoRA 如何自适应分配 rank。

2. 模型微调的基本范式

预训练模型学习通用语言能力,但具体业务或任务通常需要微调。常见微调范式包括:

全量微调:
  更新模型所有参数。

部分层微调:
  冻结大部分层,只训练部分层或 task head。

参数高效微调 PEFT:
  冻结原模型,只训练少量新增参数或低秩增量。

Prompt/Prefix 类方法:
  不改原权重,学习连续提示向量或前缀键值。
全量微调表达能力强,但显存、训练成本和存储成本高。PEFT 更适合多任务、多领域、资源有限或需要快速迭代的场景。

3. 全量微调的成本

全量微调需要训练所有参数。以 7B 模型为例,仅参数本身在 bf16 下约需要:

7B * 2 bytes ≈ 14 GB
训练时还需要梯度、优化器状态、激活等显存。Adam 优化器通常还要保存一阶和二阶动量,实际显存远大于参数本身。 全量微调还会带来存储成本:

每个任务保存一份完整 checkpoint
如果一个 7B 模型有几十个任务版本,存储和管理都会很重。 LoRA 的价值在于:大部分预训练权重不变,只训练和保存很小的增量参数。

4. PEFT 的核心思想

PEFT 是 Parameter-Efficient Fine-Tuning,参数高效微调。它的共同目标是减少可训练参数,同时尽量保持下游性能。 PEFT 的主要思路: - 冻结预训练模型主体。

  • 只训练少量新增参数。

  • 让新增参数影响模型输出。

  • 每个任务只保存小规模 adapter/LoRA/prompt 参数。

PEFT 的优势: - 显存更低。

  • 训练更快。

  • 多任务存储成本低。

  • 原模型权重保持不变,便于管理。

  • 部署时可按任务加载不同增量模块。

局限是:表达能力通常弱于全量微调;任务差异很大或需要深度改变模型行为时,PEFT 可能不足。

5. LoRA 的核心公式

LoRA 的全称是 Low-Rank Adaptation。它认为微调过程中权重更新 Delta W 具有低内在秩,可以用两个低秩矩阵近似。 原始线性层:

y = W x
LoRA 后:

y = W x + Delta W x
Delta W = B A * alpha / r
其中: - W 是冻结的原始权重。

  • AB 是可训练低秩矩阵。

  • r 是 rank。

  • alpha 是缩放系数。

  • alpha / r 是 LoRA scaling。

如果 W: [d_out, d_in],则通常:

A: [r, d_in]
B: [d_out, r]
Delta W = B A: [d_out, d_in]
训练时只更新 AB,不更新 W

6. LoRA 的低秩直觉

全量微调允许 W 的每个元素独立变化,参数量是:

d_out * d_in
LoRA 限制权重更新位于低秩子空间:

Delta W = B A
rank(Delta W) <= r
r << min(d_in, d_out) 时,可训练参数量大幅减少:

r * d_in + d_out * r = r(d_in + d_out)
LoRA 的经验观察是:大模型适配下游任务时,不一定需要在全参数空间中任意更新,很多有效更新可以由低秩子空间表达。

7. LoRA 参数量计算

假设一个线性层:

W: [4096, 4096]
全量训练参数:

4096 * 4096 = 16,777,216
若 LoRA rank r=8

A: [8, 4096] &nbsp; &nbsp; &nbsp;-&gt; 32,768
B: [4096, 8] &nbsp; &nbsp; &nbsp;-&gt; 32,768
total &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -&gt; 65,536
参数量约是全量的:

65,536 / 16,777,216 ≈ 0.39%
这就是 LoRA 显存和存储高效的来源。

8. LoRA 初始化

LoRA 通常希望训练开始时不改变原模型输出。因此常见初始化是:

A 随机初始化
B 初始化为 0
这样初始时:

Delta W = B A = 0
模型一开始等价于原始预训练模型。随着训练进行,BA 学习任务相关增量。 也有实现可能反过来初始化,但核心目标是让初始增量为 0 或足够小,避免破坏原模型。

9. Rank、Alpha 与 Dropout

LoRA 常见超参:

r: rank
alpha: scaling factor
lora_dropout: dropout applied before LoRA branch
target_modules: 哪些线性层加 LoRA
rank r 控制低秩子空间容量。rank 越大,可训练参数越多,表达能力越强,但显存和过拟合风险增加。 alpha 控制 LoRA 增量的缩放:

scaling = alpha / r
alpha 较大时 LoRA 分支影响更强,但过大可能不稳定。 lora dropout 是对 LoRA 分支输入做 dropout,用于正则化,尤其在数据较小场景有用。

10. LoRA Target Modules

在 Transformer 中,LoRA 通常加在线性层上,尤其是 attention 和 MLP 的投影矩阵。 常见 target modules:

q_proj
k_proj
v_proj
o_proj
gate_proj
up_proj
down_proj
不同任务和资源下选择不同: - 只加 q_projv_proj:参数更少,经典设置之一。

  • q_proj,k_proj,v_proj,o_proj:attention 适配更充分。

  • 加 MLP 投影:表达能力更强,但参数更多。

  • all-linear:几乎所有线性层都加 LoRA,能力更强,资源更多。

面试中需要能解释 target module 选择是容量、成本和任务需求之间的折中。

11. LoRA 在 Attention 中的作用

以 query projection 为例:

Q = X W_q^T
加入 LoRA:

Q = X W_q^T + X A_q^T B_q^T * alpha/r
LoRA 改变了 Q/K/V/O 等投影后的表示,从而影响 attention score、value 聚合和输出变换。 因为 attention 决定 token 间信息路由,给 Q/V 或 Q/K/V/O 加 LoRA 通常能有效适配任务。

12. LoRA 训练流程

典型 LoRA 微调流程:

1. 加载预训练模型。
2. 冻结原始模型权重。
3. 在 target modules 中注入 LoRA A/B 矩阵。
4. 只把 LoRA 参数设为 trainable。
5. 用下游数据训练。
6. 保存 LoRA adapter 权重。
7. 推理时加载 base model + LoRA adapter,或 merge 后推理。
检查可训练参数非常重要:

trainable params &lt;&lt; total params
如果误把 base model 参数也设为 trainable,就失去 LoRA 的参数高效优势。

13. LoRA Merge 与 Unmerge

LoRA 的一个重要优点是可以合并到原权重:

W_merged = W + B A * alpha/r
合并后推理可以只执行普通线性层,不需要额外 LoRA 分支,推理延迟更低。 unmerge 则是把增量从权重中移除,恢复 base weight 和 LoRA adapter 的分离状态。 部署时有两种方式: - 不 merge:灵活切换多个 LoRA adapter。

  • merge:单任务推理更简单、更快,但不便于动态切换。

14. LoRA 与全量微调对比

LoRA: - 可训练参数少。

  • 显存和存储成本低。

  • 多任务切换方便。

  • 对小数据更不容易过拟合。

  • 表达能力受 rank 和 target modules 限制。

全量微调: - 表达能力更强。

  • 可深度改变模型行为。

  • 显存、优化器状态、存储成本高。

  • 多任务版本管理成本大。

  • 更容易遗忘原能力或过拟合。

选择时要看任务规模、数据量、资源、是否需要多任务部署以及性能要求。

15. LoRA 与 Adapter 对比

Adapter 通常在 Transformer 层中插入小型瓶颈 MLP:

x -&gt; down projection -&gt; nonlinearity -&gt; up projection -&gt; x + adapter(x)
LoRA 则是在已有线性层权重上添加低秩增量:

W -&gt; W + BA
对比: - Adapter 增加新的前向模块,可能增加推理延迟。

  • LoRA 可 merge 到原权重,推理更友好。

  • Adapter 更像新增旁路网络,LoRA 更像约束后的权重更新。

16. LoRA 与 Prompt/Prefix Tuning 对比

Prompt/Prefix Tuning 学习连续提示向量,不直接改模型权重。

Prompt Tuning:
&nbsp; 学习输入 embedding 前面的 soft prompt。

Prefix Tuning:
&nbsp; 为每层 attention 学习 prefix key/value。

LoRA:
&nbsp; 学习线性层权重的低秩增量。
Prompt/Prefix 参数量可以更少,但表达能力和任务适配能力有时弱于 LoRA。LoRA 通常是性能、成本和工程便利之间非常强的折中。

17. AdaLoRA 的动机

普通 LoRA 给所有目标矩阵设置相同 rank 或手动指定 rank。但不同层、不同模块对任务的重要性不同。 例如某些层的 Q/V 更新很重要,另一些层可能不需要太大 rank。固定 rank 会造成: - 重要模块容量不足。

  • 不重要模块浪费参数预算。

AdaLoRA 的目标是:在固定参数预算下,自适应把更多 rank 分配给更重要的权重更新。

18. AdaLoRA 的核心思想

AdaLoRA 使用可分解形式表示增量,并根据重要性分数动态裁剪或分配 rank。 直觉流程:

1. 为多个模块分配初始较高 rank。
2. 训练过程中估计各 rank 方向的重要性。
3. 在预算约束下保留重要方向,裁剪不重要方向。
4. 最终得到不同模块、不同矩阵的自适应 rank。
相比普通 LoRA,AdaLoRA 不要求所有模块用相同 rank,而是学习 rank 分配。 面试中不必完整复现所有数学细节,但要讲清:AdaLoRA 关注“参数预算如何分配”,LoRA 关注“用低秩矩阵表示增量”。

19. LoRA 超参选择

常见经验: - rank r=4/8/16/32/64 都常见。

  • alpha 常设为 r2r 或其他经验值。

  • 小数据可加 lora_dropout,例如 0.05 或 0.1。

  • target modules 越多,能力越强,成本越高。

  • 学习率通常可比全量微调稍大,但要结合模型和数据调试。

不要机械认为 rank 越大越好。rank 大可能提升上限,也可能增加过拟合和训练成本。

20. LoRA 数据与评测

LoRA 只是训练方法,不保证数据质量。下游效果依赖: - 指令数据质量。

  • 任务覆盖。

  • 输入输出格式一致。

  • train/dev/test 划分。

  • 是否有数据泄漏。

  • 评价指标是否与目标一致。

  • badcase 分析。

微调报告中至少应记录:

base model
dataset
template
target modules
r / alpha / dropout
learning rate
batch size / grad accumulation
epochs / steps
eval metrics
badcases

21. LoRA 常见工程问题

常见问题: - 忘记冻结 base model。

  • target module 名称写错,实际没有注入 LoRA。

  • 只保存了 adapter,推理时没加载 base model。

  • tokenizer/chat template 和 base model 不匹配。

  • LoRA rank 太低导致欠拟合。

  • rank 太高或数据太少导致过拟合。

  • merge 后继续训练导致权重状态混乱。

  • 多个 LoRA adapter 叠加时 scaling 和任务冲突。

  • 量化模型上训练 LoRA 时 dtype 处理不当。

排查时先检查:

print trainable parameters
inspect target modules
decode training samples
compare base vs lora outputs
verify adapter loading

22. 面试中的核心表达

第七天内容可以压缩为:

LoRA 是一种参数高效微调方法,冻结原模型 W,只训练低秩增量 Delta W。
公式是 W' = W + BA * alpha/r。
如果 W 是 d_out x d_in,LoRA 参数量是 r(d_in + d_out),远小于 d_out d_in。
LoRA 通常加到 attention 和 MLP 的线性投影层,可训练参数少,训练和存储成本低。
训练后 LoRA 可以 merge 到原权重,降低推理开销。
rank、alpha、dropout、target modules 是关键超参。
AdaLoRA 在 LoRA 基础上自适应分配 rank,把参数预算给更重要的模块或方向。

23. 参考资料

  • LoRA: Low-Rank Adaptation of Large Language Models: https://arxiv.org/abs/2106.09685

  • AdaLoRA: Adaptive Budget Allocation for Parameter-Efficient Fine-Tuning: https://arxiv.org/abs/2303.10512

  • Hugging Face PEFT LoRA Documentation: https://huggingface.co/docs/peft/main/en/package_reference/lora

  • Hugging Face PEFT Conceptual Guides: https://huggingface.co/docs/peft/main/en/conceptual_guides/adapter

  • LoRA 原论文:https://arxiv.org/pdf/2106.09685

  • AdaLoRA 原论文:https://arxiv.org/pdf/2303.10512

  • LoRA 作者讲解:https://www.bilibili.com/video/BV1sT4y1t7Cu/

            预览时标签不可点
    

    <div class="