====== LoRA ====== LoRA(Low-Rank Adaptation,低秩适配)是一种用于[[大语言模型]]和其他大型神经网络的[[参数高效微调]](PEFT)方法。LoRA 由 Edward J. Hu 等人于 2021 年在 Microsoft Research 提出的论文《LoRA: Low-Rank Adaptation of Large Language Models》中提出。 LoRA 的核心思想是:**冻结预训练模型原有参数,只训练少量低秩矩阵,使模型能够学习新的任务或领域知识。** 传统的[[全量微调]]需要更新模型的全部参数,而 LoRA 只增加少量可训练参数,因此显著降低显存和存储需求。 ===== 为什么需要 LoRA ===== 假设一个已经训练好的 [[Transformer]] 模型拥有数十亿甚至数千亿参数。 如果对它进行全量微调: 预训练模型 → 更新全部参数 → 得到新的模型 这种方法存在几个问题: * 需要巨大的 GPU 显存。 * 训练成本高。 * 每个任务都需要保存一份完整模型。 * 多个任务会产生大量重复参数。 例如一个 70B 参数模型,如果使用 FP16 保存,仅模型参数本身就需要约: 70B × 2 bytes ≈ 140 GB 如果训练时还需要保存梯度和优化器状态,实际显存需求会远高于这个数字。 LoRA 的思路则是: 冻结原模型 → 添加少量可训练参数 → 只训练新增参数。 ===== LoRA 的核心思想 ===== LoRA 建立在一个重要假设上: **模型在适应特定任务时,并不一定需要改变完整的高维参数空间,而可能只需要学习一个低秩的参数变化。** 假设原来的权重矩阵为 W。 传统微调直接学习: W → W + ΔW LoRA 不直接训练 ΔW,而是将它表示成两个低秩矩阵的乘积: ΔW = BA 因此: W' = W + BA 其中: * W:预训练模型的原始权重,冻结。 * A:可训练的低秩矩阵。 * B:可训练的低秩矩阵。 * BA:对原模型权重的更新量。 * r:低秩矩阵的秩,通常远小于原矩阵维度。 ===== 为什么这样能够减少参数 ===== 假设原始权重矩阵: W ∈ R^(d × k) 全量微调需要训练: d × k 个参数。 LoRA 将 ΔW 分解为: B ∈ R^(d × r) A ∈ R^(r × k) 因此需要训练的参数数量变成: d × r + r × k = r(d + k) 因为: r << d, k 所以: r(d + k) << dk 例如: d = 4096 k = 4096 r = 8 原始矩阵参数量: 4096 × 4096 = 16,777,216 LoRA 参数量: 4096 × 8 + 8 × 4096 = 65,536 只需要原始矩阵约 0.39% 的参数。 ===== LoRA 的前向传播 ===== 对于输入 x,传统线性层计算: y = Wx LoRA 则变为: y = Wx + BAx 其中 W 保持冻结,A 和 B 参与训练。 实际实现中通常还会加入缩放系数: y = Wx + α/r · BAx 其中 α 是 LoRA scaling factor,r 是 LoRA rank。 因此,训练过程中实际上只有 A 和 B 的参数会更新。 ===== LoRA 初始化 ===== LoRA 通常采用特殊初始化,使模型刚开始训练时基本保持原模型的行为。 一种常见做法是: * A 使用随机初始化。 * B 初始化为 0。 这样一开始: BA = 0 因此: W' = W 模型刚开始训练时与原始预训练模型基本一致,然后随着训练逐渐学习任务相关的参数变化。 ===== LoRA 应该加在哪里 ===== 在 [[Transformer]] 中,LoRA 通常被应用于 [[Attention]] 模块中的线性投影层。 常见目标包括: * Query Projection(q_proj) * Key Projection(k_proj) * Value Projection(v_proj) * Output Projection(o_proj) 例如: Attention → Q/K/V Projection → LoRA 一些训练方案也会把 LoRA 应用于 [[Feed Forward Network]] 的线性层。 因此,“LoRA 微调”并不意味着整个模型都增加 LoRA,而是选择模型中的部分权重矩阵进行低秩适配。 ===== Rank ===== Rank(秩)是 LoRA 最重要的超参数之一。 例如: r = 4、8、16、32、64 r 越大: 参数量增加 → 模型可学习的更新空间增加 → 潜在表达能力增加。 但同时: 显存和训练成本增加 → 过拟合风险可能增加。 r 越小: 参数量减少 → 训练更加轻量。 但如果任务复杂,过低的 rank 可能限制模型适应能力。 因此,rank 本质上控制了 LoRA 参数更新的自由度。 ===== LoRA Scaling ===== LoRA 通常使用 α/r 对低秩更新进行缩放: y = Wx + α/r · BAx α 控制 LoRA 更新对原模型输出的影响程度。 因此,rank 和 scaling 并不是同一个概念: * r:控制低秩空间的维度。 * α:控制 LoRA 更新的缩放强度。 ===== LoRA Dropout ===== LoRA 还可以使用 LoRA Dropout,在输入进入低秩分支之前进行 [[Dropout]]。 例如: x → Dropout → A → B → Scaling 它可以降低训练过程中的过拟合风险。 ===== LoRA 的训练过程 ===== LoRA 微调的过程可以概括为: 预训练模型 → 冻结 W → 添加 A、B → 输入训练数据 → 前向传播 → 计算 Loss → 反向传播 → 更新 A、B。 因此训练结束后: W 不变 A、B 已经学会任务相关的信息。 这就是 LoRA 与全量微调最大的区别。 ===== LoRA 与全量微调 ===== 全量微调: 预训练模型 → 更新 W → 新模型 LoRA: 预训练模型 → 冻结 W → 学习 ΔW = BA → LoRA Adapter 两者的主要区别在于训练参数量。 全量微调的可训练参数: ≈ 模型全部参数 LoRA: ≈ 被选择的权重矩阵 × 很小的 rank 因此 LoRA 特别适合个人开发者和计算资源有限的研究环境。 ===== LoRA Adapter ===== LoRA 训练完成后,可以把 A 和 B 保存为一个独立的 [[Adapter]]。 因此: Base Model + LoRA Adapter → 微调模型 不同任务可以使用不同 Adapter: Base Model + Coding Adapter Base Model + Medical Adapter Base Model + Instruction Adapter 而不需要为每个任务保存一份完整的 Base Model。 这使 LoRA 非常适合多任务模型部署。 ===== LoRA 的合并 ===== 训练完成后,可以将 LoRA 参数合并回原始权重: W' = W + α/r · BA 这样可以得到一个普通的模型权重。 合并之后推理时不再需要额外计算 LoRA 分支。 因此 LoRA 通常存在两种使用方式: **Adapter 模式** Base Model + LoRA Adapter **Merged 模式** Base Model + LoRA → 合并后的模型 ===== LoRA 与 PEFT ===== [[PEFT]](Parameter-Efficient Fine-Tuning,参数高效微调)是一大类方法,而 LoRA 是其中最重要的方法之一。 关系可以理解为: PEFT → LoRA → [[QLoRA]] → [[Adapter]] → [[Prefix Tuning]] → [[Prompt Tuning]] 它们共同目标都是: **尽可能少地更新模型参数,同时让预训练模型适应新的任务。** ===== LoRA 与 QLoRA ===== [[QLoRA]] 是 LoRA 的进一步发展。 LoRA: 模型权重通常以较高精度加载 → 冻结 Base Model → 训练 LoRA 参数。 QLoRA: [[量化]] Base Model → 冻结量化模型 → 训练 LoRA 参数。 QLoRA 的核心论文由 Tim Dettmers 等人于 2023 年发表,题为《QLoRA: Efficient Finetuning of Quantized LLMs》。 因此: LoRA = 低秩适配 QLoRA = 量化 + LoRA QLoRA 可以进一步降低显存需求,使在消费级 GPU 上微调较大的 [[LLM]] 成为可能。 ===== LoRA 的优点 ===== * 可训练参数数量非常少。 * 显著降低训练显存需求。 * 训练成本低。 * Adapter 文件通常远小于完整模型。 * 可以为同一个 Base Model 保存多个任务 Adapter。 * 可以方便地切换不同任务。 * 通常能够取得接近全量微调的效果。 * 特别适合大语言模型的任务适配。 ===== LoRA 的局限 ===== LoRA 并不是所有场景下都优于全量微调。 * 低 rank 可能限制模型的参数更新能力。 * rank、target modules、learning rate 等超参数需要合理选择。 * 对某些需要大规模改变模型行为的任务,全量微调可能更有效。 * 不同任务之间可能产生 Adapter 之间的冲突。 * LoRA 主要学习参数更新,并不能简单等同于向模型“写入知识”。 * Adapter 过多时,部署和管理会变得复杂。 ===== LoRA 的意义 ===== LoRA 最重要的意义在于证明: **大型预训练模型的任务适应并不一定需要更新全部参数。** 通过学习低秩参数变化: ΔW = BA 就可以用极少的可训练参数改变模型行为。 这使得“大模型预训练一次,多任务使用”变得更加现实,也推动了 [[参数高效微调]] 成为大模型训练的重要技术路线。 从整个大模型发展来看,可以将训练过程理解为: 大规模预训练 → 得到 Base Model → PEFT / LoRA → 针对不同任务进行适配。 因此,LoRA 是连接[[预训练]]与[[下游任务]]的重要技术之一。 ===== 相关条目 ===== * [[参数高效微调]] * [[PEFT]] * [[QLoRA]] * [[Transformer]] * [[大语言模型]] * [[Adapter]] * [[量化]] * [[全量微调]] ===== 参考资料 ===== * Hu et al., 2021, 《LoRA: Low-Rank Adaptation of Large Language Models》 * Dettmers et al., 2023, 《QLoRA: Efficient Finetuning of Quantized LLMs》 * Houlsby et al., 2019, 《Parameter-Efficient Transfer Learning for NLP》 * Liu et al., 2022, 《Few-Shot Parameter-Efficient Fine-Tuning is Better and Cheaper than In-Context Learning》