用途
本文旨在为希望高效微调大语言模型(LLM)的读者提供基于数百次实验的实用技巧。LoRA(Low-Rank Adaptation)是一种广泛使用且有效的技术,用于高效训练自定义 LLM。对于对开源 LLM 感兴趣的人来说,这是值得熟悉的关键技术。文章基于作者与 Lightning AI 同事共同维护的开源 Lit-GPT 仓库进行的 LoRA 实验,讨论了从实验中得出的主要经验,并回答了相关常见问题。
主要能力
文章总结了一系列主要发现,包括:尽管 LLM 训练具有固有随机性,但多次运行的结果仍然非常一致;QLoRA 在 GPU 内存受限时可能值得权衡,它节省 33% 内存但增加 39% 运行时间;微调 LLM 时优化器选择不应是主要关注点,AdamW、带调度器的 SGD 或 AdamW 带调度器结果差异很小;Adam 虽常被视为内存密集型优化器,但对 LLM 峰值内存需求影响不大;对于静态数据集,多轮训练可能无益甚至因过拟合而恶化结果;使用 LoRA 时应应用于所有层,而不仅是 Key 和 Value 矩阵;调整 LoRA 秩(rank)和 alpha 值很重要,常用启发式是 alpha 设为秩的两倍;7B 参数模型可在单 GPU(14 GB RAM)上几小时内高效微调;静态数据集下,LLM 无法在所有基准任务上表现优异,需要多样数据源或 LoRA 可能不是理想工具。
文章还回答了十个常见问题:数据集重要性、LoRA 是否适用于领域适应、如何选择最佳秩、LoRA 是否需要所有层、如何避免过拟合、其他优化器、影响内存的其他因素、与全量微调和 RLHF 的比较、LoRA 权重能否合并、逐层最优秩适应。
使用方式
文章介绍 LoRA 的基本原理:在训练中,权重更新为 W_updated = W + ΔW,传统方法需要计算完整的 ΔW 矩阵,计算和内存密集。LoRA 将 ΔW 分解为两个较小矩阵 A 和 B 的乘积(ΔW = AB),直接学习分解表示,从而节省资源。例如,若 ΔW 有 10,000 行和 20,000 列(200,000,000 参数),选择秩 r=8 时,A 为 10,000×8,B 为 8×20,000,共 240,000 参数,减少约 830 倍。
文章提供了具体实验细节:默认 LoRA 使用 16 位 brain floating point 精度时,训练时间 1.85 小时,内存 21.33 GB;QLoRA 使用 4 位 Normal Floats 时,训练时间 2.79 小时,内存 14.18 GB。在 7B Llama 2 模型上,使用 AdamW 和 LoRA 默认设置(r=8)需要 14.18 GB GPU 内存,使用 SGD 需要 14.15 GB,差异微小(0.03 GB)。当 r=256 时,差异更明显:AdamW 为 17.86 GB,SGD 为 14.46 GB。
对于 LoRA 层应用,文章指出仅对 Key 和 Value 权重矩阵启用 LoRA 时,7B Llama 2 模型有 4,194,304 个可训练参数;若对所有额外层(Query、投影层、多头注意力块之间的线性层、线性输出层)启用,可训练参数增加 5 倍至 20,277,248,内存需求增至 16.62 GB,但可能显著提高建模性能。
超参数方面,文章提到 LoRA 引入缩放系数,涉及秩 r 和 alpha。常用经验是 alpha = 2×rank。实验中使用 r=8 和 alpha=16(2 倍缩放)。但作者发现,在特定模型和数据集组合中,r=256 和 alpha=128(0.5 倍缩放)性能更好。作者尝试了 r=32、64、128、512,但为清晰省略了结果,因为 r=256 表现最佳。
适用场景
文章适用于希望微调自定义 LLM 的研究人员和开发者,特别是在 GPU 内存有限的情况下。LoRA 允许在单个 GPU 上微调 7B 参数模型,例如使用 QLoRA 最佳设置(r=256 和 alpha=512)需要 17.86 GB 内存(AdamW),在 A100 上对 50k 训练示例(Alpaca 数据集)约需 3 小时。
限制
文章指出,对于静态数据集,多轮训练(如 2 个 epoch)会导致性能下降,可能由于过拟合。在 50k 示例的 Alpaca 指令微调数据集和 1k 示例的 LIMA 数据集上均观察到相同现象。此外,Alpaca 是合成数据集,由旧版 ChatGPT 生成,可能不是当今最佳标准。数据质量可能至关重要。文章仅探索了两种 LoRA 层设置(仅 Query 和 Value 矩阵,或所有层),其他组合值得未来研究。LoRA 的秩和 alpha 选择可能需要实验,alpha=2×rank 并不总是最佳。文章未提供所有实验细节,部分内容可能需参考其他文章。