LoRA 的 target_modules 应该如何选择?
简化版
target_modules 决定 LoRA 注入哪些线性层。只适配 q_proj/v_proj 成本最低,适合轻量实验;覆盖 q/k/v/o 能更完整改变注意力;再加入 FFN 的 gate/up/down 层会显著增加容量,适合领域或风格偏移较大的任务。
选择时要先核对模型真实模块名和权重共享,再按任务、数据规模、显存和部署方式做消融。注入越多不一定越好,可能加剧过拟合和推理开销。Embedding、LM Head 或 MoE 专家需要特别处理。
Target Modules 决定模型“哪里可以改变”,Rank 决定每个位置“可以改变多少方向”。
详细版
Transformer 层可简化为:
x -> Q,K,V projections -> attention -> O projection -> residual
-> gate/up projections -> activation -> down projection -> residual
若隐藏维度 H=4096、FFN 维度 I=11008、rank=16,给一个 H×H 投影加 LoRA 约需 16×(4096+4096)=131,072 参数;给 H×I 的 up_proj 加 LoRA 约需 16×(4096+11008)=241,664,FFN 层通常更贵。
| 注入范围 | 容量/成本 | 常见用途 |
|---|---|---|
| q,v | 最小 | 快速基线、简单格式适配 |
| q,k,v,o | 中等 | 改变完整注意力行为 |
| Attention + FFN | 较高 | 领域知识、复杂行为适配 |
| All Linear | 最高的 PEFT 范围 | QLoRA 常见通用配置 |
| Embedding/LM Head | 词汇接口 | 新 Token,但兼容复杂 |
完整版教学
1. Target Modules 为什么影响表达能力
LoRA 只改变被选层的前向映射。若任务需要重塑 FFN 中的知识和特征变换,仅改少数 Attention 投影可能容量不足。
反过来,简单输出格式或语气任务未必需要修改所有线性层。
2. Attention 各投影分别做什么
Q 影响当前位置寻找什么,K 影响内容如何被匹配,V 决定传递的信息,O 把多头结果映射回隐藏空间。
只选 q/v 是历史常见轻量配置,不代表 k/o 永远无价值;模型架构和任务会改变结果。
需要修改“关注哪些上下文”的任务可能更依赖 Q/K,需要改变传递内容或输出组合则可能从 V/O 受益。这只是机制假设,最终仍要用模块消融验证。
3. FFN 为什么常带来更强领域适配
FFN 占 Transformer 大量参数,负责逐 Token 非线性特征变换。加入 gate/up/down 投影能增加适配容量,常用于复杂领域和全线性 QLoRA。
代价是参数、优化器状态和动态 Adapter 计算明显增加,也更容易覆盖基座行为。
4. 如何查看模型真实模块名
不同模型可能叫 q_proj、query_key_value、Wqkv 或融合 QKV。不能直接复制另一个架构的字符串。
for name, module in model.named_modules():
if isinstance(module, torch.nn.Linear):
print(name, module.in_features, module.out_features)
注入后打印匹配数量和可训练参数;匹配 0 个却继续训练是常见静默错误。
5. Fused QKV 如何处理
有些模型把 Q/K/V 存在一个大矩阵中。框架可能对整个矩阵注入一份 LoRA,不能仅选 v_proj。
需要确认 Adapter 库是否支持切片 LoRA、量化层包装和张量并行分片,否则保存/加载可能不兼容。
6. All Linear 什么时候合理
QLoRA 常冻结 4-bit 基座,并给几乎所有线性层加 LoRA,增加可训练容量以逼近全量微调。
它适合数据和任务复杂、显存仍可接受的场景;小数据简单任务应先从较窄范围建立基线。
“参数高效”是相对全量微调而言,不代表 target_modules 可以无限扩展而没有统计和部署代价。
7. Embedding 与 LM Head 为什么特殊
新增 Token 需要训练对应 Embedding 行和输出层;若输入输出权重绑定,适配或保存方式要保持共享关系。
全矩阵 LoRA 可能影响整个词表,不如只训练新增行直接。量化、合并和导出时要验证 Tokenizer 长度与权重维度。
8. MoE 架构要额外注意什么
MoE 的 Attention 共享,但 FFN 分布在多个专家。对所有专家注入 LoRA 参数量会乘专家数,且冷门专家训练样本不足。
可以只适配共享层、选择部分专家或共享 Adapter,但要评估路由分布和专家负载,避免某些专家未训练。
9. 参数预算如何估算
对每个线性层 d_out×d_in,LoRA 参数为 r(d_in+d_out)。求和后再考虑 dtype、梯度和 Adam 状态。
| 状态 | 每参数近似内存(示意) |
|---|---|
| FP16 参数 | 2 bytes |
| FP16/BF16 梯度 | 2 bytes |
| FP32 Adam m,v | 8 bytes |
实际还受混合精度与优化器实现影响,应以峰值监控确认。
10. 如何设计模块消融实验
固定数据、rank、alpha、学习率和 Token 预算,比较 qv、完整 Attention、Attention+FFN。每组报告目标、通用、安全和训练/推理成本。
如果扩大模块只降低训练 Loss,却不提升未见组验证,应选更小配置。
11. 层深选择是否有意义
不仅可选模块类型,也可只适配顶部、底部或特定层。底层更多处理词法与局部特征,深层更接近任务行为,但这种分工不是绝对。
层选择适合极致参数预算,但实现和实验组合更多。先用全层同类型建立基线。
12. 部署兼容性如何约束选择
推理引擎可能只支持标准 Linear LoRA,不支持 Embedding、Conv、MoE 专家或融合层。动态多 Adapter 批处理也会限制模块布局。
训练前先做一次最小 Adapter 的保存、加载、合并、量化和目标引擎推理测试,避免训练完成才发现不能服务。
13. 常见误区与追问
- 误区:所有模型都用 q_proj/v_proj。 融合 QKV 和其他架构模块名可能完全不同。
- 误区:目标层越多效果一定越好。 容量、过拟合和部署开销同步增加。
- 误区:Rank 相同就代表不同配置参数量相同。 层数量和输入输出维度决定总参数。
- 误区:FFN 不参与领域知识适配。 FFN 是重要容量来源,复杂任务常受益。
- 误区:训练框架能运行就说明注入成功。 必须打印匹配模块和可训练参数,并检查梯度。
- 追问:小数据从哪里开始? q/v 或完整 Attention 低 rank 基线,再依据欠拟合证据扩展。
- 追问:QLoRA 为什么常选 all-linear? 基座被冻结量化,扩大低秩更新范围可增加适配容量。
14. 加强记忆
- 先查架构模块名,绝不盲抄配置。
- Attention 轻,FFN 强但贵,All Linear 容量最高。
- 参数公式:每层
r(d_in+d_out),总量对所有目标层求和。 - 特殊层:融合 QKV、Embedding/LM Head、MoE 和量化要单独验证。
- 用消融选择:固定其他变量,看目标、回归与部署成本。