A Note on LoRA
- 摘要
- Additional Insights
- Practical Improvements
- Looking Ahead
摘要
LoRA已成为一种首选的方法,用以高效地适应大型语言模型(LLM),其简便性和有效性令人瞩目。本文档扩展了原始LoRA论文,提供了最初未讨论的新视角,并展示了一系列在规模化部署LoRA时的见解。在不引入新实验的情况下,作者旨在提高对LoRA的理解和应用。
Additional Insights
On Comparison
尽管LoRA原始论文与各种替代方法进行了比较,但它并没有完全解释为什么作者要以这种方式设计LoRA,或者它是如何解决其他方法中产生的挑战的。
回到2020年,主流的参数高效适配技术是Adapter [1]。这种方法在每个Transformer [2]层中顺序集成两个适配模块,一个在注意力模块之后,另一个在前馈模块之后。这不仅会导致额外的推理延迟,特别是在LoRA研究中强调的小批量大小情况下,而且还会导致网络深度的显著增加。作者从经验上观察到,这种增加通常会导致训练不稳定。特别是对于某些任务或数据集,当使用96层GPT-3模型[3]时,实现训练收敛变得具有挑战性。增加深度的问题部分启发作者考虑以宽度而不是深度扩展网络,这为LoRA的设计奠定了基础,LoRA通过并行扩展权重与Adapter的顺序方法形成对比。
大约在同一时间,由Yang和Hu等人[2]领导的另一个关于超参数转移(HPT)的项目,证明了在模型的宽度上转移超参数的实用性。然而,尝试沿模型的深度应用HPT则不太成功。这进一步证实了LoRA所采用的并行宽度扩展网络的合理性,而不是像Adapter那样的顺序扩展。实际上,缺乏关于模型适配或超参数转移在深度方面的困难进行全面的理论或证据。这就是作者在最初的LoRA论文中最初没有讨论这些观点的原因之一。
在作者探索LoRA的同时,作者还同时研究了Prefix Tuning [1]和Prompt Tuning [1]。尽管Prefix Tuning提供了一种新颖的方法,但它减少了模型的上下文长度,这是一个重大限制。相比之下,尽管Prompt Tuning显示出潜力,但在作者的测试中,它在不同的数据集上提供了不一致的结果。这强调了输入 Level 的修改可能不足以确保在多样化应用中的稳定性和一致性,而模型内部结构的变化至关重要。
LoRA的特点是在矩阵 Level 实现适配,与Adapter添加额外层的方法相比,这一方法更为简化。这种粒度 Level 的适配使LoRA具有灵活性,可适用于各种模块,包括Transformer注意力层中的不同矩阵、前馈网络(FFN)块中的全连接层,甚至嵌入层。这使得LoRA广泛适用于任何依赖矩阵计算的模型。
On Motivation
从基础设施的角度探索高效微调的主要初衷之一是,由于模型权重和优化状态的传输成本,网络负担相当大,特别是在跨区域网络上。这类问题通常在保存和加载预训练权重时出现。虽然缓存静态预训练模型的权重可以减少微调时重新下载权重的需要,但支持持续微调或恢复先前暂停的实验则经常需要重新获取模型权重。此外,对于需要跨多个节点分布式训练的大型模型,这一挑战更为严重。这也增加了权重传输过程中网络失败的风险。考虑训练一个配备了1750亿参数和FP16权重的GPT-3模型。其快照大约占用350GB,需要使用多个节点来管理权重及其优化器状态,无论是在RAM中还是通过网络存储。分布式模型的权重预训练权重可能会引入很多开销。然而,转向使用LoRA显著稳定了训练过程中的预训练权重管理,因为它只要求保存和传输相对较小的LoRA矩阵。在持续微调中,如果使用了LoRA,就不再需要下载整个模型权重,只需下载相关的LoRA矩阵,假设基础模型权重先前已经存在或被缓存(例如,从上一个运行中)。虽然最初作者认为提高训练稳定性是主要的好处,但不久作者发现,大规模部署LoRA模型进行在线推理带来了更为显著和相关的优势。作者将在后续章节中详细解释这一点。
On FFN
原始的LoRA论文主要关注注意力层,对 Transformer 中的前馈网络(FFN)模块的影响进行了有限的探讨[20]。最初,作者在使用LoRA时遇到了FFN性能的不一致问题,这导致了对进一步FFN研究的兴趣减少。然而,在发表原始论文几个月后,作者识别并修正了LoRA FFN实现中的一个错误。随后的广泛实验揭示了将LoRA应用于FFN可以是有效的,并且通常能够补充基于注意力的LoRA。尽管如此,考虑到LoRA额外的内存需求,基于注意力的LoRA通常在内存限制下提供更高的效率。以下作者提供了更多关于在 Transformer 中放置LoRA的见解。
Practical Improvements
以下是过去几年在生产环境中广泛部署使用LoRA训练的模型所获得的经验和实践总结。
Placement
LoRA的灵活性使得它能够应用于执行矩阵乘法操作的多种模型架构中。作者的洞察主要来自于在NLP任务中将LoRA应用于Transformer中,其放置位置的选择可以显著影响训练结果。
LoRA的最佳放置位置高度依赖于数据集和模型架构,模型的大小是一个关键因素。虽然在大多数情况下,将LoRA统一应用于所有矩阵会产生最好的训练结果,但作者通常通过选择性地将LoRA应用于矩阵的子集来达到可比较的性能。最佳选择因任务和架构而异。对于一些较大规模的数据集,特别是那些大规模的,LoRA与全量微调之间的性能差距无法完全弥合。这表明有必要针对每种独特情况进行定制实验。
根据作者的经验,仅将LoRA应用于注意力层提供了最稳定性,并减轻了发散的风险,尽管这需要多个训练周期以达到最佳性能。下一个有效的LoRA应用目标是嵌入矩阵,特别是对于较小规模的模型,这些矩阵占参数的较大比例。当LoRA应用于未嵌入矩阵时,通常将LoRA添加到嵌入矩阵中会变得多余。将LoRA整合到全连接(MLP)层中可以进一步增强模型性能。至于超参数,作者观察到默认值通常对LoRA训练表现良好,然而,当LoRA应用于矩阵的小子集时,需要更高的学习率。总的来说,调整LoRA的位置可以保持模型容量、适应速度和过拟合风险之间的平衡。
研究将LoRA应用于MoE(混合专家)模型时,作者发现,在许多设置中,单独对每个专家应用LoRA可以提高性能。然而,这种方法显著增加了内存使用,使其成本效益降低。作者发现,将LoRA应用于路由矩阵仅对某些设置有利,效果有限。
LoRA的有效性还受到基础模型大小的影响。随着模型规模的增加,使用较大LoRA秩的好处更快地饱和,并且最有效的LoRA设置与全量微调之间的性能差距缩小。这建议在考虑增加LoRA秩之前,尽可能多地应用LoRA到不同类型的矩阵上,并在内存约束下进行。通过利用一些技术,例如在LoRA中跨不同的矩阵共享相同的矩阵,可以实现进一步的内存优化,例如在Transformers中的注意力矩阵、和。
总之,对于LoRA的放置没有一劳永逸的策略。作者的经验提倡逐步的方法:从注意力矩阵开始,然后是嵌入矩阵,接着是全连接(MLP)矩阵,最后将LoRA应用于所有矩阵,同时增加其秩,直到达到所需的性能。这种方法在模型质量、训练时间和推理期间的内存消耗之间进行了权衡。
Inference
先前的研究通常认为LoRA在提高训练过程效率方面发挥了作用。然而,当作者大规模地在生产中应用LoRA时,作者发现其更具影响力的在于LoRA的性价比高的在线服务。尤其是通过服务非合并权重的LoRA模型,可以极大地降低服务额外LoRA模型的开销。
通常,有三种主要方法可以为推理服务训练好的LoRA模型。第一种是将LoRA权重与基本权重合并,生成与基础模型格式相同的预训练权重。由于在推理过程中不需要额外的操作,这种方法可以提供与基础模型相比零额外的推理延迟。然而,除非用例对推理延迟极为敏感,且需要在大量GPU上部署相同的模型,使得在不同LoRA模型之间共享GPU的可替代性不重要,否则作者在生产中很少采用这种方法。否则,这种方法有几个缺点。首先,在部署时传输完整的模型权重会引入大量的网络开销。其次,它会在部署时造成架构不匹配,因为训练时模型使用的是合并之前的独立LoRA权重路径。它还可能引入数值不稳定,尤其是在使用4位[1]等低精度格式时,因为权重的合并是有损且非平凡的,例如,通常需要重新量化。
一种直接的选择是以非合并形式服务结果LoRA模型,即在推理图中明确存在delta LoRA权重。这种方法允许单一基础模型动态地与多个delta LoRA权重配对,即多个模型。由于基础模型的权重保持不变,相同的GPU可以保持它们在内存中,只需交换计算图的LoRA部分或一次性加载多个LoRA权重,并 Mask 除当前选择权重之外的所有权重。对于每个需要不同LoRA模型的新请求,这种方法允许进行快速的权重交换操作以服务新的LoRA模型。尽管LoRA的delta权重较小,但交换它们仍然可能对在线服务引入明显的开销,影响延迟、吞吐量和服务成本。
第三种选择是在同一组GPU上通过共享端点服务多个模型,即LoRA权重,将传入请求路由到正确的底层delta LoRA权重。这种设计可以使得生产服务一次性服务成千上万个基于相同基础模型的LoRA模型。这种设计的实现还可以允许一批请求指向不同的LoRA权重,这些权重可以在前向传递过程中动态选择。进一步优化技术,如缓冲和批量处理传入请求,可以带来显著的速度提升。由于大多数推理操作仍然受内存限制,批量处理请求是充分利用GPU资源的关键,可以显著降低成本并提高总体吞吐量。
下面作者描述一种方法,可以同时服务多个LoRA模型,支持指向多个LoRA模型的请求,而无需交换LoRA权重,同时保持与指向单一模型的请求相当的延迟。作者首先将所有LoRA模型中每个共享基础层的LoRA权重组合成一系列堆叠张量,每个基础层一个。在处理指向多个LoRA模型的批量请求时,作者定义了一个批量路由 Mask ,将权重1分配给堆叠LoRA矩阵中目标LoRA模型权重的索引,而将其他部分置零。作者实现了一组支持批量路由 Mask 与堆叠LoRA权重相乘的 Kernel ,允许高效的前向传递,开销很小。这种方法类似于Switch Transformer[14]中的FFN层的路由和专家混合(MoE),可以同时高效地批量服务指向大量LoRA模型的请求。这样的系统帮助作者在生产规模上服务LoRA,极大地降低了一个新LoRA模型额外的延迟和成本。最近的一项工作,S-LoRA[15],针对这种情况提出了一个同样有效的解决方案,并进行了一些优化。
Additional Explorations
作者还研究了除主要关注点之外的多项方法论,但这些探索并未带来显著的结果。
一项值得注意的调查涉及实现了一种自适应版本的LoRA,其中秩维度在训练期间为每个层和矩阵动态确定。尽管这种方法通常有助于提高模型的品质,但它受到训练时间增加和推理时基础设施挑战的限制。特别是,这种方法导致内存碎片化水平更高,推理时产生了更大的开销。对于具有不同LoRA维度性的模型,批量处理LoRA请求成了一个进一步的问题。近期开发的S-LoRA [15] 可能提供了解决这些挑战的方法,暗示了未来采用自适应LoRA的潜力。
作者还探索了通过各种技术增强基本LoRA,例如类似于DenseNet [17] 的非线性 [16],但仅限于LoRA权重,将LoRA扩展到MoE LoRA [18],或将LoRA与其他参数高效训练技术 [19] 结合。
尽管某些方法在某些数据集上提高了结果,但它们增加的复杂性阻碍了将LoRA与基础模型集成的简便性。当模型大小足够大时,作者的观察表明,添加到LoRA的非线性并没有实质性地提升性能,而MoE LoRA由于额外的内存需求不够成本效益。
正如作者最初的出版物所概述的,作者尝试将LoRA与其他技术(如前缀调整和提示调整)结合使用,鉴于它们在结构增强上的正交性质。然而,作者最终更倾向于仅使用LoRA的简单性和可维护性,考虑到它对未来扩展的简便性以及同时探索将LoRA应用于不同矩阵的详细描述,如2.1节所述。
Looking Ahead
尽管LoRA及其它参数高效的微调方法广受欢迎并具有多种优势,但在研究和生产中仍有很大提升空间。
首先,当基于LoRA权重的基础模型发生改变或更新时,当前的方法论将需要重新训练所有LoRA模型,这降低了该方法的有效性。找到一个针对这一问题的可行解决方案仍然是一个难题,这复杂化了在基础模型需要每月或每年更新时,维护那些利用众多LoRA模型的服务。
第二,尽管LoRA在推理过程中通常表现优于其他方法,但在训练过程中仍然相对较慢且成本高昂,特别是在大规模模型上。初步尝试在不使用反向传播的情况下创建LoRA参数[14]显示出潜力,但还不足以在实际中使用。其他研究[12][13]探索了从预先存在的LoRA权重发展新的LoRA模型,而不是从零开始。为了在生产环境中提高不同任务的品质和适应性,需要在LoRA合成方面进行进一步创新。
量化感知训练的兴起带来了新的复杂性。虽然低精度训练与LoRA结合[1]是使LoRA能够在低内存GPU上运行的重要进展,但它也量化了模型权重,这可能会降低性能。最近的研究[11][14]尝试通过将量化差异整合到LoRA的初始权重中来弥合这一差距。这些结果是初步的,进一步研究至关重要,尤其是随着量化训练即将普及。
尽管LoRA源自对语言建模任务的研究,但它已被成功应用于其他模态的模型和任务,特别是在计算机视觉任务中,例如应用到扩散模型[15]。进一步研究将LoRA的简便性和有效性与这些方法固有的独特机制相结合,例如扩散模型中的多步去噪,很可能会带来激动人心的进展。